parent
10b487b1c0
commit
75a983fab0
|
@ -610,9 +610,6 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
|
||||||
arfcn = lchan->ts->trx->arfcn;
|
arfcn = lchan->ts->trx->arfcn;
|
||||||
subch = lchan->nr;
|
subch = lchan->nr;
|
||||||
|
|
||||||
DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %u\n",
|
|
||||||
arfcn, ts_number, subch, lchan->type);
|
|
||||||
|
|
||||||
rsl_chan_activate_lchan(lchan, 0x00, rqd_ta);
|
rsl_chan_activate_lchan(lchan, 0x00, rqd_ta);
|
||||||
|
|
||||||
/* create IMMEDIATE ASSIGN 04.08 messge */
|
/* create IMMEDIATE ASSIGN 04.08 messge */
|
||||||
|
@ -631,6 +628,9 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
|
||||||
ia.timing_advance = rqd_ta;
|
ia.timing_advance = rqd_ta;
|
||||||
ia.mob_alloc_len = 0;
|
ia.mob_alloc_len = 0;
|
||||||
|
|
||||||
|
DEBUGP(DRSL, "Activating ARFCN(%u) TS(%u) SS(%u) lctype %u chan_nr=0x%02x\n",
|
||||||
|
arfcn, ts_number, subch, lchan->type, ia.chan_desc.chan_nr);
|
||||||
|
|
||||||
/* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
|
/* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */
|
||||||
return rsl_imm_assign_cmd(bts, sizeof(ia), (u_int8_t *) &ia);
|
return rsl_imm_assign_cmd(bts, sizeof(ia), (u_int8_t *) &ia);
|
||||||
}
|
}
|
||||||
|
|
|
@ -636,6 +636,18 @@ int main(int argc, char **argv)
|
||||||
/* parse options */
|
/* parse options */
|
||||||
handle_options(argc, argv);
|
handle_options(argc, argv);
|
||||||
|
|
||||||
|
if (db_init()) {
|
||||||
|
printf("DB: Failed to init database. Please check the option settings.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("DB: Database initialized.\n");
|
||||||
|
|
||||||
|
if (db_prepare()) {
|
||||||
|
printf("DB: Failed to prepare database.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("DB: Database prepared.\n");
|
||||||
|
|
||||||
bootstrap_network();
|
bootstrap_network();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
|
@ -63,7 +63,25 @@ struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
|
||||||
int i, j;
|
int i, j;
|
||||||
for (i = 0; i < bts->num_trx; i++) {
|
for (i = 0; i < bts->num_trx; i++) {
|
||||||
struct gsm_bts_trx *trx = &bts->trx[i];
|
struct gsm_bts_trx *trx = &bts->trx[i];
|
||||||
for (j = 0; j < 8; j++) {
|
int from, to;
|
||||||
|
|
||||||
|
/* the following constraints are pure policy,
|
||||||
|
* no requirement to put this restriction in place */
|
||||||
|
switch (pchan) {
|
||||||
|
case GSM_PCHAN_CCCH:
|
||||||
|
case GSM_PCHAN_CCCH_SDCCH4:
|
||||||
|
from = 0; to = 0;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_SDCCH8_SACCH8C:
|
||||||
|
from = 1; to = 1;
|
||||||
|
break;
|
||||||
|
case GSM_PCHAN_TCH_F:
|
||||||
|
case GSM_PCHAN_TCH_H:
|
||||||
|
from = 2; to = 7;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = from; j <= to; j++) {
|
||||||
struct gsm_bts_trx_ts *ts = &trx->ts[j];
|
struct gsm_bts_trx_ts *ts = &trx->ts[j];
|
||||||
if (ts->pchan == GSM_PCHAN_NONE) {
|
if (ts->pchan == GSM_PCHAN_NONE) {
|
||||||
ts->pchan = pchan;
|
ts->pchan = pchan;
|
||||||
|
|
15
src/db.c
15
src/db.c
|
@ -69,7 +69,7 @@ int db_prepare() {
|
||||||
"created TIMESTAMP NOT NULL, "
|
"created TIMESTAMP NOT NULL, "
|
||||||
"updated TIMESTAMP NOT NULL, "
|
"updated TIMESTAMP NOT NULL, "
|
||||||
"imsi NUMERIC UNIQUE NOT NULL, "
|
"imsi NUMERIC UNIQUE NOT NULL, "
|
||||||
"tmsi NUMERIC UNIQUE, "
|
"tmsi TEXT UNIQUE, "
|
||||||
"extension TEXT UNIQUE, "
|
"extension TEXT UNIQUE, "
|
||||||
"lac INTEGER NOT NULL DEFAULT 0, "
|
"lac INTEGER NOT NULL DEFAULT 0, "
|
||||||
"authorized INTEGER NOT NULL DEFAULT 0"
|
"authorized INTEGER NOT NULL DEFAULT 0"
|
||||||
|
@ -146,6 +146,8 @@ struct gsm_subscriber* db_create_subscriber(char imsi[GSM_IMSI_LENGTH]) {
|
||||||
|
|
||||||
int db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber* subscriber) {
|
int db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber* subscriber) {
|
||||||
dbi_result result;
|
dbi_result result;
|
||||||
|
char *string;
|
||||||
|
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case GSM_SUBSCRIBER_IMSI:
|
case GSM_SUBSCRIBER_IMSI:
|
||||||
result = dbi_conn_queryf(conn,
|
result = dbi_conn_queryf(conn,
|
||||||
|
@ -174,9 +176,16 @@ int db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber* su
|
||||||
dbi_result_free(result);
|
dbi_result_free(result);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
memset(subscriber, 0, sizeof(*subscriber));
|
||||||
subscriber->id = dbi_result_get_ulonglong(result, "id");
|
subscriber->id = dbi_result_get_ulonglong(result, "id");
|
||||||
strncpy(subscriber->imsi, dbi_result_get_string(result, "imsi"), GSM_IMSI_LENGTH);
|
string = dbi_result_get_string(result, "imsi");
|
||||||
strncpy(subscriber->tmsi, dbi_result_get_string(result, "tmsi"), GSM_TMSI_LENGTH);
|
if (string)
|
||||||
|
strncpy(subscriber->imsi, string, GSM_IMSI_LENGTH);
|
||||||
|
|
||||||
|
string = dbi_result_get_string(result, "tmsi");
|
||||||
|
if (string)
|
||||||
|
strncpy(subscriber->tmsi, string, GSM_TMSI_LENGTH);
|
||||||
|
|
||||||
// FIXME handle extension
|
// FIXME handle extension
|
||||||
subscriber->lac = dbi_result_get_uint(result, "lac");
|
subscriber->lac = dbi_result_get_uint(result, "lac");
|
||||||
subscriber->authorized = dbi_result_get_uint(result, "authorized");
|
subscriber->authorized = dbi_result_get_uint(result, "authorized");
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <openbsc/db.h>
|
||||||
#include <openbsc/msgb.h>
|
#include <openbsc/msgb.h>
|
||||||
#include <openbsc/debug.h>
|
#include <openbsc/debug.h>
|
||||||
#include <openbsc/gsm_data.h>
|
#include <openbsc/gsm_data.h>
|
||||||
|
@ -98,15 +99,12 @@ static void generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
|
||||||
#define TMSI_LEN 4
|
#define TMSI_LEN 4
|
||||||
#define MID_TMSI_LEN (TMSI_LEN + 2)
|
#define MID_TMSI_LEN (TMSI_LEN + 2)
|
||||||
|
|
||||||
static void generate_mid_from_tmsi(u_int8_t *buf, u_int8_t *tmsi_bcd)
|
static void generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi)
|
||||||
{
|
{
|
||||||
buf[0] = GSM48_IE_MOBILE_ID;
|
buf[0] = GSM48_IE_MOBILE_ID;
|
||||||
buf[1] = MID_TMSI_LEN;
|
buf[1] = MID_TMSI_LEN;
|
||||||
buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
|
buf[2] = 0xf0 | GSM_MI_TYPE_TMSI;
|
||||||
buf[3] = tmsi_bcd[0];
|
*((u_int32_t *) &buf[3]) = htonl(tmsi);
|
||||||
buf[4] = tmsi_bcd[1];
|
|
||||||
buf[5] = tmsi_bcd[2];
|
|
||||||
buf[6] = tmsi_bcd[3];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct msgb *gsm48_msgb_alloc(void)
|
static struct msgb *gsm48_msgb_alloc(void)
|
||||||
|
@ -144,7 +142,7 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
|
/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
|
||||||
int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int8_t *tmsi)
|
int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
|
||||||
{
|
{
|
||||||
struct gsm_bts *bts = lchan->ts->trx->bts;
|
struct gsm_bts *bts = lchan->ts->trx->bts;
|
||||||
struct msgb *msg = gsm48_msgb_alloc();
|
struct msgb *msg = gsm48_msgb_alloc();
|
||||||
|
@ -241,14 +239,33 @@ static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
|
||||||
static int mm_rx_id_resp(struct msgb *msg)
|
static int mm_rx_id_resp(struct msgb *msg)
|
||||||
{
|
{
|
||||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||||
|
struct gsm_lchan *lchan = msg->lchan;
|
||||||
u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
|
u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
|
||||||
char mi_string[MI_SIZE];
|
char mi_string[MI_SIZE];
|
||||||
|
u_int32_t tmsi;
|
||||||
|
|
||||||
mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
|
mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
|
||||||
DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
|
DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n",
|
||||||
mi_type, mi_string);
|
mi_type, mi_string);
|
||||||
|
|
||||||
/* FIXME: update subscribe <-> IMEI mapping */
|
switch (mi_type) {
|
||||||
|
case GSM_MI_TYPE_IMSI:
|
||||||
|
if (!lchan->subscr)
|
||||||
|
lchan->subscr = db_create_subscriber(mi_string);
|
||||||
|
if (lchan->subscr && lchan->subscr->authorized) {
|
||||||
|
/* FIXME: check if we've recently received UPDATE REQUEST */
|
||||||
|
db_subscriber_alloc_tmsi(lchan->subscr);
|
||||||
|
tmsi = strtoul(lchan->subscr->tmsi, NULL, 16);
|
||||||
|
return gsm0408_loc_upd_acc(msg->lchan, tmsi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GSM_MI_TYPE_IMEI:
|
||||||
|
/* update subscribe <-> IMEI mapping */
|
||||||
|
if (lchan->subscr)
|
||||||
|
db_subscriber_assoc_imei(lchan->subscr, mi_string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MI_SIZE 32
|
#define MI_SIZE 32
|
||||||
|
@ -260,6 +277,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
||||||
struct gsm48_loc_upd_req *lu;
|
struct gsm48_loc_upd_req *lu;
|
||||||
struct gsm_subscriber *subscr;
|
struct gsm_subscriber *subscr;
|
||||||
u_int8_t mi_type;
|
u_int8_t mi_type;
|
||||||
|
u_int32_t tmsi;
|
||||||
char mi_string[MI_SIZE];
|
char mi_string[MI_SIZE];
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -275,7 +293,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
||||||
/* we always want the IMEI, too */
|
/* we always want the IMEI, too */
|
||||||
rc = mm_tx_identity_req(msg->lchan, GSM_MI_TYPE_IMEISV);
|
rc = mm_tx_identity_req(msg->lchan, GSM_MI_TYPE_IMEISV);
|
||||||
/* look up subscriber based on IMSI */
|
/* look up subscriber based on IMSI */
|
||||||
subscr = subscr_get_by_imsi(lu->mi);
|
subscr = db_create_subscriber(mi_string);
|
||||||
break;
|
break;
|
||||||
case GSM_MI_TYPE_TMSI:
|
case GSM_MI_TYPE_TMSI:
|
||||||
/* we always want the IMEI, too */
|
/* we always want the IMEI, too */
|
||||||
|
@ -297,17 +315,20 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subscr) {
|
if (!subscr || !subscr->authorized) {
|
||||||
/* 0x16 is congestion */
|
/* 0x16 is congestion */
|
||||||
gsm0408_loc_upd_rej(msg->lchan, 0x16);
|
gsm0408_loc_upd_rej(msg->lchan, 0x16);
|
||||||
rsl_chan_release(msg->lchan);
|
rsl_chan_release(msg->lchan);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db_subscriber_alloc_tmsi(subscr);
|
||||||
|
|
||||||
msg->lchan->subscr = subscr;
|
msg->lchan->subscr = subscr;
|
||||||
subscr_update(subscr, bts);
|
subscr_update(subscr, bts);
|
||||||
|
tmsi = strtoul(subscr->tmsi, NULL, 16);
|
||||||
|
|
||||||
return gsm0408_loc_upd_acc(msg->lchan, subscr->tmsi);
|
return gsm0408_loc_upd_acc(msg->lchan, tmsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
|
static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
|
||||||
|
|
|
@ -20,24 +20,63 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <openbsc/gsm_subscriber.h>
|
#include <openbsc/gsm_subscriber.h>
|
||||||
|
#include <openbsc/db.h>
|
||||||
|
|
||||||
static struct gsm_subscriber subscr = {
|
struct gsm_subscriber *subscr_alloc(void)
|
||||||
.name = "Test User 1",
|
|
||||||
.tmsi = { 0x22, 0x33, 0x44, 0x55 },
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gsm_subscriber *subscr_get_by_tmsi(u_int8_t *tmsi)
|
|
||||||
{
|
{
|
||||||
return &subscr;
|
struct gsm_subscriber *s;
|
||||||
|
|
||||||
|
s = malloc(sizeof(struct gsm_subscriber));
|
||||||
|
if (!s)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
struct gsm_subscriber *subscr_get_by_imsi(u_int8_t *imsi)
|
|
||||||
|
void subscr_free(struct gsm_subscriber *subscr)
|
||||||
{
|
{
|
||||||
return &subscr;
|
free(subscr);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_subscriber *subscr_get_by_tmsi(char *tmsi)
|
||||||
|
{
|
||||||
|
struct gsm_subscriber *subscr = subscr_alloc();
|
||||||
|
|
||||||
|
strncpy(subscr->tmsi, tmsi, sizeof(subscr->tmsi));
|
||||||
|
subscr->tmsi[sizeof(subscr->tmsi)-1] = '\0';
|
||||||
|
|
||||||
|
if (db_get_subscriber(GSM_SUBSCRIBER_TMSI, subscr) != 0) {
|
||||||
|
subscr_free(subscr);
|
||||||
|
subscr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return subscr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gsm_subscriber *subscr_get_by_imsi(char *imsi)
|
||||||
|
{
|
||||||
|
struct gsm_subscriber *subscr = subscr_alloc();
|
||||||
|
|
||||||
|
strncpy(subscr->imsi, imsi, sizeof(subscr->imsi));
|
||||||
|
subscr->imsi[sizeof(subscr->imsi)-1] = '\0';
|
||||||
|
|
||||||
|
if (db_get_subscriber(GSM_SUBSCRIBER_IMSI, subscr) != 0) {
|
||||||
|
subscr_free(subscr);
|
||||||
|
subscr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return subscr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts)
|
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts)
|
||||||
{
|
{
|
||||||
return 0;
|
return db_set_subscriber(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,8 +286,10 @@ static int handle_tsX_read(struct bsc_fd *bfd)
|
||||||
|
|
||||||
msg->l2h = msg->data + MISDN_HEADER_LEN;
|
msg->l2h = msg->data + MISDN_HEADER_LEN;
|
||||||
|
|
||||||
|
#if 0
|
||||||
fprintf(stdout, "BCHAN RX: ");
|
fprintf(stdout, "BCHAN RX: ");
|
||||||
hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN);
|
hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN);
|
||||||
|
#endif
|
||||||
if (!e1h->ts2_fd)
|
if (!e1h->ts2_fd)
|
||||||
e1h->ts2_fd = open("/tmp/ts2.dump", O_WRONLY|O_APPEND|O_CREAT, 0660);
|
e1h->ts2_fd = open("/tmp/ts2.dump", O_WRONLY|O_APPEND|O_CREAT, 0660);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue