diff options
-rw-r--r-- | openbsc/include/openbsc/gsm_04_11.h | 50 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 4 | ||||
-rw-r--r-- | openbsc/src/db.c | 8 | ||||
-rw-r--r-- | openbsc/src/gsm_04_11.c | 81 | ||||
-rw-r--r-- | openbsc/src/gsm_subscriber.c | 1 |
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", |