Make mi_to_string parse the TMSI we generate, finish CM Service Request implementation

The TMSI encoding is up to us but generate_mid_from_tmsi and mi_to_string
did not agree on the encoding. Adjust mi_to_string to properly decode the
TMSI generated by generate_mid_from_tmsi. Check that the four bits are '1111'
and that the length is five. Memcpy the bytes to tmsi (to work with ARM or such)
and convert the number to host order...

Implement the CM Service Request. Try to get the subscriber from the TMSI and
assign it to the gsm_lchan. There is a small issue that will be fixed in the
next commit.

(done by z.)
This commit is contained in:
Harald Welte 2009-01-10 03:17:30 +00:00
parent ba4cf164b0
commit 4ed0e92464
1 changed files with 27 additions and 10 deletions

View File

@ -258,6 +258,7 @@ static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
int i;
u_int8_t mi_type;
char *str_cur = string;
u_int32_t tmsi;
mi_type = mi[0] & GSM_MI_TYPE_MASK;
@ -265,12 +266,11 @@ static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
case GSM_MI_TYPE_NONE:
break;
case GSM_MI_TYPE_TMSI:
/* skip padding nibble at the beginning, start at offset 1... */
for (i = 1; i < mi_len; i++) {
if (str_cur + 2 >= string + str_len)
return str_cur - string;
*str_cur++ = bcd2char(mi[i] >> 4);
*str_cur++ = bcd2char(mi[i] & 0xf);
/* Table 10.5.4.3, reverse generate_mid_from_tmsi */
if (mi_len == TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {
memcpy(&tmsi, &mi[1], 4);
tmsi = ntohl(tmsi);
return snprintf(string, str_len, "%u", tmsi);
}
break;
case GSM_MI_TYPE_IMSI:
@ -553,10 +553,20 @@ static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
return gsm48_sendmsg(msg);
}
/*
* Handle CM Service Requests
* a) Verify that the packet is long enough to contain the information
* we require otherwsie reject with INCORRECT_MESSAGE
* b) Try to parse the TMSI. If we do not have one reject
* c) Check that we know the subscriber with the TMSI otherwise reject
* with a HLR cause
* d) Set the subscriber on the gsm_lchan and accept
*/
static int gsm48_rx_mm_serv_req(struct msgb *msg)
{
u_int8_t mi_type;
char mi_string[MI_SIZE];
struct gsm_subscriber *subscr;
struct gsm48_hdr *gh = msgb_l3(msg);
@ -582,10 +592,17 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg)
GSM48_REJECT_INCORRECT_MESSAGE);
}
subscr = subscr_get_by_tmsi((char *)req->mi);
DEBUGP(DMM, "<- CM SERVICE REQUEST serv_type=0x%02x mi_type=0x%02x Subscriber(%p)\n",
req->cm_service_type, mi_type, subscr);
mi_to_string(mi_string, sizeof(mi_string), req->mi, req->mi_len);
subscr = subscr_get_by_tmsi(mi_string);
DEBUGP(DMM, "<- CM SERVICE REQUEST serv_type=0x%02x mi_type=0x%02x M(%s)\n",
req->cm_service_type, mi_type, mi_string);
if (!subscr)
return gsm48_tx_mm_serv_rej(msg->lchan,
GSM48_REJECT_IMSI_UNKNOWN_IN_HLR);
if (!msg->lchan->subscr)
msg->lchan->subscr = subscr;
return gsm48_tx_mm_serv_ack(msg->lchan);
}