aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/gsm/gsm0808.h3
-rw-r--r--include/osmocom/gsm/gsm48.h30
-rw-r--r--src/gb/gprs_bssgp.c9
-rw-r--r--src/gb/gprs_bssgp_vty.c5
-rw-r--r--src/gsm/gsm0808.c2
-rw-r--r--src/gsm/gsm48.c47
6 files changed, 63 insertions, 33 deletions
diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h
index 5127c00..553f10d 100644
--- a/include/osmocom/gsm/gsm0808.h
+++ b/include/osmocom/gsm/gsm0808.h
@@ -21,10 +21,11 @@
#define OSMOCORE_GSM0808_H
#include "tlv.h"
+#include "gsm48.h"
struct msgb;
-struct msgb *gsm0808_create_layer3(struct msgb *msg, uint16_t netcode, uint16_t countrycode, int lac, uint16_t ci);
+struct msgb *gsm0808_create_layer3(struct msgb *msg, gsm_mnc_t netcode, uint16_t countrycode, int lac, uint16_t ci);
struct msgb *gsm0808_create_reset(void);
struct msgb *gsm0808_create_reset_ack(void);
struct msgb *gsm0808_create_clear_command(uint8_t reason);
diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h
index 1e7498a..37054b8 100644
--- a/include/osmocom/gsm/gsm48.h
+++ b/include/osmocom/gsm/gsm48.h
@@ -1,14 +1,22 @@
#ifndef _OSMOCORE_GSM48_H
#define _OSMOCORE_GSM48_H
+#include <stdbool.h>
+#include <stdlib.h>
+
#include <osmocom/gsm/tlv.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/gsm/gsm48_ie.h>
+typedef struct {
+ int16_t network_code:15; /**< MNC, 00-999. Signed to allow -1 as invalid placeholder. */
+ bool two_digits:1; /**< If true, MNC is 2 digits, otherwise 3. */
+} gsm_mnc_t;
+
/* A parsed GPRS routing area */
struct gprs_ra_id {
- uint16_t mnc;
uint16_t mcc;
+ gsm_mnc_t mnc;
uint16_t lac;
uint8_t rac;
};
@@ -21,9 +29,9 @@ const char *gsm48_cc_msg_name(uint8_t msgtype);
const char *rr_cause_name(uint8_t cause);
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
- uint16_t *mnc, uint16_t *lac);
+ gsm_mnc_t *mnc, uint16_t *lac);
void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
- uint16_t mnc, uint16_t lac);
+ gsm_mnc_t mnc, uint16_t lac);
int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi);
int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi);
@@ -37,4 +45,20 @@ int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid);
int gsm48_number_of_paging_subchannels(struct gsm48_control_channel_descr *chan_desc);
+static inline gsm_mnc_t gsm48_str_to_mnc(const char *s)
+{
+ gsm_mnc_t r;
+
+ r.two_digits = strlen(s) <= 2;
+ r.network_code = atoi(s);
+
+ return r;
+}
+
+static inline int gsm48_mnc_are_equal(gsm_mnc_t a, gsm_mnc_t b)
+{
+ return a.network_code == b.network_code &&
+ a.two_digits == b.two_digits;
+}
+
#endif
diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c
index 5ef1887..06d683a 100644
--- a/src/gb/gprs_bssgp.c
+++ b/src/gb/gprs_bssgp.c
@@ -267,9 +267,10 @@ static int bssgp_rx_bvc_reset(struct msgb *msg, struct tlv_parsed *tp,
/* actually extract RAC / CID */
bctx->cell_id = bssgp_parse_cell_id(&bctx->ra_id,
TLVP_VAL(tp, BSSGP_IE_CELL_ID));
- LOGP(DBSSGP, LOGL_NOTICE, "Cell %u-%u-%u-%u CI %u on BVCI %u\n",
- bctx->ra_id.mcc, bctx->ra_id.mnc, bctx->ra_id.lac,
- bctx->ra_id.rac, bctx->cell_id, bvci);
+ LOGP(DBSSGP, LOGL_NOTICE, "Cell %u-%0*u-%u-%u CI %u on BVCI %u\n",
+ bctx->ra_id.mcc,
+ bctx->ra_id.mnc.two_digits ? 2 : 3, bctx->ra_id.mnc.network_code,
+ bctx->ra_id.lac, bctx->ra_id.rac, bctx->cell_id, bvci);
}
/* Send NM_BVC_RESET.ind to NM */
@@ -587,7 +588,7 @@ static int fc_queue_timer_cfg(struct bssgp_flow_control *fc)
if (llist_empty(&fc->queue))
return 0;
- fcqe = llist_entry(&fc->queue.next, struct bssgp_fc_queue_element,
+ fcqe = llist_entry(fc->queue.next, struct bssgp_fc_queue_element,
list);
if (fc->bucket_leak_rate != 0) {
diff --git a/src/gb/gprs_bssgp_vty.c b/src/gb/gprs_bssgp_vty.c
index d8e1d32..f2263da 100644
--- a/src/gb/gprs_bssgp_vty.c
+++ b/src/gb/gprs_bssgp_vty.c
@@ -83,9 +83,10 @@ DEFUN(cfg_bssgp, cfg_bssgp_cmd,
static void dump_bvc(struct vty *vty, struct bssgp_bvc_ctx *bvc, int stats)
{
- vty_out(vty, "NSEI %5u, BVCI %5u, RA-ID: %u-%u-%u-%u, CID: %u, "
+ vty_out(vty, "NSEI %5u, BVCI %5u, RA-ID: %u-%0*u-%u-%u, CID: %u, "
"STATE: %s%s", bvc->nsei, bvc->bvci, bvc->ra_id.mcc,
- bvc->ra_id.mnc, bvc->ra_id.lac, bvc->ra_id.rac, bvc->cell_id,
+ bvc->ra_id.mnc.two_digits ? 2 : 3, bvc->ra_id.mnc.network_code,
+ bvc->ra_id.lac, bvc->ra_id.rac, bvc->cell_id,
bvc->state & BVC_S_BLOCKED ? "BLOCKED" : "UNBLOCKED",
VTY_NEWLINE);
diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c
index 06ee18e..ba55b96 100644
--- a/src/gsm/gsm0808.c
+++ b/src/gsm/gsm0808.c
@@ -27,7 +27,7 @@
#define BSSMAP_MSG_SIZE 512
#define BSSMAP_MSG_HEADROOM 128
-struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, uint16_t _ci)
+struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, gsm_mnc_t nc, uint16_t cc, int lac, uint16_t _ci)
{
struct msgb* msg;
struct {
diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c
index 80f7502..9bc9d14 100644
--- a/src/gsm/gsm48.c
+++ b/src/gsm/gsm48.c
@@ -265,7 +265,7 @@ static void to_bcd(uint8_t *bcd, uint16_t val)
}
void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
- uint16_t mnc, uint16_t lac)
+ gsm_mnc_t mnc, uint16_t lac)
{
uint8_t bcd[3];
@@ -273,9 +273,8 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
lai48->digits[0] = bcd[0] | (bcd[1] << 4);
lai48->digits[1] = bcd[2];
- to_bcd(bcd, mnc);
- /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
- if (mnc > 99) {
+ to_bcd(bcd, mnc.network_code);
+ if (!mnc.two_digits) {
lai48->digits[1] |= bcd[2] << 4;
lai48->digits[2] = bcd[0] | (bcd[1] << 4);
} else {
@@ -288,19 +287,21 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
/* Attention: this function retunrs true integers, not hex! */
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
- uint16_t *mnc, uint16_t *lac)
+ gsm_mnc_t *mnc, uint16_t *lac)
{
*mcc = (lai->digits[0] & 0x0f) * 100
+ (lai->digits[0] >> 4) * 10
+ (lai->digits[1] & 0x0f);
if ((lai->digits[1] & 0xf0) == 0xf0) {
- *mnc = (lai->digits[2] & 0x0f) * 10
- + (lai->digits[2] >> 4);
+ mnc->two_digits = true;
+ mnc->network_code = (lai->digits[2] & 0x0f) * 10
+ | (lai->digits[2] >> 4);
} else {
- *mnc = (lai->digits[2] & 0x0f) * 100
- + (lai->digits[2] >> 4) * 10
- + (lai->digits[1] >> 4);
+ mnc->two_digits = false;
+ mnc->network_code = (lai->digits[2] & 0x0f) * 100
+ | (lai->digits[2] >> 4) * 10
+ | (lai->digits[1] >> 4);
}
*lac = ntohs(lai->lac);
@@ -401,12 +402,14 @@ void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf)
/* I wonder who came up with the stupidity of encoding the MNC
* differently depending on how many digits its decimal number has! */
if ((buf[1] >> 4) == 0xf) {
- raid->mnc = (buf[2] & 0xf) * 10;
- raid->mnc += (buf[2] >> 4) * 1;
+ raid->mnc.two_digits = true;
+ raid->mnc.network_code = (buf[2] & 0xf) * 10;
+ raid->mnc.network_code |= (buf[2] >> 4) * 1;
} else {
- raid->mnc = (buf[2] & 0xf) * 100;
- raid->mnc += (buf[2] >> 4) * 10;
- raid->mnc += (buf[1] >> 4) * 1;
+ raid->mnc.two_digits = false;
+ raid->mnc.network_code = (buf[2] & 0xf) * 100;
+ raid->mnc.network_code |= (buf[2] >> 4) * 10;
+ raid->mnc.network_code |= (buf[1] >> 4) * 1;
}
raid->lac = ntohs(*(uint16_t *)(buf + 3));
@@ -415,21 +418,21 @@ void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf)
int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid)
{
- uint16_t mcc = raid->mcc;
- uint16_t mnc = raid->mnc;
- uint16_t _lac;
+ uint16_t mcc = raid->mcc;
+ gsm_mnc_t mnc = raid->mnc;
+ uint16_t _lac;
buf[0] = ((mcc / 100) % 10) | (((mcc / 10) % 10) << 4);
buf[1] = (mcc % 10);
/* I wonder who came up with the stupidity of encoding the MNC
* differently depending on how many digits its decimal number has! */
- if (mnc < 100) {
+ if (mnc.two_digits) {
buf[1] |= 0xf0;
- buf[2] = ((mnc / 10) % 10) | ((mnc % 10) << 4);
+ buf[2] = ((mnc.network_code / 10) % 10) | ((mnc.network_code % 10) << 4);
} else {
- buf[1] |= (mnc % 10) << 4;
- buf[2] = ((mnc / 100) % 10) | (((mnc / 10) % 10) << 4);
+ buf[1] |= (mnc.network_code % 10) << 4;
+ buf[2] = ((mnc.network_code / 100) % 10) | (((mnc.network_code / 10) % 10) << 4);
}
_lac = htons(raid->lac);