summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gb/gprs_ns.c19
-rw-r--r--src/gb/libosmogb.map1
-rw-r--r--src/gsm/gsm0480.c33
-rw-r--r--src/gsm/gsm_utils.c6
-rw-r--r--src/gsm/lapd_core.c19
-rw-r--r--src/gsm/lapdm.c28
6 files changed, 75 insertions, 31 deletions
diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c
index ef937d9e..5620b3a7 100644
--- a/src/gb/gprs_ns.c
+++ b/src/gb/gprs_ns.c
@@ -917,13 +917,7 @@ struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb, void *ctx)
return nsi;
}
-/*! \brief Destroy an entire NS instance
- * \param nsi gprs_ns_inst that is to be destroyed
- *
- * This function releases all resources associated with the
- * NS-instance.
- */
-void gprs_ns_destroy(struct gprs_ns_inst *nsi)
+void gprs_ns_close(struct gprs_ns_inst *nsi)
{
struct gprs_nsvc *nsvc, *nsvc2;
@@ -935,8 +929,19 @@ void gprs_ns_destroy(struct gprs_ns_inst *nsi)
if (nsi->nsip.fd.data) {
close(nsi->nsip.fd.fd);
osmo_fd_unregister(&nsi->nsip.fd);
+ nsi->nsip.fd.data = NULL;
}
+}
+/*! \brief Destroy an entire NS instance
+ * \param nsi gprs_ns_inst that is to be destroyed
+ *
+ * This function releases all resources associated with the
+ * NS-instance.
+ */
+void gprs_ns_destroy(struct gprs_ns_inst *nsi)
+{
+ gprs_ns_close(nsi);
/* free the NSI */
talloc_free(nsi);
}
diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map
index d65819b4..7af085c5 100644
--- a/src/gb/libosmogb.map
+++ b/src/gb/libosmogb.map
@@ -38,6 +38,7 @@ bssgp_nsi;
gprs_ns_cause_str;
gprs_ns_destroy;
+gprs_ns_close;
gprs_ns_frgre_listen;
gprs_ns_frgre_sendmsg;
gprs_ns_instantiate;
diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c
index b9b3ed97..89d43c84 100644
--- a/src/gsm/gsm0480.c
+++ b/src/gsm/gsm0480.c
@@ -85,7 +85,7 @@ struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *
{
struct msgb *msg;
uint8_t *seq_len_ptr, *ussd_len_ptr, *data;
- int len;
+ int len, octet_len;
msg = msgb_alloc_headroom(1024, 128, "GSM 04.80");
if (!msg)
@@ -106,8 +106,13 @@ struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *
ussd_len_ptr = msgb_put(msg, 1);
data = msgb_put(msg, 0);
len = gsm_7bit_encode(data, text);
- msgb_put(msg, len);
- ussd_len_ptr[0] = len;
+ octet_len = len*7/8;
+ if (len*7%8 != 0)
+ octet_len++;
+ /* Warning, len indicates the amount of septets
+ * (characters), we need amount of octets occupied */
+ msgb_put(msg, octet_len);
+ ussd_len_ptr[0] = octet_len;
/* USSD-String } */
/* alertingPattern { */
@@ -127,7 +132,7 @@ struct msgb *gsm0480_create_notifySS(const char *text)
struct msgb *msg;
uint8_t *data, *tmp_len;
uint8_t *seq_len_ptr, *cal_len_ptr, *opt_len_ptr, *nam_len_ptr;
- int len;
+ int len, octet_len;
len = strlen(text);
if (len < 1 || len > 160)
@@ -173,12 +178,17 @@ struct msgb *gsm0480_create_notifySS(const char *text)
tmp_len = msgb_put(msg, 1);
data = msgb_put(msg, 0);
len = gsm_7bit_encode(data, text);
- tmp_len[0] = len;
- msgb_put(msg, len);
+ octet_len = len*7/8;
+ if (len*7%8 != 0)
+ octet_len++;
+ /* Warning, len indicates the amount of septets
+ * (characters), we need amount of octets occupied */
+ tmp_len[0] = octet_len;
+ msgb_put(msg, octet_len);
/* }; namePresentationAllowed */
- cal_len_ptr[0] = 3 + 3 + 2 + len;
+ cal_len_ptr[0] = 3 + 3 + 2 + octet_len;
opt_len_ptr[0] = cal_len_ptr[0] + 2;
/* }; callingName */
@@ -415,7 +425,7 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const
struct msgb *msg;
struct gsm48_hdr *gh;
uint8_t *ptr8;
- int response_len;
+ int response_len, octet_len;
msg = msgb_alloc_headroom(1024, 128, "GSM 04.80");
if (!msg)
@@ -424,7 +434,12 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const
/* First put the payload text into the message */
ptr8 = msgb_put(msg, 0);
response_len = gsm_7bit_encode(ptr8, text);
- msgb_put(msg, response_len);
+ octet_len = response_len*7/8;
+ if (response_len*7%8 != 0)
+ octet_len++;
+ /* Warning, response_len indicates the amount of septets
+ * (characters), we need amount of octets occupied */
+ msgb_put(msg, octet_len);
/* Then wrap it as an Octet String */
msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG);
diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c
index 9569cf32..fa77eae4 100644
--- a/src/gsm/gsm_utils.c
+++ b/src/gsm/gsm_utils.c
@@ -241,6 +241,12 @@ int gsm_septets2octets(uint8_t *result, const uint8_t *rdata, uint8_t septet_len
result[z++] = cb;
shift++;
}
+ /* To avoid the situation where the receiving entity confuses 7 binary
+ * zero pad bits as the @ character, the carriage return or <CR>
+ * character (defined in subclause 7.1.1) shall be used for padding in
+ * this situation. */
+ if (shift == 7)
+ result[z - 1] |= 0x1a;
free(data);
diff --git a/src/gsm/lapd_core.c b/src/gsm/lapd_core.c
index 116e3116..68b5e784 100644
--- a/src/gsm/lapd_core.c
+++ b/src/gsm/lapd_core.c
@@ -826,14 +826,23 @@ static int lapd_rx_u(struct msgb *msg, struct lapd_msg_ctx *lctx)
* yet received UA or another mobile (collision) tries
* to establish connection. The mobile must receive
* UA again. */
- if (!dl->cont_res && dl->v_send != dl->v_recv) {
- LOGP(DLLAPD, LOGL_INFO, "Remote reestablish\n");
- mdl_error(MDL_CAUSE_SABM_MF, lctx);
+ /* 5.4.2.1 */
+ if (!length) {
+ /* If no content resolution, this is a
+ * re-establishment. */
+ LOGP(DLLAPD, LOGL_INFO,
+ "Remote reestablish\n");
break;
}
+ if (!dl->cont_res) {
+ LOGP(DLLAPD, LOGL_INFO, "SABM command not "
+ "allowed in this state\n");
+ mdl_error(MDL_CAUSE_SABM_MF, lctx);
+ msgb_free(msg);
+ return 0;
+ }
/* Ignore SABM if content differs from first SABM. */
- if (dl->mode == LAPD_MODE_NETWORK && length
- && dl->cont_res) {
+ if (dl->mode == LAPD_MODE_NETWORK && length) {
#ifdef TEST_CONTENT_RESOLUTION_NETWORK
dl->cont_res->data[0] ^= 0x01;
#endif
diff --git a/src/gsm/lapdm.c b/src/gsm/lapdm.c
index 71045aa1..52290cbe 100644
--- a/src/gsm/lapdm.c
+++ b/src/gsm/lapdm.c
@@ -407,6 +407,11 @@ static int send_rslms_dlsap(struct osmo_dlsap_prim *dp,
switch (OSMO_PRIM_HDR(&dp->oph)) {
case OSMO_PRIM(PRIM_DL_EST, PRIM_OP_INDICATION):
+ if (dp->oph.msg && dp->oph.msg->len == 0) {
+ /* omit L3 info by freeing message */
+ msgb_free(dp->oph.msg);
+ dp->oph.msg = NULL;
+ }
rll_msg = RSL_MT_EST_IND;
break;
case OSMO_PRIM(PRIM_DL_EST, PRIM_OP_CONFIRM):
@@ -817,10 +822,10 @@ static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl)
static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl)
{
struct lapdm_entity *le = dl->entity;
- int ui_bts = (le->mode == LAPDM_MODE_BTS);
struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
uint8_t chan_nr = rllh->chan_nr;
uint8_t link_id = rllh->link_id;
+ int ui_bts = (le->mode == LAPDM_MODE_BTS && (link_id & 0x40));
uint8_t sapi = link_id & 7;
struct tlv_parsed tv;
int length;
@@ -844,9 +849,10 @@ static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl)
msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);
length = TLVP_LEN(&tv, RSL_IE_L3_INFO);
/* check if the layer3 message length exceeds N201 */
- if (length + 4 + !ui_bts > 23) {
+ if (length + ((link_id & 0x40) ? 4 : 2) + !ui_bts > 23) {
LOGP(DLLAPD, LOGL_ERROR, "frame too large: %d > N201(%d) "
- "(discarding)\n", length, 18 + ui_bts);
+ "(discarding)\n", length,
+ ((link_id & 0x40) ? 18 : 20) + ui_bts);
msgb_free(msg);
return -EIO;
}
@@ -860,13 +866,16 @@ static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl)
msg->tail = msg->l3h + length;
/* Push L1 + LAPDm header on msgb */
- msg->l2h = msgb_push(msg, 4 + !ui_bts);
- msg->l2h[0] = le->tx_power;
- msg->l2h[1] = le->ta;
- msg->l2h[2] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, dl->dl.cr.loc2rem.cmd);
- msg->l2h[3] = LAPDm_CTRL_U(LAPDm_U_UI, 0);
+ msg->l2h = msgb_push(msg, 2 + !ui_bts);
+ msg->l2h[0] = LAPDm_ADDR(LAPDm_LPD_NORMAL, sapi, dl->dl.cr.loc2rem.cmd);
+ msg->l2h[1] = LAPDm_CTRL_U(LAPDm_U_UI, 0);
if (!ui_bts)
- msg->l2h[4] = LAPDm_LEN(length);
+ msg->l2h[2] = LAPDm_LEN(length);
+ if (link_id & 0x40) {
+ msg->l2h = msgb_push(msg, 2);
+ msg->l2h[0] = le->tx_power;
+ msg->l2h[1] = le->ta;
+ }
/* Tramsmit */
return tx_ph_data_enqueue(dl, msg, chan_nr, link_id, 23);
@@ -1083,7 +1092,6 @@ static int rslms_rx_rll(struct msgb *msg, struct lapdm_channel *lc)
}
switch (msg_type) {
- case RSL_MT_UNIT_DATA_REQ:
case RSL_MT_DATA_REQ:
case RSL_MT_SUSP_REQ:
case RSL_MT_REL_REQ: