Merge branch 'master' into sms
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h
index 61a3ac4..c9b7265 100644
--- a/openbsc/include/openbsc/db.h
+++ b/openbsc/include/openbsc/db.h
@@ -31,14 +31,17 @@
int db_fini();
/* subscriber management */
-struct gsm_subscriber* db_create_subscriber(char *imsi);
-struct gsm_subscriber* db_get_subscriber(enum gsm_subscriber_field field, const char *subscr);
+struct gsm_subscriber* db_create_subscriber(struct gsm_network *net,
+ char *imsi);
+struct gsm_subscriber* db_get_subscriber(struct gsm_network *net,
+ enum gsm_subscriber_field field,
+ const char *subscr);
int db_sync_subscriber(struct gsm_subscriber* subscriber);
int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber);
int db_subscriber_assoc_imei(struct gsm_subscriber* subscriber, char *imei);
/* SMS store-and-forward */
int db_sms_store(struct gsm_sms *sms);
-struct gsm_sms *db_sms_get_unsent(int min_id);
+struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id);
int db_sms_mark_sent(struct gsm_sms *sms);
#endif /* _DB_H */
diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h
index 12c607f..4f45357 100644
--- a/openbsc/include/openbsc/gsm_04_11.h
+++ b/openbsc/include/openbsc/gsm_04_11.h
@@ -16,6 +16,19 @@
GSM411_CP_IE_CAUSE = 0x02, /* 8.1.4.2. */
};
+/* Section 8.1.4.2 / Table 8.2 */
+enum gsm411_cp_cause {
+ GSM411_CP_CAUSE_NET_FAIL = 17,
+ GSM411_CP_CAUSE_CONGESTION = 22,
+ GSM411_CP_CAUSE_INV_TRANS_ID = 81,
+ GSM411_CP_CAUSE_SEMANT_INC_MSG = 95,
+ GSM411_CP_CAUSE_INV_MAND_INF = 96,
+ GSM411_CP_CAUSE_MSGTYPE_NOTEXIST= 97,
+ GSM411_CP_CAUSE_MSG_INCOMP_STATE= 98,
+ GSM411_CP_CAUSE_IE_NOTEXIST = 99,
+ GSM411_CP_CAUSE_PROTOCOL_ERR = 111,
+};
+
/* Chapter 8.2.2 */
#define GSM411_MT_RP_DATA_MO 0x00
#define GSM411_MT_RP_DATA_MT 0x01
@@ -30,6 +43,36 @@
GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */
};
+/* Chapter 8.2.5.4 Table 8.4 */
+enum gsm411_rp_cause {
+ /* valid only for MO */
+ GSM411_RP_CAUSE_MO_NUM_UNASSIGNED = 1,
+ GSM411_RP_CAUSE_MO_OP_DET_BARR = 8,
+ GSM411_RP_CAUSE_MO_CALL_BARRED = 10,
+ GSM411_RP_CAUSE_MO_SMS_REJECTED = 21,
+ GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER = 27,
+ GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR = 28,
+ GSM411_RP_CAUSE_MO_FACILITY_REJ = 29,
+ GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR = 30,
+ GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER = 38,
+ GSM411_RP_CAUSE_MO_TEMP_FAIL = 41,
+ GSM411_RP_CAUSE_MO_CONGESTION = 42,
+ GSM411_RP_CAUSE_MO_RES_UNAVAIL = 47,
+ GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR = 50,
+ GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL = 69,
+ GSM411_RP_CAUSE_MO_INTERWORKING = 127,
+ /* valid only for MT */
+ GSM411_RP_CAUSE_MT_MEM_EXCEEDED = 22,
+ /* valid for both directions */
+ GSM411_RP_CAUSE_INV_TRANS_REF = 81,
+ GSM411_RP_CAUSE_SEMANT_INC_MSG = 95,
+ GSM411_RP_CAUSE_INV_MAND_INF = 96,
+ GSM411_RP_CAUSE_MSGTYPE_NOTEXIST = 97,
+ GSM411_RP_CAUSE_MSG_INCOMP_STATE = 98,
+ GSM411_RP_CAUSE_IE_NOTEXIST = 99,
+ GSM411_RP_CAUSE_PROTOCOL_ERR = 111,
+};
+
/* Chapter 8.2.1 */
struct gsm411_rp_hdr {
u_int8_t len;
@@ -49,20 +92,20 @@
/* SMS submit PDU */
struct sms_submit {
u_int8_t *smsc;
- u_int8_t mti:2;
- u_int8_t vpf:2;
- u_int8_t msg_ref;
- u_int8_t pid;
- u_int8_t dcs;
- u_int8_t *vp;
- u_int8_t ud_len;
- u_int8_t *user_data;
+ u_int8_t mti:2; /* message type indicator */
+ u_int8_t vpf:2; /* validity period format */
+ u_int8_t msg_ref; /* message reference */
+ u_int8_t pid; /* protocol identifier */
+ u_int8_t dcs; /* data coding scheme */
+ u_int8_t *vp; /* validity period */
+ u_int8_t ud_len; /* user data length */
+ u_int8_t *user_data; /* user data */
/* interpreted */
- u_int8_t mms:1;
- u_int8_t sri:1;
- u_int8_t udhi:1;
- u_int8_t rp:1;
+ u_int8_t mms:1; /* more messages to send */
+ u_int8_t srr:1; /* status report request */
+ u_int8_t udhi:1; /* user data headre indication */
+ u_int8_t rp:1; /* request for reply path */
enum sms_alphabet alphabet;
char dest_addr[20+1]; /* DA LV is 12 bytes max, i.e. 10 bytes BCD == 20 bytes string */
unsigned long validity_mins;
@@ -144,20 +187,20 @@
/* SMS deliver PDU */
struct sms_deliver {
+ u_int8_t mti:2; /* message type indicator */
+ u_int8_t mms:1; /* more messages to send */
+ u_int8_t rp:1; /* reply path */
+ u_int8_t udhi:1; /* user data header indicator */
+ u_int8_t sri:1; /* status report indication */
+ u_int8_t *orig_addr; /* originating address */
+ u_int8_t pid; /* protocol identifier */
+ u_int8_t dcs; /* data coding scheme */
+ /* service centre time stamp */
+ u_int8_t ud_len; /* user data length */
+ u_int8_t *user_data; /* user data */
+
+ u_int8_t msg_ref; /* message reference */
u_int8_t *smsc;
- u_int8_t mti:2;
- u_int8_t rd:1;
- u_int8_t vpf:2;
- u_int8_t srr:1;
- u_int8_t udhi:1;
- u_int8_t rp:1;
- u_int8_t msg_ref;
- u_int8_t *orig_addr;
- u_int8_t pid;
- u_int8_t dcs;
- u_int8_t vp;
- u_int8_t ud_len;
- u_int8_t *user_data;
};
struct msgb;
@@ -166,7 +209,4 @@
int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms);
-struct msgb *gsm411_msgb_alloc(void);
-int gsm0411_sendmsg(struct msgb *msg);
-
#endif
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index de3f1f5..087123f 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -74,7 +74,7 @@
* Use the channel. As side effect the lchannel recycle timer
* will be started.
*/
-#define LCHAN_RELEASE_TIMEOUT 10, 0
+#define LCHAN_RELEASE_TIMEOUT 20, 0
#define use_lchan(lchan) \
do { lchan->use_count++; \
DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \
@@ -104,29 +104,36 @@
/* Entry in list of all transactions */
struct llist_head entry;
- /* Network */
- struct gsm_network *network;
+ /* The protocol within which we live */
+ u_int8_t protocol;
/* The current transaction ID */
u_int8_t transaction_id;
- /* The LCHAN that we're part of */
- struct gsm_lchan *lchan;
-
- /* To whom we are allocated at the moment */
+ /* To whom we belong, unique identifier of remote MM entity */
struct gsm_subscriber *subscr;
- /* reference */
+ /* The LCHAN that we're currently using to transmit messages */
+ struct gsm_lchan *lchan;
+
+ /* reference from MNCC or other application */
u_int32_t callref;
- /* current call state */
- int state;
+ union {
+ struct {
- /* current timer and message queue */
- int Tcurrent; /* current CC timer */
- int T308_second; /* used to send release again */
- struct timer_list cc_timer;
- struct gsm_mncc cc_msg; /* stores setup/disconnect/release message */
+ /* current call state */
+ int state;
+
+ /* current timer and message queue */
+ int Tcurrent; /* current CC timer */
+ int T308_second; /* used to send release again */
+ struct timer_list timer;
+ struct gsm_mncc msg; /* stores setup/disconnect/release message */
+ } cc;
+ struct {
+ } sms;
+ };
};
@@ -381,6 +388,8 @@
struct gsm_subscriber *sender;
struct gsm_subscriber *receiver;
+ unsigned long validity_minutes;
+ unsigned int header_len;
unsigned char header[SMS_HDR_SIZE];
char text[SMS_TEXT_SIZE];
};
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 4a23115..f182230 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -50,6 +50,7 @@
GSM_SUBSCRIBER_IMSI,
GSM_SUBSCRIBER_TMSI,
GSM_SUBSCRIBER_EXTENSION,
+ GSM_SUBSCRIBER_ID,
};
enum gsm_subscriber_update_reason {
@@ -60,9 +61,12 @@
struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr);
struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr);
-struct gsm_subscriber *subscr_get_by_tmsi(const char *tmsi);
-struct gsm_subscriber *subscr_get_by_imsi(const char *imsi);
-struct gsm_subscriber *subscr_get_by_extension(const char *ext);
+struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net,
+ const char *tmsi);
+struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net,
+ const char *imsi);
+struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
+ const char *ext);
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
void subscr_put_channel(struct gsm_lchan *lchan);
void subscr_get_channel(struct gsm_subscriber *subscr,
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index c0ac63c..c6e9dae 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -9,7 +9,8 @@
gsm_subscriber.c msgb.c select.c chan_alloc.c timer.c debug.c db.c \
gsm_04_11.c telnet_interface.c subchan_demux.c \
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \
- input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c
+ input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c \
+ transaction.c
libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
diff --git a/openbsc/src/db.c b/openbsc/src/db.c
index 543f44c..57c5c85 100644
--- a/openbsc/src/db.c
+++ b/openbsc/src/db.c
@@ -79,7 +79,7 @@
"sent TIMESTAMP, "
"sender_id NUMERIC NOT NULL, "
"receiver_id NUMERIC NOT NULL, "
- "header NUMERIC, "
+ "header BLOB, "
"text TEXT NOT NULL "
")",
"CREATE TABLE IF NOT EXISTS VLR ("
@@ -158,12 +158,13 @@
return 0;
}
-struct gsm_subscriber* db_create_subscriber(char *imsi) {
+struct gsm_subscriber* db_create_subscriber(struct gsm_network *net, char *imsi)
+{
dbi_result result;
struct gsm_subscriber* subscr;
/* Is this subscriber known in the db? */
- subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi);
+ subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi);
if (subscr) {
result = dbi_conn_queryf(conn,
"UPDATE Subscriber set updated = datetime('now') "
@@ -189,6 +190,7 @@
if (result==NULL) {
printf("DB: Failed to create Subscriber by IMSI.\n");
}
+ subscr->net = net;
subscr->id = dbi_conn_sequence_last(conn, NULL);
strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1);
dbi_result_free(result);
@@ -196,7 +198,10 @@
return subscr;
}
-struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, const char *id) {
+struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
+ enum gsm_subscriber_field field,
+ const char *id)
+{
dbi_result result;
const char *string;
char *quoted;
@@ -230,6 +235,13 @@
);
free(quoted);
break;
+ case GSM_SUBSCRIBER_ID:
+ dbi_conn_quote_string_copy(conn, id, "ed);
+ result = dbi_conn_queryf(conn,
+ "SELECT * FROM Subscriber "
+ "WHERE id = %s ", quoted);
+ free(quoted);
+ break;
default:
printf("DB: Unknown query selector for Subscriber.\n");
return NULL;
@@ -246,6 +258,7 @@
}
subscr = subscr_alloc();
+ subscr->net = net;
subscr->id = dbi_result_get_ulonglong(result, "id");
string = dbi_result_get_string(result, "imsi");
if (string)
@@ -440,16 +453,20 @@
{
dbi_result result;
char *q_text;
+ unsigned char *q_header;
dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text);
+ dbi_conn_quote_binary_copy(conn, sms->header, sms->header_len,
+ &q_header);
result = dbi_conn_queryf(conn,
"INSERT INTO SMS "
"(created,sender_id,receiver_id,header,text) VALUES "
"(datetime('now'),%llu,%llu,%s,%s)",
sms->sender->id,
sms->receiver ? sms->receiver->id : 0,
- NULL, q_text);
+ q_header, q_text);
free(q_text);
+ free(q_header);
if (!result)
return -EIO;
@@ -459,10 +476,13 @@
}
/* retrieve the next unsent SMS with ID >= min_id */
-struct gsm_sms *db_sms_get_unsent(int min_id)
+struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id)
{
dbi_result result;
+ long long unsigned int sender_id, receiver_id;
struct gsm_sms *sms = malloc(sizeof(*sms));
+ char *text;
+ char buf[32];
if (!sms) {
free(sms);
@@ -476,8 +496,21 @@
free(sms);
return NULL;
}
+ sms->id = dbi_result_get_ulonglong(result, "id");
- /* FIXME: fill gsm_sms from database */
+ sender_id = dbi_result_get_ulonglong(result, "sender_id");
+ sprintf(buf, "%llu", sender_id);
+ sms->sender = db_get_subscriber(net, GSM_SUBSCRIBER_ID, buf);
+
+ receiver_id = dbi_result_get_ulonglong(result, "receiver_id");
+ sprintf(buf, "%llu", receiver_id);
+ sms->receiver = db_get_subscriber(net, GSM_SUBSCRIBER_ID, buf);
+
+ /* FIXME: fill header */
+
+ text = dbi_result_get_string(result, "text");
+ if (text)
+ strncpy(sms->text, text, sizeof(sms->text));
dbi_result_free(result);
return sms;
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index df4d3c6..44f8672 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -45,6 +45,7 @@
#include <openbsc/trau_frame.h>
#include <openbsc/trau_mux.h>
#include <openbsc/talloc.h>
+#include <openbsc/transaction.h>
#define GSM48_ALLOC_SIZE 1024
#define GSM48_ALLOC_HEADROOM 128
@@ -54,7 +55,6 @@
#define GSM_MAX_USERUSER 128
static void *tall_locop_ctx;
-static void *tall_trans_ctx;
static const struct tlv_definition rsl_att_tlvdef = {
.def = {
@@ -240,7 +240,7 @@
rep->flags |= MEAS_REP_F_BA1;
if (data[0] & 0x40)
rep->flags |= MEAS_REP_F_DTX;
- if (data[1] & 0x40)
+ if ((data[1] & 0x40) == 0x00)
rep->flags |= MEAS_REP_F_VALID;
rep->rxlev_full = data[0] & 0x3f;
@@ -292,7 +292,6 @@
static int gsm48_tx_simple(struct gsm_lchan *lchan,
u_int8_t pdisc, u_int8_t msg_type);
static void schedule_reject(struct gsm_lchan *lchan);
-void free_trans(struct gsm_trans *trans);
struct gsm_lai {
u_int16_t mcc;
@@ -392,9 +391,12 @@
release_loc_updating_req(lchan);
/* Free all transactions that are associated with the released lchan */
+ /* FIXME: this is not neccessarily the right thing to do, we should
+ * only set trans->lchan to NULL and wait for another lchan to be
+ * established to the same MM entity (phone/subscriber) */
llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
if (trans->lchan == lchan)
- free_trans(trans);
+ trans_free(trans);
}
return 0;
@@ -1129,6 +1131,8 @@
{
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm_lchan *lchan = msg->lchan;
+ struct gsm_bts *bts = lchan->ts->trx->bts;
+ struct gsm_network *net = bts->network;
u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
char mi_string[MI_SIZE];
@@ -1139,7 +1143,7 @@
switch (mi_type) {
case GSM_MI_TYPE_IMSI:
if (!lchan->subscr)
- lchan->subscr = db_create_subscriber(mi_string);
+ lchan->subscr = db_create_subscriber(net, mi_string);
if (lchan->loc_operation)
lchan->loc_operation->waiting_for_imsi = 0;
break;
@@ -1196,6 +1200,7 @@
struct gsm48_loc_upd_req *lu;
struct gsm_subscriber *subscr = NULL;
struct gsm_lchan *lchan = msg->lchan;
+ struct gsm_bts *bts = lchan->ts->trx->bts;
u_int8_t mi_type;
char mi_string[MI_SIZE];
int rc;
@@ -1230,7 +1235,7 @@
lchan->loc_operation->waiting_for_imei = 1;
/* look up subscriber based on IMSI */
- subscr = db_create_subscriber(mi_string);
+ subscr = db_create_subscriber(bts->network, mi_string);
break;
case GSM_MI_TYPE_TMSI:
DEBUGPC(DMM, "\n");
@@ -1239,7 +1244,7 @@
lchan->loc_operation->waiting_for_imei = 1;
/* look up the subscriber based on TMSI, request IMSI if it fails */
- subscr = subscr_get_by_tmsi(mi_string);
+ subscr = subscr_get_by_tmsi(bts->network, mi_string);
if (!subscr) {
/* send IDENTITY REQUEST message to get IMSI */
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
@@ -1421,6 +1426,7 @@
u_int8_t mi_type;
char mi_string[MI_SIZE];
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm_subscriber *subscr;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_service_request *req =
@@ -1455,7 +1461,7 @@
DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
req->cm_service_type, mi_type, mi_string);
- subscr = subscr_get_by_tmsi(mi_string);
+ subscr = subscr_get_by_tmsi(bts->network, mi_string);
/* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
if (!subscr)
@@ -1478,6 +1484,7 @@
static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
{
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_imsi_detach_ind *idi =
(struct gsm48_imsi_detach_ind *) gh->data;
@@ -1491,10 +1498,10 @@
switch (mi_type) {
case GSM_MI_TYPE_TMSI:
- subscr = subscr_get_by_tmsi(mi_string);
+ subscr = subscr_get_by_tmsi(bts->network, mi_string);
break;
case GSM_MI_TYPE_IMSI:
- subscr = subscr_get_by_imsi(mi_string);
+ subscr = subscr_get_by_imsi(bts->network, mi_string);
break;
case GSM_MI_TYPE_IMEI:
case GSM_MI_TYPE_IMEISV:
@@ -1574,6 +1581,7 @@
/* Receive a PAGING RESPONSE message from the MS */
static int gsm48_rr_rx_pag_resp(struct msgb *msg)
{
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t *classmark2_lv = gh->data + 1;
u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
@@ -1588,10 +1596,10 @@
mi_type, mi_string);
switch (mi_type) {
case GSM_MI_TYPE_TMSI:
- subscr = subscr_get_by_tmsi(mi_string);
+ subscr = subscr_get_by_tmsi(bts->network, mi_string);
break;
case GSM_MI_TYPE_IMSI:
- subscr = subscr_get_by_imsi(mi_string);
+ subscr = subscr_get_by_imsi(bts->network, mi_string);
break;
}
@@ -1789,9 +1797,9 @@
return;
DEBUGP(DCC, "new state %s -> %s\n",
- cc_state_names[trans->state], cc_state_names[state]);
+ cc_state_names[trans->cc.state], cc_state_names[state]);
- trans->state = state;
+ trans->cc.state = state;
}
static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
@@ -1831,10 +1839,10 @@
static void gsm48_stop_cc_timer(struct gsm_trans *trans)
{
- if (bsc_timer_pending(&trans->cc_timer)) {
- DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
- bsc_del_timer(&trans->cc_timer);
- trans->Tcurrent = 0;
+ if (bsc_timer_pending(&trans->cc.timer)) {
+ DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
+ bsc_del_timer(&trans->cc.timer);
+ trans->cc.Tcurrent = 0;
}
}
@@ -1883,49 +1891,23 @@
return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
}
-void free_trans(struct gsm_trans *trans)
+/* Call Control Specific transaction release.
+ * gets called by trans_free, DO NOT CALL YOURSELF! */
+void _gsm48_cc_trans_free(struct gsm_trans *trans)
{
- struct gsm_bts *bts;
-
gsm48_stop_cc_timer(trans);
/* send release to L4, if callref still exists */
if (trans->callref) {
/* Ressource unavailable */
- mncc_release_ind(trans->network, trans, trans->callref,
+ mncc_release_ind(trans->subscr->net, trans, trans->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
- if (trans->state != GSM_CSTATE_NULL)
- new_cc_state(trans, GSM_CSTATE_NULL);
}
-
- if (!trans->lchan && trans->subscr && trans->subscr->net) {
- /* Stop paging on all bts' */
- bts = NULL;
- do {
- bts = gsm_bts_by_lac(trans->subscr->net,
- trans->subscr->lac, bts);
- if (!bts)
- break;
- /* Stop paging */
- paging_request_stop(bts, trans->subscr, NULL);
- } while (1);
- }
-
- if (trans->lchan) {
- trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
- put_lchan(trans->lchan);
- }
-
- if (trans->subscr)
- subscr_put(trans->subscr);
-
- if (trans->state != GSM_CSTATE_NULL)
+ if (trans->cc.state != GSM_CSTATE_NULL)
new_cc_state(trans, GSM_CSTATE_NULL);
-
- llist_del(&trans->entry);
-
- talloc_free(trans);
+ if (trans->lchan)
+ trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
}
static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
@@ -1966,7 +1948,7 @@
use_lchan(lchan);
}
/* send SETUP request to called party */
- gsm48_cc_tx_setup(transt, &transt->cc_msg);
+ gsm48_cc_tx_setup(transt, &transt->cc.msg);
if (is_ipaccess_bts(lchan->ts->trx->bts))
rsl_ipacc_bind(lchan);
break;
@@ -1974,11 +1956,12 @@
DEBUGP(DCC, "Paging subscr %s expired!\n",
subscr->extension);
/* Temporarily out of order */
- mncc_release_ind(transt->network, transt, transt->callref,
+ mncc_release_ind(transt->subscr->net, transt,
+ transt->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_DEST_OOO);
transt->callref = 0;
- free_trans(transt);
+ trans_free(transt);
break;
}
}
@@ -2027,21 +2010,11 @@
return 0;
}
-static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
-{
- struct gsm_trans *trans;
- llist_for_each_entry(trans, &net->trans_list, entry) {
- if (trans->callref == callref)
- return trans;
- }
- return NULL;
-}
-
/* bridge channels of two transactions */
static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
{
- struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
- struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
+ struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
+ struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
if (!trans1 || !trans2)
return -EIO;
@@ -2059,7 +2032,7 @@
struct gsm_trans *trans;
/* Find callref */
- trans = get_trans_ref(net, data->callref);
+ trans = trans_find_by_callref(net, data->callref);
if (!trans)
return -EIO;
if (!trans->lchan)
@@ -2077,7 +2050,7 @@
struct gsm_trans *trans;
/* Find callref */
- trans = get_trans_ref(net, frame->callref);
+ trans = trans_find_by_callref(net, frame->callref);
if (!trans)
return -EIO;
if (!trans->lchan)
@@ -2116,7 +2089,7 @@
memset(&l4_rel, 0, sizeof(struct gsm_mncc));
l4_rel.callref = trans->callref;
- switch(trans->Tcurrent) {
+ switch(trans->cc.Tcurrent) {
case 0x303:
release = 1;
l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
@@ -2134,21 +2107,21 @@
l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
break;
case 0x308:
- if (!trans->T308_second) {
+ if (!trans->cc.T308_second) {
/* restart T308 a second time */
- gsm48_cc_tx_release(trans, &trans->cc_msg);
- trans->T308_second = 1;
+ gsm48_cc_tx_release(trans, &trans->cc.msg);
+ trans->cc.T308_second = 1;
break; /* stay in release state */
}
- free_trans(trans);
+ trans_free(trans);
return;
// release = 1;
// l4_cause = 14;
// break;
case 0x306:
release = 1;
- mo_cause = trans->cc_msg.cause.value;
- mo_location = trans->cc_msg.cause.location;
+ mo_cause = trans->cc.msg.cause.value;
+ mo_location = trans->cc.msg.cause.location;
break;
case 0x323:
disconnect = 1;
@@ -2159,7 +2132,7 @@
if (release && trans->callref) {
/* process release towards layer 4 */
- mncc_release_ind(trans->network, trans, trans->callref,
+ mncc_release_ind(trans->subscr->net, trans, trans->callref,
l4_location, l4_cause);
trans->callref = 0;
}
@@ -2167,15 +2140,15 @@
if (disconnect && trans->callref) {
/* process disconnect towards layer 4 */
mncc_set_cause(&l4_rel, l4_location, l4_cause);
- mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
+ mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
}
/* process disconnect towards mobile station */
if (disconnect || release) {
mncc_set_cause(&mo_rel, mo_location, mo_cause);
- mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
- mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
- mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
+ mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
+ mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
+ mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
mo_rel.cause.diag_len = 3;
if (disconnect)
@@ -2190,10 +2163,10 @@
int sec, int micro)
{
DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
- trans->cc_timer.cb = gsm48_cc_timeout;
- trans->cc_timer.data = trans;
- bsc_schedule_timer(&trans->cc_timer, sec, micro);
- trans->Tcurrent = current;
+ trans->cc.timer.cb = gsm48_cc_timeout;
+ trans->cc.timer.data = trans;
+ bsc_schedule_timer(&trans->cc.timer, sec, micro);
+ trans->cc.Tcurrent = current;
}
static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
@@ -2268,7 +2241,7 @@
new_cc_state(trans, GSM_CSTATE_INITIATED);
/* indicate setup to MNCC */
- mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
+ mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
return 0;
}
@@ -2289,16 +2262,16 @@
DEBUGP(DCC, "TX Setup with assigned transaction. "
"This is not allowed!\n");
/* Temporarily out of order */
- rc = mncc_release_ind(trans->network, trans, trans->callref,
+ rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
/* Get free transaction_id */
- llist_for_each_entry(transt, &trans->network->trans_list, entry) {
+ llist_for_each_entry(transt, &trans->subscr->net->trans_list, entry) {
/* Transaction of our lchan? */
if (transt->lchan == trans->lchan &&
transt->transaction_id != 0xff)
@@ -2307,11 +2280,11 @@
/* Assign free transaction ID */
if ((trans_id_mask & 0x007f) == 0x7f) {
/* no free transaction ID */
- rc = mncc_release_ind(trans->network, trans, trans->callref,
+ rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
for (i = 0; i < 7; i++) {
@@ -2398,7 +2371,8 @@
new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
- return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
+ &call_conf);
}
static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
@@ -2461,7 +2435,8 @@
new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
- return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
+ &alerting);
}
static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
@@ -2580,7 +2555,7 @@
new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
- return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
}
@@ -2594,7 +2569,7 @@
memset(&connect_ack, 0, sizeof(struct gsm_mncc));
connect_ack.callref = trans->callref;
- return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
&connect_ack);
}
@@ -2651,7 +2626,7 @@
TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
}
- return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
}
@@ -2695,7 +2670,7 @@
encode_useruser(msg, 0, &disc->useruser);
/* store disconnect cause for T306 expiry */
- memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
+ memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
@@ -2740,19 +2715,20 @@
TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
}
- if (trans->state == GSM_CSTATE_RELEASE_REQ) {
+ if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
/* release collision 5.4.5 */
- rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
+ rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
} else {
- rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
- GSM48_MT_CC_RELEASE_COMPL);
- rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
+ rc = gsm48_tx_simple(msg->lchan,
+ GSM48_PDISC_CC | trans->transaction_id,
+ GSM48_MT_CC_RELEASE_COMPL);
+ rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
}
new_cc_state(trans, GSM_CSTATE_NULL);
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
@@ -2782,10 +2758,10 @@
if (rel->fields & MNCC_F_USERUSER)
encode_useruser(msg, 0, &rel->useruser);
- trans->T308_second = 0;
- memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
+ trans->cc.T308_second = 0;
+ memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
- if (trans->state != GSM_CSTATE_RELEASE_REQ)
+ if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
return gsm48_sendmsg(msg);
@@ -2830,23 +2806,23 @@
}
if (trans->callref) {
- switch (trans->state) {
+ switch (trans->cc.state) {
case GSM_CSTATE_CALL_PRESENT:
- rc = mncc_recvmsg(trans->network, trans,
+ rc = mncc_recvmsg(trans->subscr->net, trans,
MNCC_REJ_IND, &rel);
break;
case GSM_CSTATE_RELEASE_REQ:
- rc = mncc_recvmsg(trans->network, trans,
+ rc = mncc_recvmsg(trans->subscr->net, trans,
MNCC_REL_CNF, &rel);
break;
default:
- rc = mncc_recvmsg(trans->network, trans,
+ rc = mncc_recvmsg(trans->subscr->net, trans,
MNCC_REL_IND, &rel);
}
}
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
@@ -2875,7 +2851,7 @@
if (rel->fields & MNCC_F_USERUSER)
encode_useruser(msg, 0, &rel->useruser);
- free_trans(trans);
+ trans_free(trans);
return gsm48_sendmsg(msg);
}
@@ -2903,7 +2879,7 @@
TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
}
- return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
}
static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
@@ -2928,7 +2904,7 @@
memset(&hold, 0, sizeof(struct gsm_mncc));
hold.callref = trans->callref;
- return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
}
static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
@@ -2968,7 +2944,8 @@
memset(&retrieve, 0, sizeof(struct gsm_mncc));
retrieve.callref = trans->callref;
- return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
+ &retrieve);
}
static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
@@ -3019,7 +2996,7 @@
TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
}
- return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
}
static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
@@ -3077,7 +3054,7 @@
memset(&dtmf, 0, sizeof(struct gsm_mncc));
dtmf.callref = trans->callref;
- return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
}
static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
@@ -3099,7 +3076,7 @@
new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
- return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
}
static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
@@ -3143,7 +3120,7 @@
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
}
static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
@@ -3191,7 +3168,7 @@
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
}
static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
@@ -3243,7 +3220,7 @@
if (payload_len >= 1)
decode_notify(¬ify.notify, gh->data);
- return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, ¬ify);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, ¬ify);
}
static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
@@ -3286,7 +3263,7 @@
if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
user.more = 1;
- return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
}
static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
@@ -3385,7 +3362,7 @@
rel.callref = data->callref;
/* Find callref */
- trans = get_trans_ref(net, data->callref);
+ trans = trans_find_by_callref(net, data->callref);
/* Callref unknown */
if (!trans) {
@@ -3410,9 +3387,10 @@
}
/* New transaction due to setup, find subscriber */
if (data->called.number[0])
- subscr = subscr_get_by_extension(data->called.number);
+ subscr = subscr_get_by_extension(net,
+ data->called.number);
else
- subscr = subscr_get_by_imsi(data->imsi);
+ subscr = subscr_get_by_imsi(net, data->imsi);
/* If subscriber is not found */
if (!subscr) {
DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
@@ -3437,7 +3415,8 @@
GSM48_CC_CAUSE_DEST_OOO);
}
/* Create transaction */
- if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
+ trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
+ if (!trans) {
DEBUGP(DCC, "No memory for trans.\n");
subscr_put(subscr);
/* Ressource unavailable */
@@ -3446,12 +3425,6 @@
GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
return -ENOMEM;
}
- trans->callref = data->callref;
- trans->network = net;
- trans->transaction_id = 0xff; /* unassigned */
- llist_add_tail(&trans->entry, &net->trans_list);
- /* Assign subscriber to transaction */
- trans->subscr = subscr;
/* Find lchan */
for (i = 0; i < net->num_bts; i++) {
bts = gsm_bts_num(net, i);
@@ -3487,7 +3460,7 @@
return 0;
}
/* store setup informations until paging was successfull */
- memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
+ memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
/* start paging subscriber on all BTS with her location */
subscr->net = net;
bts = NULL;
@@ -3525,7 +3498,7 @@
else
rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
@@ -3534,13 +3507,13 @@
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
trans->transaction_id,
(lchan->subscr)?(lchan->subscr->extension):"-",
- get_mncc_name(msg_type), trans->state,
- cc_state_names[trans->state]);
+ get_mncc_name(msg_type), trans->cc.state,
+ cc_state_names[trans->cc.state]);
/* Find function for current state and message */
for (i = 0; i < DOWNSLLEN; i++)
if ((msg_type == downstatelist[i].type)
- && ((1 << trans->state) & downstatelist[i].states))
+ && ((1 << trans->cc.state) & downstatelist[i].states))
break;
if (i == DOWNSLLEN) {
DEBUGP(DCC, "Message unhandled at this state.\n");
@@ -3613,8 +3586,7 @@
u_int8_t msg_type = gh->msg_type & 0xbf;
u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
struct gsm_lchan *lchan = msg->lchan;
- struct gsm_trans *trans = NULL, *transt;
- struct gsm_network *net = lchan->ts->trx->bts->network;
+ struct gsm_trans *trans = NULL;
int i, rc = 0;
if (msg_type & 0x80) {
@@ -3623,50 +3595,38 @@
}
/* Find transaction */
- llist_for_each_entry(transt, &net->trans_list, entry) {
- /* Transaction of our lchan? */
- if (transt->lchan == lchan
- && transt->transaction_id == transaction_id) {
- trans = transt;
- }
- }
-
+ trans = trans_find_by_id(lchan, transaction_id);
+
DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
"Received '%s' from MS in state %d (%s)\n",
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
- cc_msg_names[msg_type], trans?(trans->state):0,
- cc_state_names[trans?(trans->state):0]);
+ cc_msg_names[msg_type], trans?(trans->cc.state):0,
+ cc_state_names[trans?(trans->cc.state):0]);
/* Create transaction */
if (!trans) {
DEBUGP(DCC, "Unknown transaction ID %02x, "
"creating new trans.\n", transaction_id);
/* Create transaction */
- if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
+ trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
+ transaction_id, new_callref++);
+ if (!trans) {
DEBUGP(DCC, "No memory for trans.\n");
rc = gsm48_tx_simple(msg->lchan,
GSM48_PDISC_CC | transaction_id,
GSM48_MT_CC_RELEASE_COMPL);
return -ENOMEM;
}
- llist_add_tail(&trans->entry, &net->trans_list);
/* Assign transaction */
- trans->callref = new_callref++;
- trans->network = net;
- trans->transaction_id = transaction_id;
trans->lchan = lchan;
use_lchan(lchan);
- if (lchan->subscr) {
- trans->subscr = lchan->subscr;
- subscr_get(trans->subscr);
- }
}
/* find function for current state and message */
for (i = 0; i < DATASLLEN; i++)
if ((msg_type == datastatelist[i].type)
- && ((1 << trans->state) & datastatelist[i].states))
+ && ((1 << trans->cc.state) & datastatelist[i].states))
break;
if (i == DATASLLEN) {
DEBUGP(DCC, "Message unhandled at this state.\n");
@@ -3823,3 +3783,4 @@
return work;
}
+
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 1b622b1..5279291 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -55,7 +55,7 @@
"GSM 04.11");
}
-int gsm0411_sendmsg(struct msgb *msg)
+static int gsm411_sendmsg(struct msgb *msg)
{
if (msg->lchan)
msg->trx = msg->lchan->ts->trx;
@@ -65,6 +65,35 @@
return rsl_data_request(msg, 0);
}
+/* Prefix msg with a 04.08/04.11 CP header */
+static int gsm411_cp_sendmsg(struct msgb *msg, u_int8_t msg_type,
+ u_int8_t trans_id)
+{
+ struct gsm48_hdr *gh;
+
+ gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
+ /* Outgoing needs the highest bit set */
+ gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
+ gh->msg_type = msg_type;
+
+ return gsm411_sendmsg(msg);
+}
+
+/* Prefix msg with a RP-DATA header and send as CP-DATA */
+static int gsm411_rp_sendmsg(struct msgb *msg, u_int8_t rp_msg_type,
+ u_int8_t rp_msg_ref, u_int8_t cp_trans_id)
+{
+ struct gsm411_rp_hdr *rp;
+
+ /* GSM 04.11 RP-DATA header */
+ rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
+ rp->len = msg->len;
+ rp->msg_type = rp_msg_type;
+ rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
+
+ return gsm411_cp_sendmsg(msg, GSM411_MT_CP_DATA, cp_trans_id);
+}
+
#if 0
static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
@@ -144,16 +173,16 @@
{
if (db_sms_store(gsms) != 0) {
DEBUGP(DSMS, "Failed to store SMS in Database\n");
- talloc_free(sms);
- talloc_free(gsms);
- return -EIO;
+ return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
}
return 0;
}
-/* process an incoming TPDU (called from RP-DATA) */
+/* process an incoming TPDU (called from RP-DATA)
+ * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
static int gsm340_rx_tpdu(struct msgb *msg)
{
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
u_int8_t *smsp = msgb_sms(msg);
struct sms_submit *sms;
struct gsm_sms *gsms;
@@ -167,7 +196,7 @@
sms = talloc(tall_sms_ctx, struct sms_submit);
if (!sms)
- return -ENOMEM;
+ return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
memset(sms, 0, sizeof(*sms));
if (!tall_gsms_ctx)
@@ -177,7 +206,7 @@
gsms = talloc(tall_gsms_ctx, struct gsm_sms);
if (!gsms) {
talloc_free(sms);
- return -ENOMEM;
+ return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
}
memset(gsms, 0, sizeof(*gsms));
@@ -185,7 +214,7 @@
sms->mti = *smsp & 0x03;
sms->mms = !!(*smsp & 0x04);
sms->vpf = (*smsp & 0x18) >> 3;
- sms->sri = !!(*smsp & 0x20);
+ sms->srr = !!(*smsp & 0x20);
sms->udhi= !!(*smsp & 0x40);
sms->rp = !!(*smsp & 0x80);
@@ -196,7 +225,7 @@
da_len_bytes = 2 + *smsp/2 + *smsp%2;
if (da_len_bytes > 12) {
DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
- rc = -EIO;
+ rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
goto out;
}
memset(address_lv, 0, sizeof(address_lv));
@@ -249,21 +278,25 @@
"PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
"UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
- sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded : hexdump(sms->user_data, sms->ud_len));
+ sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded :
+ hexdump(sms->user_data, sms->ud_len));
dispatch_signal(SS_SMS, 0, sms);
+ /* now we've filled the 'sms' structure. Go on filling
+ * the gsms structure based on information from the sms */
+
gsms->sender = msg->lchan->subscr;
/* FIXME: sender refcount */
- /* determine gsms->receiver based on dialled number */
- gsms->receiver = subscr_get_by_extension(sms->dest_addr);
- if (!gsms->receiver) {
- rc = 1; /* cause 1: unknown subscriber */
- goto out;
- }
+ gsms->validity_minutes = gsm340_validity_period(sms);
+ /* determine gsms->receiver based on dialled number */
+ gsms->receiver = subscr_get_by_extension(bts->network, sms->dest_addr);
if (sms->user_data)
+ memcpy(gsms->header, sms->user_data, sms->ud_len);
+
+ if (sms->decoded)
strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
switch (sms->mti) {
@@ -274,12 +307,17 @@
case GSM340_SMS_COMMAND_MS2SC:
case GSM340_SMS_DELIVER_REP_MS2SC:
DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
+ rc = GSM411_RP_CAUSE_IE_NOTEXIST;
break;
default:
DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
+ rc = GSM411_RP_CAUSE_IE_NOTEXIST;
break;
}
+ if (!rc && !gsms->receiver)
+ rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
+
out:
talloc_free(gsms);
talloc_free(sms);
@@ -291,48 +329,26 @@
u_int8_t msg_ref)
{
struct msgb *msg = gsm411_msgb_alloc();
- struct gsm48_hdr *gh;
- struct gsm411_rp_hdr *rp;
msg->lchan = lchan;
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- // Outgoing needs the highest bit set
- gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
- gh->msg_type = GSM411_MT_CP_DATA;
-
- rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
- rp->len = 2;
- rp->msg_type = GSM411_MT_RP_ACK_MT;
- rp->msg_ref = msg_ref;
-
DEBUGP(DSMS, "TX: SMS RP ACK\n");
- return gsm0411_sendmsg(msg);
+ return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ACK_MT, msg_ref, trans_id);
}
static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
u_int8_t msg_ref, u_int8_t cause)
{
struct msgb *msg = gsm411_msgb_alloc();
- struct gsm48_hdr *gh;
- struct gsm411_rp_hdr *rp;
msg->lchan = lchan;
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- // Outgoing needs the highest bit set
- gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
- gh->msg_type = GSM411_MT_CP_DATA;
-
- rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
- rp->msg_type = GSM411_MT_RP_ERROR_MT;
- rp->msg_ref = msg_ref;
msgb_tv_put(msg, 1, cause);
DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
- return gsm0411_sendmsg(msg);
+ return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ERROR_MT, msg_ref, trans_id);
}
/* Receive a 04.11 TPDU inside RP-DATA / user data */
@@ -350,12 +366,13 @@
if (!dst_len || !dst || !tpdu_len || !tpdu) {
DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
+ gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref,
+ GSM411_RP_CAUSE_INV_MAND_INF);
return -EIO;
}
msg->smsh = tpdu;
DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
- //return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
rc = gsm340_rx_tpdu(msg);
if (rc == 0)
@@ -385,11 +402,42 @@
if (rpud_len)
rp_ud = &rph->data[1+src_len+1+dst_len+1];
- DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n", src_len, dst_len, rpud_len);
+ DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
+ src_len, dst_len, rpud_len);
return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
rpud_len, rp_ud);
}
+
+static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm411_rp_hdr *rph)
+{
+ /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
+ * successfully received a SMS. We can now safely mark it as
+ * transmitted */
+
+ /* we need to look-up the transaction based on rph->msg_ref to
+ * identify which particular RP_DATA/SMS-submit was ACKed */
+
+}
+
+static int gsm411_rx_rp_error(struct msgb *msg, struct gsm411_rp_hdr *rph)
+{
+ /* Error in response to MT RP_DATA, i.e. the MS did not
+ * successfully receive the SMS. We need to investigate
+ * the cause and take action depending on it */
+
+ /* we need to look-up the transaction based on rph->msg_ref to
+ * identify which particular RP_DATA/SMS-submit failed */
+
+}
+
+static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm411_rp_hdr *rph)
+{
+ /* MS tells us that it has memory for more SMS, we need
+ * to check if we have any pending messages for it and then
+ * transfer those */
+}
+
static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
{
struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
@@ -402,16 +450,17 @@
rc = gsm411_rx_rp_data(msg, rp_data);
break;
case GSM411_MT_RP_ACK_MO:
- /* Acnkowledgement to MT RP_DATA */
+ rc = gsm411_rx_rp_ack(msg, rp_data);
+ break;
case GSM411_MT_RP_ERROR_MO:
- /* Error in response to MT RP_DATA */
+ rc = gsm411_rx_rp_error(msg, rp_data);
+ break;
case GSM411_MT_RP_SMMA_MO:
- /* MS tells us that it has memory for more SMS, we need
- * to check if we have any pending messages for it and then
- * transfer those */
+ rc = gsm411_rx_rp_smma(msg, rp_data);
DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
break;
default:
+ /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
break;
}
@@ -469,32 +518,26 @@
int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
{
struct msgb *msg = gsm411_msgb_alloc();
- struct gsm48_hdr *gh;
- struct gsm411_rp_hdr *rp;
u_int8_t *data;
+ u_int8_t msg_ref = 42;
+ u_int8_t trans_id = 23;
msg->lchan = lchan;
- gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_SMS;
- gh->msg_type = GSM411_MT_CP_DATA;
-
- rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
- rp->len = sizeof(tpdu_test) + 10;
- rp->msg_type = GSM411_MT_RP_DATA_MT;
- rp->msg_ref = 42; /* FIXME: Choose randomly */
- /* Hardcode OA for now */
+ /* Hardcode Originating Address for now */
data = (u_int8_t *)msgb_put(msg, 8);
- data[0] = 0x07;
- data[1] = 0x91;
- data[2] = 0x44;
+ data[0] = 0x07; /* originator length == 7 */
+ data[1] = 0x91; /* type of number: international, ISDN */
+ data[2] = 0x44; /* 447785016005 */
data[3] = 0x77;
data[4] = 0x58;
data[5] = 0x10;
data[6] = 0x06;
data[7] = 0x50;
+
+ /* Hardcoded Destination Address */
data = (u_int8_t *)msgb_put(msg, 1);
- data[0] = 0;
+ data[0] = 0; /* destination length == 0 */
/* FIXME: Hardcoded for now */
//smslen = gsm0411_tpdu_from_sms(tpdu, sms);
@@ -510,5 +553,5 @@
DEBUGP(DSMS, "TX: SMS SUBMIT\n");
- return gsm0411_sendmsg(msg);
+ return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
}
diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c
index a323d4e..60dec43 100644
--- a/openbsc/src/gsm_subscriber.c
+++ b/openbsc/src/gsm_subscriber.c
@@ -126,7 +126,8 @@
talloc_free(subscr);
}
-struct gsm_subscriber *subscr_get_by_tmsi(const char *tmsi)
+struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net,
+ const char *tmsi)
{
struct gsm_subscriber *subscr;
@@ -136,10 +137,11 @@
return subscr_get(subscr);
}
- return db_get_subscriber(GSM_SUBSCRIBER_TMSI, tmsi);
+ return db_get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi);
}
-struct gsm_subscriber *subscr_get_by_imsi(const char *imsi)
+struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net,
+ const char *imsi)
{
struct gsm_subscriber *subscr;
@@ -148,10 +150,11 @@
return subscr_get(subscr);
}
- return db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi);
+ return db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi);
}
-struct gsm_subscriber *subscr_get_by_extension(const char *ext)
+struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
+ const char *ext)
{
struct gsm_subscriber *subscr;
@@ -160,7 +163,7 @@
return subscr_get(subscr);
}
- return db_get_subscriber(GSM_SUBSCRIBER_EXTENSION, ext);
+ return db_get_subscriber(net, GSM_SUBSCRIBER_EXTENSION, ext);
}
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason)
@@ -168,6 +171,7 @@
/* FIXME: Migrate pending requests from one BSC to another */
switch (reason) {
case GSM_SUBSCRIBER_UPDATE_ATTACHED:
+ s->net = bts->network;
/* Indicate "attached to LAC" */
s->lac = bts->location_area_code;
break;
@@ -175,7 +179,6 @@
/* Only detach if we are currently in this area */
if (bts->location_area_code == s->lac)
s->lac = 0;
-
break;
default:
fprintf(stderr, "subscr_update with unknown reason: %d\n",
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index 4626890..11b2ff6 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -589,7 +589,7 @@
const char *imsi = argv[0];
struct gsm_subscriber *subscr;
- subscr = subscr_get_by_imsi(imsi);
+ subscr = subscr_get_by_imsi(gsmnet, imsi);
if (!subscr) {
vty_out(vty, "%% No subscriber for IMSI %s%s",
imsi, VTY_NEWLINE);
@@ -855,7 +855,7 @@
if (argc >= 1) {
imsi = argv[0];
- subscr = subscr_get_by_imsi(imsi);
+ subscr = subscr_get_by_imsi(gsmnet, imsi);
if (!subscr) {
vty_out(vty, "%% unknown subscriber%s",
VTY_NEWLINE);