aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2008-12-30 17:56:55 +0000
committerHarald Welte <laforge@gnumonks.org>2008-12-30 17:56:55 +0000
commitdb253af1aa1609de7040d1073db222cd521e492c (patch)
treedc85cba73a986e20ac1c2a24a97286c4ed39ef65 /src
parent89824fc46650332fa5c85ac1675588682802ecdf (diff)
* fix IMSI parsing of last two digits
* add MM INFO packet support and send it after LOCATION ACCEPT * send 'ALL YOUR BASE ARE BELONG TO US'
Diffstat (limited to 'src')
-rw-r--r--src/gsm_04_08.c116
1 files changed, 105 insertions, 11 deletions
diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c
index 056068587..f23a97847 100644
--- a/src/gsm_04_08.c
+++ b/src/gsm_04_08.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <time.h>
#include <netinet/in.h>
#include <openbsc/db.h>
@@ -99,6 +100,17 @@ static void to_bcd(u_int8_t *bcd, u_int16_t val)
val = val / 10;
}
+static u_int8_t to_bcd8(unsigned int val)
+{
+ u_int8_t bcd;
+
+ bcd = (val % 10) & 0x0f;
+ val = val / 10;
+ bcd |= (val % 10) << 4;
+
+ return bcd;
+}
+
void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
u_int16_t mnc, u_int16_t lac)
{
@@ -183,7 +195,9 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
gh->msg_type = GSM48_MT_MM_LOC_UPD_REJECT;
gh->data[0] = cause;
- DEBUGP(DMM, "-> LOCATION UPDATING REJECT\n");
+ DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
+
+ //gsm0411_send_sms(lchan, NULL);
return gsm48_sendmsg(msg);
}
@@ -214,12 +228,16 @@ int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
lchan->pending_update_request = 0;
DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
- ret = gsm48_sendmsg(msg);
-
/* inform the upper layer on the progress */
if (bts->network->update_request)
(*bts->network->update_request)(bts, tmsi, 1);
+ ret = gsm48_sendmsg(msg);
+
+ /* return gsm48_cc_tx_setup(lchan); */
+ ret = gsm48_tx_mm_info(lchan);
+ ret = gsm0411_send_sms(lchan, NULL);
+
return ret;
}
@@ -244,7 +262,8 @@ 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:
- for (i = 1; i < mi_len - 1; i++) {
+ /* 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);
@@ -254,21 +273,22 @@ static int mi_to_string(char *string, int str_len, u_int8_t *mi, int mi_len)
case GSM_MI_TYPE_IMSI:
case GSM_MI_TYPE_IMEI:
case GSM_MI_TYPE_IMEISV:
- if (mi[0] & GSM_MI_ODD)
- *str_cur++ = bcd2char(mi[0] >> 4);
-
- for (i = 1; i < mi_len - 1; i++) {
+ *str_cur++ = bcd2char(mi[0] >> 4);
+
+ for (i = 1; i < mi_len; i++) {
if (str_cur + 2 >= string + str_len)
return str_cur - string;
*str_cur++ = bcd2char(mi[i] & 0xf);
- *str_cur++ = bcd2char(mi[i] >> 4);
+ /* skip last nibble in last input byte when GSM_EVEN */
+ if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD))
+ *str_cur++ = bcd2char(mi[i] >> 4);
}
break;
default:
break;
}
-
*str_cur++ = '\0';
+
return str_cur - string;
}
@@ -313,6 +333,7 @@ static int mm_rx_id_resp(struct msgb *msg)
if (authorize_subscriber(lchan->subscr)) {
db_subscriber_alloc_tmsi(lchan->subscr);
tmsi = strtoul(lchan->subscr->tmsi, NULL, 10);
+ del_timer(&lchan->timer);
return gsm0408_loc_upd_acc(msg->lchan, tmsi);
} else {
schedule_reject(lchan);
@@ -334,7 +355,8 @@ static void loc_upd_rej_cb(void *data)
{
struct gsm_lchan *lchan = data;
- gsm0408_loc_upd_rej(lchan, 0x16);
+ /* 0x16 is congestion */
+ gsm0408_loc_upd_rej(lchan, 0x04);
rsl_chan_release(lchan);
}
@@ -412,9 +434,81 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
tmsi = strtoul(subscr->tmsi, NULL, 10);
+ del_timer(&lchan->timer);
return gsm0408_loc_upd_acc(lchan, tmsi);
}
+/* Section 9.2.15a */
+int gsm48_tx_mm_info(struct gsm_lchan *lchan)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh;
+ struct gsm_network *net = lchan->ts->trx->bts->network;
+ time_t cur_t;
+ struct tm* cur_time;
+ u_int8_t *ptr8;
+ u_int16_t *ptr16;
+ int name_len;
+ int tz15min;
+ int i;
+
+ msg->lchan = lchan;
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_MM;
+ gh->msg_type = GSM48_MT_MM_INFO;
+
+ if (net->name_long) {
+ name_len = strlen(net->name_long);
+ /* 10.5.3.5a */
+ ptr8 = msgb_put(msg, 3);
+ ptr8[0] = GSM48_IE_NAME_LONG;
+ ptr8[1] = name_len*2 +1;
+ ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
+
+ ptr16 = (u_int16_t *) msgb_put(msg, name_len*2);
+ for (i = 0; i < name_len; i++)
+ ptr16[i] = net->name_long[i];
+
+ /* FIXME: Use Cell Broadcast, not UCS-2, since
+ * UCS-2 is only supported by later revisions of the spec */
+ }
+
+ if (net->name_short) {
+ name_len = strlen(net->name_short);
+ /* 10.5.3.5a */
+ ptr8 = (u_int8_t *) msgb_put(msg, 3);
+ ptr8[0] = GSM48_IE_NAME_LONG;
+ ptr8[1] = name_len*2 + 1;
+ ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
+
+ ptr16 = msgb_put(msg, name_len*2);
+ for (i = 0; i < name_len; i++)
+ ptr16[i] = net->name_short[i];
+ }
+
+#if 0
+ /* Section 10.5.3.9 */
+ cur_t = time(NULL);
+ cur_time = gmtime(cur_t);
+ ptr8 = msgb_put(msg, 8);
+ ptr8[0] = GSM48_IE_NET_TIME_TZ;
+ ptr8[1] = to_bcd8(cur_time->tm_year % 100);
+ ptr8[2] = to_bcd8(cur_time->tm_mon);
+ ptr8[3] = to_bcd8(cur_time->tm_mday);
+ ptr8[4] = to_bcd8(cur_time->tm_hour);
+ ptr8[5] = to_bcd8(cur_time->tm_min);
+ ptr8[6] = to_bcd8(cur_time->tm_sec);
+ /* 02.42: coded as BCD encoded signed value in units of 15 minutes */
+ tz15min = (cur_time->tm_gmtoff)/(60*15);
+ ptr8[6] = to_bcd8(tz15min);
+ if (tz15min < 0)
+ ptr8[6] |= 0x80;
+#endif
+
+ return gsm48_sendmsg(msg);
+}
+
static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
{
DEBUGP(DMM, "-> CM SERVICE ACK\n");