aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-07-05 14:02:46 +0200
committerHarald Welte <laforge@gnumonks.org>2009-07-05 14:02:46 +0200
commitb9c758b2ac120a8f45c7c0a8b64429eb6105a9c7 (patch)
treeb83e04b679cc601217aadeaed2f7e9859da3bcfe /openbsc
parent5a691b52902ce383f87f5942cc4d1b44fc0176b6 (diff)
more SMS improvements
* describe data structures in gsm_04_11.h * increae LCHAN RELEASE TIMEOUT for case of long SMS * convert header field in sql table from NUMERIC to BLOB * initial handling for validity period * send RP ERROR messages with meaningful RP CAUSE in case of error
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/gsm_04_11.h50
-rw-r--r--openbsc/include/openbsc/gsm_data.h4
-rw-r--r--openbsc/src/db.c8
-rw-r--r--openbsc/src/gsm_04_11.c81
-rw-r--r--openbsc/src/gsm_subscriber.c1
5 files changed, 92 insertions, 52 deletions
diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h
index 51c37f016..4f4535786 100644
--- a/openbsc/include/openbsc/gsm_04_11.h
+++ b/openbsc/include/openbsc/gsm_04_11.h
@@ -92,20 +92,20 @@ enum sms_alphabet {
/* 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;
@@ -187,20 +187,20 @@ struct sms_submit {
/* 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;
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index af2e22c5a..11176d6d6 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -74,7 +74,7 @@ typedef int gsm_cbfn(unsigned int hooknum,
* 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", \
@@ -381,6 +381,8 @@ struct gsm_sms {
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/src/db.c b/openbsc/src/db.c
index 600699ae7..1bcd10175 100644
--- a/openbsc/src/db.c
+++ b/openbsc/src/db.c
@@ -75,7 +75,7 @@ static char *create_stmts[] = {
"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 ("
@@ -402,16 +402,20 @@ int db_sms_store(struct gsm_sms *sms)
{
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;
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 351a5fc50..68ccec64c 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -173,14 +173,13 @@ static int gsm340_rx_sms_submit(struct msgb *msg, struct sms_submit *sms,
{
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)
{
u_int8_t *smsp = msgb_sms(msg);
@@ -196,7 +195,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
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)
@@ -206,7 +205,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
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));
@@ -214,7 +213,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
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);
@@ -225,7 +224,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
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));
@@ -278,21 +277,25 @@ static int gsm340_rx_tpdu(struct msgb *msg)
"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 */
+ gsms->validity_minutes = gsm340_validity_period(sms);
+
/* 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;
- }
-
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) {
@@ -303,12 +306,17 @@ static int gsm340_rx_tpdu(struct msgb *msg)
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);
@@ -357,12 +365,13 @@ static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
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)
@@ -392,11 +401,36 @@ static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
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 */
+
+}
+
+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 */
+
+}
+
+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;
@@ -409,16 +443,17 @@ static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
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;
}
@@ -485,8 +520,8 @@ int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
/* Hardcode Originating Address for now */
data = (u_int8_t *)msgb_put(msg, 8);
data[0] = 0x07; /* originator length == 7 */
- data[1] = 0x91; /* type of number */
- data[2] = 0x44;
+ data[1] = 0x91; /* type of number: international, ISDN */
+ data[2] = 0x44; /* 447785016005 */
data[3] = 0x77;
data[4] = 0x58;
data[5] = 0x10;
diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c
index a323d4e87..32f436f28 100644
--- a/openbsc/src/gsm_subscriber.c
+++ b/openbsc/src/gsm_subscriber.c
@@ -175,7 +175,6 @@ int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason)
/* 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",