[PATCH]: Implement SMS decoding
Gianni Tedesco
gianni at scaramanga.co.uk
Thu May 12 04:27:15 CEST 2011
Hi,
Attached patch implements SMS decoding. Right now it just logs it all to
DMM (when I tried DSMS I didn't get any output?!). What remains is to
plumb this through to mobile so that the messages can be displayed over
a vty and also to send a response other than
GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED - but I'm not sure what needs to
happen here.
Is anyone else working in this area?
Gianni
commit a244cccb6f7600cb867e4949926cc7d877b58f31
Author: Gianni Tedesco <gianni at scaramanga.co.uk>
Date: Thu May 12 03:24:19 2011 +0100
Implement SMS decoding
diff --git a/src/host/layer23/src/mobile/Makefile.am b/src/host/layer23/src/mobile/Makefile.am
index fb0423e..60e8d23 100644
--- a/src/host/layer23/src/mobile/Makefile.am
+++ b/src/host/layer23/src/mobile/Makefile.am
@@ -4,7 +4,7 @@ LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOG
noinst_LIBRARIES = libmobile.a
libmobile_a_SOURCES = gsm322.c gsm48_cc.c gsm48_mm.c gsm48_rr.c \
- mnccms.c settings.c subscriber.c support.c \
+ gsm48_sms.c mnccms.c settings.c subscriber.c support.c \
transaction.c vty_interface.c
bin_PROGRAMS = mobile
diff --git a/src/host/layer23/src/mobile/gsm48_mm.c b/src/host/layer23/src/mobile/gsm48_mm.c
index bf5bbc2..84069f3 100644
--- a/src/host/layer23/src/mobile/gsm48_mm.c
+++ b/src/host/layer23/src/mobile/gsm48_mm.c
@@ -36,6 +36,7 @@
#include <osmocom/bb/common/networks.h>
#include <osmocom/bb/common/l1ctl.h>
#include <osmocom/bb/mobile/gsm48_cc.h>
+#include <osmocom/bb/mobile/gsm48_sms.h>
#include <osmocom/bb/mobile/app_mobile.h>
extern void *l23_ctx;
@@ -737,10 +738,10 @@ int gsm48_mmxx_dequeue(struct osmocom_ms *ms)
case GSM48_MMSS_CLASS:
gsm48_rcv_ss(ms, msg);
break;
+#endif
case GSM48_MMSMS_CLASS:
gsm48_rcv_sms(ms, msg);
break;
-#endif
}
msgb_free(msg);
work = 1; /* work done */
@@ -3847,9 +3848,10 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
case GSM48_PDISC_NC_SS:
return gsm48_rcv_ss(ms, msg);
- case GSM48_PDISC_SMS:
- return gsm48_rcv_sms(ms, msg);
#endif
+ case GSM48_PDISC_SMS:
+ LOGP(DMM, LOGL_NOTICE, "SMS PDISC = 0x%.2x\n", GSM48_PDISC_SMS);
+ gsm48_rcv_sms(ms, msg);
default:
LOGP(DMM, LOGL_NOTICE, "Protocol type 0x%02x unsupported.\n",
diff --git a/src/host/layer23/src/mobile/gsm48_sms.c b/src/host/layer23/src/mobile/gsm48_sms.c
new file mode 100644
index 0000000..63b1965
--- /dev/null
+++ b/src/host/layer23/src/mobile/gsm48_sms.c
@@ -0,0 +1,306 @@
+/*
+ * (C) 2010 by Andreas Eversberg <jolly at eversberg.eu>
+ * (C) 2011 by Gianni Tedesco <gianni at scaramanga.co.uk>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm48.h>
+#include <osmocom/core/talloc.h>
+
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/common/networks.h>
+#include <osmocom/bb/common/l1ctl.h>
+#include <osmocom/bb/mobile/gsm48_sms.h>
+#include <osmocom/bb/mobile/app_mobile.h>
+
+#define CP_DATA 1
+
+#define RP_DATA 1
+#define RP_ACK 3
+#define RP_ERROR 5
+
+#define TP_MTI_MASK 3
+#define SMS_DELIVER 0
+#define SMS_SUBMIT_REPORT 1
+#define SMS_STATUS_REPORT 2
+
+#define TP_RP 0x80
+#define TP_UDHI 0x40
+#define TP_SRI 0x20
+#define TP_MMS 0x04
+
+static void decode_7bit(const uint8_t *inp, size_t octets, size_t len)
+{
+ uint8_t out[len + 1];
+ unsigned int i;
+
+ for(i = 0; i <= len; i++) {
+ int ipos = i - (i >> 3);
+ int offset = (i & 0x7);
+
+ out[i] = (inp[ipos] & (0x7F >> offset)) << offset;
+ if( 0 == offset )
+ continue;
+
+ out[i] |= (inp[ipos - 1] &
+ (0x7F << (8 - offset)) & 0xFF) >> (8 - offset);
+ }
+
+ out[len] = '\0';
+ LOGP(DMM, LOGL_NOTICE, "SMS: \"%s\"\n", out);
+}
+
+static uint8_t hi_nibble(uint8_t byte)
+{
+ return byte >> 4;
+}
+
+static uint8_t lo_nibble(uint8_t byte)
+{
+ return byte & 0xf;
+}
+
+static int parse_address(struct msgb *msg, int rp, const char *name)
+{
+ uint8_t len, type;
+
+ if ( !msg->len )
+ return -EPROTO;
+
+ len = msgb_get_u8(msg);
+ if ( !len )
+ return 0;
+
+ type = msgb_get_u8(msg);
+
+ if ( rp ) {
+ /* for RP address, len is in bytes including type field */
+ len = len - 1;
+ }else{
+ /* TP address is in BCD digits, not including type field */
+ len = len / 2;
+ }
+
+ if ( msg->len < len )
+ return -EPROTO;
+
+ LOGP(DMM, LOGL_NOTICE, "%s: type=0x%.2x %s\n",
+ name, type, hexdump(msg->data, len));
+
+ msgb_pull(msg, len);
+ return 0;
+}
+
+static int parse_timestamp(struct msgb *msg, const char *name)
+{
+ if ( msg->len < 7 )
+ return -EPROTO;
+ LOGP(DMM, LOGL_NOTICE,
+ "%s: 20%1x%1x-%1x%1x-%1x%1x %1x%1x:%1x%1x:%1x%1x\n",
+ name,
+ lo_nibble(msg->data[0]),
+ hi_nibble(msg->data[0]),
+ lo_nibble(msg->data[1]),
+ hi_nibble(msg->data[1]),
+ lo_nibble(msg->data[2]),
+ hi_nibble(msg->data[2]),
+ lo_nibble(msg->data[3]),
+ hi_nibble(msg->data[3]),
+ lo_nibble(msg->data[4]),
+ hi_nibble(msg->data[4]),
+ lo_nibble(msg->data[5]),
+ hi_nibble(msg->data[5]));
+ msgb_pull(msg, 7);
+ return 0;
+}
+static int sms_deliver(struct osmocom_ms *ms, struct msgb *msg, uint8_t b)
+{
+ uint8_t tp_pid, tp_dcs, tp_udlen;
+ int rc;
+
+ if ( !(b & TP_MMS) )
+ LOGP(DMM, LOGL_NOTICE, "SMS-DELIVER: More messages to send.\n");
+
+ rc = parse_address(msg, 0, "TP-Originating");
+ if ( rc )
+ return -EPROTO;
+
+ if ( msg->len < 2 )
+ return -EPROTO;
+
+ tp_pid = msgb_get_u8(msg);
+ tp_dcs = msgb_get_u8(msg);
+ LOGP(DMM, LOGL_NOTICE, "TP-PID: 0x%.2x\n", tp_pid);
+ LOGP(DMM, LOGL_NOTICE, "TP-DCS: 0x%.2x\n", tp_dcs);
+
+ rc = parse_timestamp(msg, "TP-Service-Center-Time-Stamp");
+ if ( rc )
+ return -EPROTO;
+
+ if ( !msg->len )
+ return -EPROTO;
+ tp_udlen = msgb_get_u8(msg);
+
+ /* check for unknown data coding scheme */
+ if (tp_dcs)
+ return 0;
+
+ decode_7bit(msg->data, msg->len, tp_udlen);
+ return 0;
+}
+
+static int sms_tpdu_decode(struct osmocom_ms *ms, struct msgb *msg)
+{
+ uint8_t tp_mti;
+
+ if ( !msg->len )
+ return 0;
+ tp_mti = msgb_get_u8(msg);
+
+ switch(tp_mti & TP_MTI_MASK) {
+ case SMS_DELIVER:
+ return sms_deliver(ms, msg, tp_mti);
+ case SMS_SUBMIT_REPORT:
+ LOGP(DMM, LOGL_NOTICE, "Received SMS-SUBMIT-REPORT: %s\n",
+ hexdump(msg->data, msg->len));
+ break;
+ case SMS_STATUS_REPORT:
+ LOGP(DMM, LOGL_NOTICE, "Received SMS-STATUS-REPORT: %s\n",
+ hexdump(msg->data, msg->len));
+ break;
+ default:
+ LOGP(DMM, LOGL_NOTICE, "Reserved MTI: 0x%.2x\n",
+ tp_mti);
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+static int rp_data_decode(struct osmocom_ms *ms, struct msgb *msg, uint8_t ref)
+{
+ static const char * const str[2] = {"RP-Origination", "RP-Destination"};
+ unsigned int i;
+ uint8_t tpdu_len;
+
+ LOGP(DMM, LOGL_NOTICE, "Received RP-DATA: ref %d\n", ref);
+
+ for(i = 0; i < 2; i++) {
+ int rc;
+
+ rc = parse_address(msg, 1, str[i]);
+ if ( rc )
+ return -EPROTO;
+ }
+
+ if ( !msg->len )
+ return -EPROTO;
+ tpdu_len = msgb_get_u8(msg);
+ if ( tpdu_len < msg->len )
+ return -EPROTO;
+ if ( tpdu_len < msg->len ) {
+ LOGP(DMM, LOGL_NOTICE, "RP-DATA: %u trailing bytes: %s\n",
+ msg->len - tpdu_len,
+ hexdump(msg->data + tpdu_len, msg->len - tpdu_len));
+ msg->len = tpdu_len;
+ }
+
+ /* TODO: pass in reference, and src/dst addresses */
+ return sms_tpdu_decode(ms, msg);
+}
+
+static int rp_decode(struct osmocom_ms *ms, struct msgb *msg)
+{
+ uint8_t rp_mt, rp_ref;
+
+ if ( msg->len < 2 )
+ return -EPROTO;
+
+ rp_mt = msgb_get_u8(msg);
+ rp_ref = msgb_get_u8(msg);
+
+ switch(rp_mt) {
+ case RP_DATA:
+ return rp_data_decode(ms, msg, rp_ref);
+ case RP_ACK:
+ LOGP(DMM, LOGL_NOTICE, "Received RP-ACK: %s\n",
+ hexdump(msg->data, msg->len));
+ return -ENOTSUP;
+ case RP_ERROR:
+ LOGP(DMM, LOGL_NOTICE, "Received RP-ERROR: %s\n",
+ hexdump(msg->data, msg->len));
+ return -ENOTSUP;
+ default:
+ LOGP(DMM, LOGL_NOTICE, "Bad RP Message-type: 0x%.2x\n", rp_mt);
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+static int cp_data(struct osmocom_ms *ms, struct msgb *msg)
+{
+ uint8_t len;
+
+ if ( !msg->len )
+ return -EPROTO;
+ len = msgb_get_u8(msg);
+ if ( len != msg->len ) {
+ LOGP(DMM, LOGL_NOTICE, "CP-DATA: size mismatch "
+ "%u != %u bytes\n", len, msg->len);
+ }else{
+ LOGP(DMM, LOGL_NOTICE, "CP-DATA: %u bytes\n", len);
+ }
+
+ return rp_decode(ms, msg);
+}
+
+int gsm48_rcv_sms(struct osmocom_ms *ms, struct msgb *msg)
+{
+ uint8_t cp_type;
+
+ LOGP(DMM, LOGL_NOTICE, "Received SMS: %s\n",
+ hexdump(msg->data, msg->len));
+
+ if ( msg->len < 2)
+ return -EPROTO;
+
+ msgb_pull(msg, 1); /* protocol discriminator */
+ cp_type = msgb_get_u8(msg);
+
+ switch(cp_type) {
+ case CP_DATA:
+ return cp_data(ms, msg);
+ default:
+ LOGP(DMM, LOGL_NOTICE, "Unknown SMS type: 0x%.2x\n", cp_type);
+ return 0;
+ }
+
+ return 0;
+}
More information about the baseband-devel
mailing list