[gsm48] Introduce a gsm48_generate_mid_from_imsi method

Prefix generate_mid_from_tmsi with a gsm48_, create a new method
to binary encode the imsi. Add a unit test for parsing and decoding.

The implementation can parse the data it generated and the
last octet seems to be filled with the end mark.
This commit is contained in:
Holger Hans Peter Freyther 2009-08-20 08:41:24 +02:00
parent d1862d7cf9
commit 5d0e56f722
5 changed files with 78 additions and 6 deletions

View File

@ -708,7 +708,8 @@ int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand);
int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan);
struct msgb *gsm48_msgb_alloc(void);
int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans);
int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi);
int gsm48_generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi);
int gsm48_generate_mid_from_imsi(u_int8_t *buf, const char* imsi);
int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, const int mi_len);
int gsm48_send_rr_release(struct gsm_lchan *lchan);

View File

@ -899,7 +899,7 @@ int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
bts->network->network_code, bts->location_area_code);
mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
generate_mid_from_tmsi(mid, tmsi);
gsm48_generate_mid_from_tmsi(mid, tmsi);
DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");

View File

@ -164,6 +164,12 @@ static char bcd2char(u_int8_t bcd)
return 'A' + (bcd - 0xa);
}
/* only works for numbers in ascci */
static u_int8_t char2bcd(char c)
{
return c - 0x30;
}
void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
u_int16_t mnc, u_int16_t lac)
@ -187,7 +193,7 @@ void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
lai48->lac = htons(lac);
}
int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
int gsm48_generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
{
u_int32_t *tptr = (u_int32_t *) &buf[3];
@ -199,6 +205,35 @@ int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
return 7;
}
int gsm48_generate_mid_from_imsi(u_int8_t *buf, const char *imsi)
{
unsigned int length = strlen(imsi), i, off = 0;
u_int8_t odd = (length & 0x1) == 1;
buf[0] = GSM48_IE_MOBILE_ID;
buf[2] = char2bcd(imsi[0]) << 4 | GSM_MI_TYPE_IMSI | (odd << 3);
/* if the length is even we will fill half of the last octet */
if (odd)
buf[1] = (length + 1) >> 1;
else
buf[1] = (length + 2) >> 1;
for (i = 1; i < buf[1]; ++i) {
u_int8_t lower, upper;
lower = char2bcd(imsi[++off]);
if (!odd && off + 1 == length)
upper = 0x0f;
else
upper = char2bcd(imsi[++off]) & 0x0f;
buf[2 + i] = (upper << 4) | lower;
}
return 2 + buf[1];
}
/* Section 9.1.8 / Table 9.9 */
struct chreq {
u_int8_t val;

View File

@ -99,7 +99,7 @@ static void page_ms(struct gsm_paging_request *request)
page_group = calculate_group(request->bts, request->subscr);
tmsi = strtoul(request->subscr->tmsi, NULL, 10);
mi_len = generate_mid_from_tmsi(mi, tmsi);
mi_len = gsm48_generate_mid_from_tmsi(mi, tmsi);
rsl_paging_cmd(request->bts, page_group, mi_len, mi,
request->chan_type);
}

View File

@ -24,13 +24,20 @@
#include <stdlib.h>
#include <openbsc/gsm_04_08.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/debug.h>
#define COMPARE(result, op, value) \
if (!((result) op (value))) {\
fprintf(stderr, "Compare failed. Was %x should be %x in %s:%d\n",result, value, __FILE__, __LINE__); \
exit(-1); \
}
#define COMPARE_STR(result, value) \
if (strcmp(result, value) != 0) { \
fprintf(stderr, "Compare failed. Was %s should be %s in %s:%d\n",result, value, __FILE__, __LINE__); \
exit(-1); \
}
/*
* Test Location Area Identifier formatting. Table 10.5.3 of 04.08
@ -58,9 +65,38 @@ static void test_location_area_identifier(void)
COMPARE(lai48.lac, ==, htons(0x000f));
}
static void test_mi_functionality(void)
{
const char *imsi_odd = "987654321098763";
const char *imsi_even = "9876543210987654";
const u_int32_t tmsi = 0xfabeacd0;
u_int8_t mi[128];
unsigned int mi_len;
char mi_parsed[GSM48_MI_SIZE];
printf("Testing parsing and generating TMSI/IMSI\n");
/* tmsi code */
mi_len = gsm48_generate_mid_from_tmsi(mi, tmsi);
gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len - 2);
COMPARE((u_int32_t)strtoul(mi_parsed, NULL, 10), ==, tmsi);
/* imsi code */
mi_len = gsm48_generate_mid_from_imsi(mi, imsi_odd);
gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len -2);
printf("hex: %s\n", hexdump(mi, mi_len));
COMPARE_STR(mi_parsed, imsi_odd);
mi_len = gsm48_generate_mid_from_imsi(mi, imsi_even);
gsm48_mi_to_string(mi_parsed, sizeof(mi_parsed), mi + 2, mi_len -2);
printf("hex: %s\n", hexdump(mi, mi_len));
COMPARE_STR(mi_parsed, imsi_even);
}
int main(int argc, char** argv)
{
test_location_area_identifier();
test_location_area_identifier();
test_mi_functionality();
}