summaryrefslogtreecommitdiff
path: root/gsmdecode/src/data_out.c
diff options
context:
space:
mode:
Diffstat (limited to 'gsmdecode/src/data_out.c')
-rw-r--r--gsmdecode/src/data_out.c3508
1 files changed, 3508 insertions, 0 deletions
diff --git a/gsmdecode/src/data_out.c b/gsmdecode/src/data_out.c
new file mode 100644
index 0000000..a419f58
--- /dev/null
+++ b/gsmdecode/src/data_out.c
@@ -0,0 +1,3508 @@
+/*
+ * TODO: memcpy for concatendated sms is unchecked.
+ */
+#include "common.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+//#include <arpa/inet.h>
+//#include <netinet/in.h>
+#include "id_list.h"
+#include "gsm_desc.h"
+
+#define OUTF(a...) do { \
+ printf(" %3d: %02x ", (int)(data - start), data[0]); \
+ printf(a); \
+} while (0)
+
+#define OUT(a...) do { \
+ printf(a); \
+} while (0)
+
+#define RETTRUNK() do { \
+ printf("%s:%d TRUNKATED (0x%p - 0x%p)\n", __func__, __LINE__, data, end); \
+ return; \
+} while (0)
+
+extern struct _opt opt;
+
+static void l2_rrm();
+static void l2_sms();
+static void l2_cc();
+static void l2_RRsystemInfo1();
+static void l2_MccMncLac();
+static void l2_RRsystemInfo2();
+//static void l2_RRsystemInfo2ter();
+static void l2_RRsystemInfo3C();
+static void l2_RRsystemInfo4C();
+static void l2_RRsystemInfo6();
+static void l2_RRsystemInfo13C();
+static void l2_RRimmediateAssTBFC();
+static void l2_RRassignCommand();
+static void l2_RRassignComplete();
+static void l2_RRpagingrequest1();
+static void l2_RRpagingrequest2();
+static void l2_RRpagingrequest3();
+static void l2_RRimmediateAssignment();
+static void l2_RRimmAssTBFDirEncHoChaC();
+static void l2_MobId();
+static void l2_mmm();
+static void l2_HoppingChannel();
+static void l2_HoppingChannelC();
+static void l2_SingleChannel();
+static void l2_SingleChannelC();
+static void l2_HoppingChannelAssCom();
+static void l2_SingleChannelAssCom();
+static void l2_MobileAllocation();
+static void l2_BcchAllocation();
+static void l2_TmsiReallocCommand();
+static void l2_RachControlParameters();
+static void l2_bcc();
+static void l2_Bbis();
+static void l2_ChannelRelease();
+static void l2_MMcmServiceRequest();
+static void l2_RRciphModCmd();
+static void l2_RRciphModCompl();
+static void l2_RRpagingresponse();
+static void l2_RRclassmarkChange();
+static void l2_NonCallSS();
+static void l2_FacilityRegister();
+static void l2_FacilityInvoke();
+static void l2_Facility();
+static void l2_FacilityReturnResult();
+static void l2_UssRequest();
+static void l2_UssData();
+static void l2_CCReleaseComplete();
+
+static void l2_ChannelNeeded(char *str, unsigned char ch);
+static void l2_MNCC(const char *str, unsigned char a, unsigned char b, unsigned char c);
+
+static char *BitRow(unsigned char c, int pos);
+static char *PageMode(unsigned char mode);
+static char *BitRowFill(unsigned char c, unsigned char mask);
+
+static void dcch_address();
+static void dcch_control();
+static void ControlChannelDescription();
+static void CellOptionsBcch();
+static void CellSelectionParameters();
+static void RequestReference();
+static void TimingAdvance();
+static void StartingTime();
+static void TypeOfIdentity();
+static void l2_NeighbourCellDescription();
+static void CellIdentity();
+static void MSClassMarkTwo();
+static void MSClassMarkOne();
+static void ClassMarkThree();
+static void cpData();
+static void Address(const char *str);
+static void TPAddress(const char *str);
+static void ChannelDescriptionTwo();
+static void CCalerting();
+static void CCsetup();
+static void ProgressIndicator();
+static void Cause();
+static void SmsProtocolDataValidity();
+static void BearerCap();
+static void BCDNumber();
+static void AuthenticationRequest();
+static void AuthenticationResponse();
+static void sms_dcs();
+static void sms_udh();
+static void sms_default_alphabet();
+static void SmscTimestamp();
+static void simdatadownload();
+static void LocationUpdateRequest();
+static void MultiSupportTwo();
+static void MeasurmentReport();
+
+static const unsigned char *start;
+static const unsigned char *data;
+static const unsigned char *end;
+
+struct _nfo
+{
+ unsigned int flags;
+ unsigned char seq_counter;
+ unsigned char sapi;
+};
+#define GSMSP_NFO_SMS (0x01)
+#define GSMSP_NFO_SEGMENTATION (0x02)
+#define GSMSP_NFO_UDHI (0x04)
+#define GSMSP_NFO_DEFAULTALPHABET (0x08)
+#define GSMSP_NFO_SIMDATADL (0x10) /* Sim Data Download */
+#define GSMSP_NFO_SMSCON (0x20) /* Concatenated SMS */
+#define GSMSP_NFO_LASTSMSCHUNK (0x40)
+
+static struct _nfo nfo;
+
+#if 0
+struct _sms
+{
+ unsigned char buf[248 + 3];
+ unsigned char *ptr;
+};
+#endif
+
+/* For concatenating SMS'es */
+struct _sms_con
+{
+ unsigned char buf[8192];
+ unsigned char *ptr;
+};
+
+struct _con
+{
+ unsigned char buf[248 + 3];
+ unsigned char *ptr;
+};
+/* Is initialized to 0 (do not remove from .bss) */
+static struct _sms_con sms_con;
+
+struct _con con[8];
+struct _con *conptr;
+
+
+
+/*
+ * B-format (and also A-Format)
+ */
+void
+l2_data_out_B(int fn, const unsigned char *input_data, int len)
+{
+ const unsigned char *from;
+ data = input_data;
+ start = data;
+ end = data + len;
+ HEXDUMPF(data, 23 /*len*/, "Format B DATA\n");
+ /* Need at least 3 octets */
+ if (data + 2 >= end)
+ RETTRUNK();
+
+ memset(&nfo, 0, sizeof nfo);
+ dcch_address();
+ data++;
+ dcch_control();
+ data++;
+ /* FIXME: Why is extended length always set to 1? */
+ OUTF("%s EL, Extended Length: %s\n", BitRow(data[0], 0), (data[0] & 1)?"y":"n");
+ OUTF("%s M, segmentation: %c\n", BitRow(data[0], 1), ((data[0] >> 1) & 1)?'Y':'N');
+ if ((data[0] >> 1) & 1)
+ nfo.flags |= GSMSP_NFO_SEGMENTATION;
+
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xfc), data[0] >> 2);
+ if (data + (data[0] >> 2) < end)
+ end = data + (data[0] >> 2) + 1;
+
+ data++;
+ if (data >= end)
+ return;
+
+ /* Initialization. have to do this only once but there
+ * is no better place to do it atm
+ */
+ if (conptr->ptr == NULL)
+ conptr->ptr = conptr->buf;
+
+ /* Chunk of a fragmented. */
+ /* All SMS type messages go into the same buffer.
+ * Other segmented messages are currently not supported.
+ */
+ //if (nfo.flags & GSMSP_NFO_SMS)
+ if ((conptr->ptr > conptr->buf) || (nfo.flags & GSMSP_NFO_SEGMENTATION))
+ {
+ from = data;
+
+ if (conptr->ptr + (end - data) < conptr->buf + sizeof conptr->buf)
+ {
+ memcpy(conptr->ptr, data, end - data);
+ conptr->ptr += (end - data);
+ } else {
+ OUTF("ERROR, buffer to small!!!\n");
+ OUTF("buf: %p, ptr %p, filled: %d len %d\n", conptr->buf, conptr->ptr, conptr->ptr - conptr->buf, end - from);
+ }
+ }
+
+ if (nfo.flags & GSMSP_NFO_SEGMENTATION)
+ {
+ OUTF("-------- [MORE DATA FOLLOWS...]\n");
+ /* More fragments follow. No need to decode yet */
+ return;
+ }
+
+ /* Here: segmentation == No */
+ /* See if we get an SMS message and if this was the last fragment */
+ if (conptr->ptr > conptr->buf)
+ {
+ start = conptr->buf;
+ data = conptr->buf;
+ end = conptr->ptr;
+ if (nfo.flags & GSMSP_NFO_SMS)
+ HEXDUMPF(data, end - data, "Format SMS data\n");
+ else
+ HEXDUMPF(data, end - data, "Format Bbis (RR, MM or CC)\n");
+ l2_Bbis();
+ conptr->ptr = conptr->buf;
+ return;
+ }
+
+
+ l2_Bbis();
+
+}
+
+static void
+dcch_control()
+{
+ if ((data[0] & 0x03) != 3)
+ {
+ if ((data[0] & 1) == 0)
+ {
+ OUTF("-------0 Information Frame\n");
+ OUTF("%s N(S), Sequence counter: %u\n", BitRowFill(data[0], 0x0e), (data[0] >> 1) & 0x07);
+ nfo.seq_counter = ((data[0] >> 1) & 0x07);
+ OUTF("%s P\n", BitRow(data[0], 4));
+ } else if ((data[0] & 0x03) == 1) {
+ OUTF("------01 Supvervisory Frame\n");
+ if (((data[0] >> 2) & 0x03) == 0)
+ OUTF("----00-- RR Frame (Receive ready)\n");
+ else if (((data[0] >> 2) & 0x03) == 1)
+ OUTF("----01-- RNR Frame (Receive not ready)\n");
+ else if (((data[0] >> 2) & 0x03) == 2)
+ OUTF("----10-- REJ Frame (REJect)\n");
+ else
+ OUTF("----11-- UNKNOWN\n");
+ OUTF("%s Poll/Final bit (P/F)\n", BitRow(data[0], 4));
+ }
+ OUTF("%s N(R), Retransmission counter: %u\n", BitRowFill(data[0], 0xe0), (data[0] >> 5) & 0x07);
+ return;
+ }
+ OUTF("------11 Unnumbered Frame\n");
+ switch (data[0] & 0xec) /* 11101100 */
+ {
+ case 0x2c: /* 001-11-- According to J.Goeller this is SABM */
+ case 0x6c: /* 011-11-- */
+ OUTF("%s P\n", BitRow(data[0], 4));
+ OUTF("011-11-- SABM frame (Set asynchonous balance mode)\n");
+ break;
+ case 0x0c: /* 000-11-- */
+ OUTF("%s F\n", BitRow(data[0], 4));
+ OUTF("000-11-- DM frame (Disconnected mode)\n");
+ break;
+ case 0x00:
+ OUTF("%s P\n", BitRow(data[0], 4));
+ OUTF("000-00-- UI frame (Unnumbered information)\n");
+ break;
+ case 0x40:
+ OUTF("%s P\n", BitRow(data[0], 4));
+ OUTF("010-00-- DISC frame (DISConnect)\n");
+ break;
+ case 0x60:
+ OUTF("%s P\n", BitRow(data[0], 4));
+ OUTF("011-00-- UA frame (Unnumbered acknowledgement)\n");
+ break;
+ default:
+ OUTF("%s P/F\n", BitRow(data[0], 4));
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xec));
+ break;
+ }
+}
+
+static void
+dcch_address()
+{
+ if (data[0] & 1)
+ OUTF("-------1 Extended Address: 1 octet long\n");
+ else
+ OUTF("-------0 Extended Address: more octets follow\n");
+
+ if ((data[0] >> 1) & 1)
+ OUTF("------1- C/R: Command\n");
+ else
+ OUTF("------0- C/R: Response\n");
+
+ if (data[0] & 1)
+ {
+ /* SAPI */
+ nfo.sapi = (data[0] >> 2) & 0x07;
+ conptr = &con[nfo.sapi];
+ switch ((data[0] >> 2) & 0x07)
+ {
+ case 0x03:
+ nfo.flags |= GSMSP_NFO_SMS;
+ OUTF("---011-- SAPI: SMS and SS\n");
+ break;
+ case 0x00:
+ OUTF("---000-- SAPI: RR, MM and CC\n");
+ break;
+ default:
+ OUTF("%s SAPI: UNKNWON\n", BitRowFill(data[0], 0x1c));
+ break;
+ }
+
+ switch ((data[0] >> 4 ) & 0x03)
+ {
+ case 0x00:
+ OUTF("%s Link Protocol Disciminator: GSM (not Cell Broadcasting)\n", BitRowFill(data[0], 0x60));
+ break;
+ case 0x01:
+ OUTF("%s Link Protocol Disciminator: Cell Broadcasting (CBS)\n", BitRowFill(data[0], 0x60));
+ break;
+ default:
+ OUTF("%s Link Protocol Disciminator: UNKNOWN %u\n", BitRowFill(data[0], 0x60), (data[0] >> 5) & 0x03);
+ }
+ } else {
+ switch ((data[0] >> 2))
+ {
+ case 0x03:
+ nfo.flags |= GSMSP_NFO_SMS;
+ OUTF("000011-- SAPI: SMS and SS\n");
+ break;
+ case 0x00:
+ OUTF("000000-- SAPI: RR, MM and CC\n");
+ break;
+ default:
+ OUTF("%s SAPI: UNKNOWN\n", BitRowFill(data[0], 0xfc));
+ break;
+ }
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] & 1)
+ OUTF("-------1 Extended Address: 1 octet long\n");
+ else
+ OUTF("-------0 Extended Address: more octets follow [ERROR]\n");
+ OUTF("%s Terminal Endpoint Identifier (TEI): %u\n", BitRowFill(data[0], 0xfe), data[0] >> 1);
+ }
+}
+
+void
+l2_data_out_Bbis(int fn, const unsigned char *input_data, int len)
+{
+ int i;
+
+
+ memset(&nfo, 0, sizeof nfo);
+ if (len <= 0)
+ return;
+
+ data = input_data;
+ start = data;
+
+ /* 2008-01-05: Motorola output has Length field wrongly set.. */
+ if (opt.flags & FL_MOTOROLA)
+ i = data[0];
+ else
+ i = data[0] >> 2;
+ if (len - 1 < i)
+ OUTF("WARN: packet to short\n");
+
+ len = MIN(len - 1, i);
+
+ /* len = number of octets following the length field */
+ end = data + len + 1;
+
+ HEXDUMPF(data, 23 /*len*/, "Format Bbis DATA\n");
+ if (len <= 0)
+ return;
+
+ OUTF("%s Pseudo Length: %d\n", BitRowFill(data[0], 0xfc), data[0] >> 2);
+ data++;
+ l2_Bbis();
+}
+
+static void
+l2_Bbis() /* GSM 04.07 11.2.3.2.1 */
+{
+ if (data >= end)
+ RETTRUNK();
+
+ switch (data[0] >> 7)
+ {
+ case 1:
+ OUTF("1------- Direction: To originating site\n");
+ break;
+ default:
+ OUTF("0------- Direction: From originating site\n");
+ }
+
+ OUTF("%s %d TransactionID\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 7);
+
+ switch (data[0] & 0x0f)
+ {
+ case 0:
+ OUTF("----0000 Group Call Control [FIXME]\n");
+ break;
+ case 1:
+ OUTF("----0001 Broadcast call control [FIXME]\n");
+ data++;
+ l2_bcc();
+ /* TS GSM 04.69 */
+ break;
+ case 2:
+ OUTF("----0010 PDSS1 [FIXME]\n");
+ break;
+ case 3:
+ OUTF("----0011 Call control. call related SS messages\n");
+ data++;
+ l2_cc();
+ /* TS 24.008 */
+ break;
+ case 4:
+ OUTF("----01-- PDSS2 [FIXME]\n");
+ break;
+ case 5:
+ OUTF("----0101 Mobile Management Message (non GPRS)\n");
+ data++;
+ /* TS 24.008 */
+ l2_mmm();
+ break;
+ case 6:
+ OUTF("----0110 Radio Resouce Management\n");
+ data++;
+ l2_rrm();
+ break;
+ case 7:
+ OUTF("----0111 RFU [FIXME]\n");
+ break;
+ case 8:
+ OUTF("----1000 GPRS Mobile Management\n");
+ /* in GMMattachAccept */
+ /* in GMMidentityRequest */
+ OUTF("FIXME: possible IMEI in here\n");
+ break;
+ case 9:
+ OUTF("----1001 SMS messages\n");
+ data++;
+ l2_sms();
+ /* TS 04.11 */
+ break;
+ case 0x0a:
+ OUTF("----1011 GRPS session management messages [FIXME]\n");
+ break;
+ case 0x0b:
+ OUTF("----1011 Non-call related SS message\n");
+ data++;
+ l2_NonCallSS();
+ /* GSM 04.80 */
+ break;
+ case 0x0c:
+ OUTF("----1100 Location services [FIXME]\n");
+ break;
+ case 0x0d:
+ OUTF("----1101 RFU [FIXME]\n");
+ break;
+ case 0x0e:
+ OUTF("----1110 Extension of the PD to one octet length [FIXME]\n");
+ break;
+ case 0x0f:
+ OUTF("----1111 Tests procedures describe in TS GSM 11.10 [FIXME]\n");
+ break;
+ default:
+ OUTF("%s 0x%02x UNKNOWN\n", BitRowFill(data[0], 0x0f), data[0] & 0x0f);
+ }
+
+}
+
+/*
+ * Broadcast Call Control (04.69)
+ */
+static void
+l2_bcc()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ /* Message type 04.69:9.3*/
+ switch (data[0] & 0x3f)
+ {
+ case 0x06: /* 0-000110 */
+ OUTF("--000110 ???\n");
+ break;
+ default:
+ OUTF("--?????? UNKNOWN [FIXME]\n");
+ return;
+ }
+
+ /* Call reference 04.69:9.4.1*/
+
+ /* Orig indication 04.69:9.5.5*/
+ /* Spare half octet 04.69:9.4.5*/
+
+}
+
+/*
+ * ProtDisc3
+ */
+static void
+l2_cc()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Send Sequence Number: %u\n", BitRowFill(data[0], 0xc0), data[0] >> 6);
+
+ if ((data[0] & 0x3f) == 0x01)
+ {
+ OUTF("--000001 Call Alerting\n");
+ data++;
+ CCalerting();
+ } else if ((data[0] & 0x3f) == 0x02) {
+ OUTF("--000010 Call Proceesing\n");
+ if (++data >= end)
+ return;
+ OUTF("FIXME %s\n", __func__);
+ } else if ((data[0] & 0x3f) == 0x07) {
+ OUTF("--000111 Call Connect\n");
+ if (++data >= end)
+ return;
+ OUTF("FIXME %s\n", __func__);
+ } else if ((data[0] & 0x3f) == 0x08) {
+ OUTF("--001000 Call Confirmed\n");
+ if (++data >= end)
+ return;
+ if (data[0] != 0x04)
+ return;
+ OUTF("--000010 Bearer Capability\n");
+ data++;
+ BearerCap();
+ } else if ((data[0] & 0x3f) == 0x05) {
+ OUTF("--000101 Call Setup\n");
+ data++;
+ CCsetup();
+ } else if ((data[0] & 0x3f) == 0x03) {
+ OUTF("--000011 Call Progress\n");
+ data++;
+ ProgressIndicator();
+ } else if ((data[0] & 0x3f) == 0x0f) {
+ OUTF("--001111 Connect Acknowledge\n");
+ } else if ((data[0] & 0x3f) == 0x25) {
+ OUTF("--100101 Disconnect\n");
+ data++;
+ Cause();
+ } else if ((data[0] & 0x3f) == 0x2d) {
+ OUTF("--101101 CC Release\n");
+ if (++data >= end)
+ RETTRUNK();
+ if (data[0] == 0x08)
+ {
+ data++;
+ Cause();
+ }
+ } else if ((data[0] & 0x3f) == 0x2a) {
+ OUTF("--101010 CC Release Complete\n");
+ if (++data >= end)
+ RETTRUNK();
+ if (data[0] == 0x08)
+ {
+ data++;
+ Cause();
+ }
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] == 0x1c)
+ {
+ /* facility */
+ OUTF("FIXME\n");
+ }
+ } else {
+ OUTF("%s FIXME %s\n", BitRowFill(data[0], 0xff), __func__);
+ }
+}
+
+/*
+ * ----0101
+ * ProtDisc5 - Mobile Management message (non GPRS)
+ */
+static void
+l2_mmm()
+{
+ if (data >= end)
+ return;
+ OUTF("%s SendSequenceNumber: %d\n", BitRowFill(data[0], 0xc0), data[0] >> 6);
+ switch (data[0] & 0x3f)
+ {
+ case 1:
+ //l2_MMimsiDetIndication(data + 1, end);
+ OUTF("--000001 Imsi Det Indication\n"); /* FIXME */
+ OUTF("FIXME: Possible IMSI in here\n");
+ OUTF("FIXME: Possible cipher mode here\n");
+ break;
+ case 2:
+ OUTF("--000010 Location Update Accept\n"); /* FIXME */
+ break;
+ case 4:
+ OUTF("--000100 Message Type: Location Updating Reject\n");
+ break;
+ case 8:
+ OUTF("--001000 MM Location Update Request\n"); /* FIXME */
+ data++;
+ LocationUpdateRequest();
+ break;
+ case 0x12:
+ OUTF("--010010 Authentication Request\n");
+ data++;
+ AuthenticationRequest();
+ break;
+ case 0x14:
+ OUTF("--010100 Authentication Response\n");
+ data++;
+ AuthenticationResponse();
+ break;
+ case 0x18:
+ OUTF("--011000 MMIdentityRequest\n");
+ data++;
+ TypeOfIdentity();
+ break;
+ case 0x19:
+ OUTF("--011001 MMidentityResponse\n");
+ data++;
+ l2_MobId();
+ break;
+ case 0x1a:
+ OUTF("--011010 TMSI Realloc Command\n");
+ data++;
+ l2_TmsiReallocCommand();
+ break;
+ case 0x21:
+ OUTF("--100001 CM Service Accept\n");
+ data++;
+ break;
+ case 0x24: /* --100100 */
+ OUTF("--100100 MMcmServiceRequest\n");
+ data++;
+ l2_MMcmServiceRequest();
+ /* in multisupport2 and others! */
+ break;
+ default:
+ OUTF("UNKNOWN\n");
+ }
+}
+
+/*
+ * ProtDisc6 - Radio Resource Management Messages
+ */
+static void
+l2_rrm()
+{
+ if (data >= end)
+ return;
+
+ switch (data[0] & 0x3f)
+ {
+ case 0x00:
+ OUTF("00000000 System Information Type 13\n");
+ data++;
+ l2_RRsystemInfo13C();
+ break;
+ case 0x06:
+ OUTF("00000110 System Information Type 5ter\n");
+ data++;
+ l2_BcchAllocation();
+ break;
+ case 0x0d:
+ OUTF("00001101 Channel Release\n");
+ data++;
+ l2_ChannelRelease();
+ break;
+ case 0x15:
+ OUTF("00010101 RR Measurement Report C\n");
+ data++;
+ MeasurmentReport();
+ break;
+ case 0x16:
+ OUTF("00010110 RRclassmarkChange\n");
+ data++;
+ l2_RRclassmarkChange();
+ break;
+ case 0x19:
+ OUTF("00011001 RRsystemInfo1\n");
+ data++;
+ l2_RRsystemInfo1();
+ break;
+ case 0x1a:
+ OUTF("00011010 RRsystemInfo2\n");
+ data++;
+ l2_RRsystemInfo2();
+ break;
+ case 0x1B: /* 0001 1011 */
+ OUTF("00011011 RRsystemInfo3C\n");
+ data++;
+ l2_RRsystemInfo3C();
+ break;
+ case 0x1c:
+ OUTF("00011100 RRsystemInfo4-C\n");
+ data++;
+ l2_RRsystemInfo4C();
+ break;
+ case 0x1d:
+ /* From SDCCH */
+ OUTF("00011101 Neighbour Cells Description\n");
+ data++;
+ l2_NeighbourCellDescription();
+ break;
+ case 0x1e:
+ /* From SDCCH */
+ OUTF("00011110 System Information Type 6\n");
+ data++;
+ l2_RRsystemInfo6();
+ break;
+ case 0x21:
+ OUTF("00100001 Paging Request Type 1\n");
+ data++;
+ l2_RRpagingrequest1();
+ break;
+ case 0x22:
+ OUTF("00100010 Paging Request Type 2\n");
+ data++;
+ l2_RRpagingrequest2();
+ break;
+ case 0x24:
+ OUTF("00100100 Paging Request Type 3\n");
+ data++;
+ l2_RRpagingrequest3();
+ break;
+ case 0x27:
+ OUTF("0-100111 RRpagingResponse\n");
+ OUTF("-x------ Send sequence number: %d\n", (data[0] >> 7) & 0x01);
+ data++;
+ l2_RRpagingresponse();
+ break;
+ case 0x29:
+ OUTF("0-101001 RR Assign Complete\n");
+ data++;
+ l2_RRassignComplete();
+ break;
+ case 0x2e:
+ OUTF("00101110 RR Assign Command\n");
+ data++;
+ l2_RRassignCommand();
+ break;
+ case 0x32:
+ OUTF("00110010 RR Cipher Mode Complete\n");
+ data++;
+ l2_RRciphModCompl();
+ break;
+ case 0x35:
+ OUTF("00110101 RR Cipher Mode Command\n");
+ data++;
+ l2_RRciphModCmd();
+ break;
+ case 0x3f:
+ OUTF("0-111111 RRimmediateAssignment\n");
+ OUTF("-x------ Send sequence number: %d\n", (data[0] >> 7) & 0x01);
+ data++;
+ l2_RRimmediateAssignment();
+ break;
+ default:
+ OUTF("???????? UNKNOWN. FIXME\n");
+ }
+}
+static void
+l2_RRsystemInfo13C()
+{
+ if (data >= end);
+ return;
+ if (data[0] >> 7)
+ OUTF("1------- SI 13 Restoctet present\n");
+ else
+ OUTF("0------- SI 13 Restoctet NOT present\n");
+ OUTF("%s BCCH_CHANGE_MARK : %d\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07);
+ switch (data[0] & 0x0f)
+ {
+ case 0x00:
+ OUTF("----0000 SI_CHANGE_FIELD : Update of unspecified SI messages\n");
+ break;
+ case 0x01:
+ OUTF("----00001 SI_CHANGE_FIELD : Update of unspecified SI1 messages\n");
+ break;
+ case 0x02:
+ OUTF("----0010 SI_CHANGE_FIELD : Update of unspecified SI2 messages\n");
+ break;
+ case 0x03:
+ OUTF("----0011 SI_CHANGE_FIELD : Update of unspecified SI3,4,7,8 messages\n");
+ break;
+ case 0x04:
+ OUTF("----0100 SI_CHANGE_FIELD : Update of unspecified SI9 messages\n");
+ break;
+ default:
+ OUTF("----???? Unknown %d\n", data[0] & 0x0f);
+ break;
+ }
+ OUTF("FIXME: implement me\n");
+
+}
+
+static void
+l2_RRimmediateAssignment()
+{
+ if (data >= end)
+ return;
+
+ /* Octect 4, 0x79 */
+ OUTF("%s\n", PageMode(data[0] & 0x03));
+
+ if ((data[0] >> 6) & 0x01)
+ OUTF("-1------ Two messages assign.: 1. message of..(continue)\n");
+ else
+ OUTF("-0------ No meaning\n");
+ if ((data[0] >> 5) & 0x01)
+ OUTF("--1----- Assigns a resource identified in the IA rest octets.\n");
+ else
+ OUTF("--0----- Downlink assig to MS: No meaning\n");
+ if ((data[0] >> 4) & 0x01)
+ {
+ OUTF("---1---- Temporary Block Flow (TBF)\n");
+ data++;
+ l2_RRimmediateAssTBFC();
+ return;
+ }
+ else
+ OUTF("---0---- This messages assigns a dedicated mode resource\n");
+ data++;
+ if (data >= end)
+ return;
+
+ /* Channel Description */
+ ChannelDescriptionTwo();
+
+ if (data >= end)
+ return;
+ if (((data[0] >> 2) & 0x07) == 0)
+ l2_SingleChannel();
+ else if (((data[0] >> 4) & 0x01) == 1)
+ {
+ l2_HoppingChannel();
+ } else {
+ OUTF("xxx0??xxx UNKNOWN %d\n", (data[0] >> 3) & 0x3);
+ }
+}
+
+static void
+l2_SingleChannel()
+{
+ l2_SingleChannelC();
+ RequestReference();
+ TimingAdvance();
+ l2_MobileAllocation();
+ if (data >= end)
+ return;
+}
+
+static void
+l2_SingleChannelC()
+{
+ int freq;
+ if (data + 1 >= end)
+ RETTRUNK();
+ OUTF("%s Training seq. code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
+ OUTF("---0---- Single channel\n");
+ freq = (data[0] & 0x03) << 8;
+ data++;
+ freq |= data[0];
+ OUTF("........ Absolute RF channel number: %u\n", freq);
+ data++;
+}
+
+static void
+l2_HoppingChannel()
+{
+ unsigned char maio = 0;
+ OUTF("%s Training seq. code : %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
+ OUTF("---1---- HoppingChannel\n");
+ maio = (data[0] & 0x0f) << 2;
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ maio |= (data[0] >> 6);
+ OUTF("........ MAIO %d\n", maio);
+ OUTF("%s Hopping Seq. Number: %d\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f);
+
+ data++;
+ RequestReference();
+ TimingAdvance();
+ l2_MobileAllocation();
+ if (data >= end)
+ return; /* finished. not truncated! */
+
+ OUTF("FIXME, more data left here???\n");
+}
+
+static void
+l2_HoppingChannelC()
+{
+ OUTF("FIXME-2\n");
+}
+
+static void
+l2_MobileAllocation()
+{
+ int c = 64, pos;
+ char *str = "Mobile allocation RF chann.";
+ const unsigned char *thisend;
+
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Length of Mobile Allocation: %d\n", BitRowFill(data[0], 0xff), data[0]);
+ thisend = data + data[0] + 1;
+ if (thisend > end)
+ {
+ OUTF("xxxxxxxx ERROR: Packet to short or length to long\n");
+ thisend = end;
+ }
+
+ data++;
+ /* If mobile allocation has length 0 */
+ if (data >= thisend)
+ return;
+
+ while (data < thisend)
+ {
+ pos = 7;
+ while (pos >= 0)
+ {
+ if ((data[0] >> pos) & 1)
+ OUTF("%s %s%d\n", BitRow(data[0], pos), str, c - (7 - pos));
+ pos--;
+
+ }
+
+ c -= 8;
+ data++;
+ if (c <= 0)
+ break;
+ }
+}
+
+/*
+ * From RRsystemInfo2
+ */
+static void
+l2_BcchAllocation()
+{
+ int c, pos;
+ char *str = "BCCH alloc. RF chan.: ";
+
+#if 0
+ /* goeller script for Info2 outputs channels 128 + 127
+ * but opengpa outputs bitmap format for info2.
+ * We do what opengpa does. (correct?)
+ */
+ if ((data[0] >> 7))
+ OUTF("1------- %s%d\n", str, 128);
+ if ((data[0] >> 6) & 1)
+ OUTF("-1------ %s%d\n", str, 127);
+#endif
+ if ((data[0] >> 6) == 0x00)
+ OUTF("00------ Bitmap format: 0\n");
+ else {
+ OUTF("%s Bitmap format: UNKNOWN [FIXME]\n", BitRowFill(data[0], 0xc0));
+ return;
+ }
+
+ if ((data[0] & 0x8e) == 0x8e)
+ {
+ /* From System Information Type 5ter */
+ OUTF("1---111- Variable Bitmap SI5ter [FIXME]\n");
+ return;
+ }
+
+ if ((data[0] >> 5) & 1)
+ OUTF("--1----- Extension Indicator: The IE carries only a part of the BA\n");
+ else
+ OUTF("--0----- Extension Indicator: The IE carries the complete BA\n");
+ OUTF("---x---- BCCH alloc. seq. num: %d\n", (data[0] >> 4) & 1);
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- %s%d\n", str, 124);
+ if ((data[0] >> 2) & 1)
+ OUTF("-----1-- %s%d\n", str, 123);
+ if ((data[0] >> 1) & 1)
+ OUTF("------1- %s%d\n", str, 122);
+ if (data[0] & 1)
+ OUTF("-------1 %s%d\n", str, 121);
+
+ data++;
+ c = 120;
+ while (data < end)
+ {
+ pos = 7;
+ while (pos >= 0)
+ {
+ if ((data[0] >> pos) & 1)
+ OUTF("%s %s%d\n", BitRow(data[0], pos), str, c - (7 - pos));
+ pos--;
+
+ }
+
+ c -= 8;
+ data++;
+ if (c <= 0)
+ break;
+ }
+}
+
+static void
+l2_RRimmediateAssTBFC()
+{
+ if (data >= end)
+ return;
+
+ /* GPRS Packet Channel Description */
+ OUTF("%s Channel Type : %d\n", BitRowFill(data[0], 0xf8), data[0] >> 3);
+ OUTF("%s Time Slot Number : %d\n", BitRowFill(data[0], 0x07), data[0] & 0x07);
+ data++;
+ if (data >= end)
+ return;
+
+ OUTF("%s Tranining Sequence Code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
+ if ((data[0] >> 4) & 0x01)
+ {
+ OUTF("---1---- Direct Encoding of Hopping Channels\n");
+ l2_RRimmAssTBFDirEncHoChaC();
+ return;
+ } else {
+ OUTF("---0---- non-hopping RF channel config or indirect encoding of hopping RFCC\n");
+ }
+
+ if ((data[0] >> 3) & 0x01)
+ {
+ OUTF("----1--- indirect encoding of hopping RF channel config\n");
+ } else {
+ OUTF("----0--- RRimmAssTBFaRFCN-C FIXME\n");
+ return;
+ }
+
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ OUTF("xxxxxxxx MAIO [FIXME]\n");
+
+ data++;
+ RequestReference();
+ TimingAdvance();
+ l2_MobileAllocation();
+ if (data >= end)
+ RETTRUNK();
+ OUTF("FIXME: implenet\n");
+}
+
+static void
+l2_RRsystemInfo1()
+{
+ int ca;
+
+ if (data + 1 >= end)
+ return;
+ switch (data[0] >> 6)
+ {
+ case 0x00:
+ OUTF("00------ Bitmap 0 format\n");
+ break;
+ case 0x01:
+ OUTF("10------ Bitmap format: (FIXME)\n");
+ break;
+ default:
+ OUTF("%s Bitmap %d format (FIXME)\n", BitRowFill(data[0], 0xc0), data[0] >> 6);
+ }
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- Cell Allocation : ARFCN 124\n");
+ if ((data[0] >> 2) & 1)
+ OUTF("-----1-- Cell Allocation : ARFCN 123\n");
+ if ((data[0] >> 1) & 1)
+ OUTF("------1- Cell Allocation : ARFCN 122\n");
+ if (data[0] & 1)
+ OUTF("-------1 Cell Allocation : ARFCN 121\n");
+
+ ca = 120;
+ while (ca > 0)
+ {
+ data++;
+ if (data >= end)
+ return;
+ if ((data[0] >> 7) & 1)
+ OUTF("1------- Cell Allocation : ARFCN %d\n", ca);
+ if ((data[0] >> 6) & 1)
+ OUTF("-1------ Cell Allocation : ARFCN %d\n", ca - 1);
+ if ((data[0] >> 5) & 1)
+ OUTF("--1----- Cell Allocation : ARFCN %d\n", ca - 2);
+ if ((data[0] >> 4) & 1)
+ OUTF("---1---- Cell Allocation : ARFCN %d\n", ca - 3);
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- Cell Allocation : ARFCN %d\n", ca - 4);
+ if ((data[0] >> 2) & 1)
+ OUTF("-----1-- Cell Allocation : ARFCN %d\n", ca - 5);
+ if ((data[0] >> 1) & 1)
+ OUTF("------1- Cell Allocation : ARFCN %d\n", ca - 6);
+ if (data[0] & 1)
+ OUTF("-------1 Cell Allocation : ARFCN %d\n", ca - 7);
+
+ ca -= 8;
+ }
+
+ data++;
+
+ l2_RachControlParameters();
+ if (data >= end)
+ return;
+ OUTF("FIXME: NCH Position\n");
+}
+
+static void
+l2_RachControlParameters()
+{
+ int ca = -1;
+
+ if (data >= end)
+ return;
+
+ if (((data[0] >> 6) & 0x03) == 0)
+ ca = 1;
+ else if (((data[0] >> 6) & 0x03) == 0x01)
+ ca = 2;
+ else if (((data[0] >> 6) & 0x03) == 0x02)
+ ca = 4;
+ else if (((data[0] >> 6) & 0x03) == 0x03)
+ ca = 7;
+ OUTF("%s Max. of retransmiss : %u\n", BitRowFill(data[0], 0xc0), ca);
+ if (((data[0] >> 2) & 0x0f) <= 9)
+ {
+ ca = ((data[0] >> 2) & 0x0f) + 3;
+ } else {
+ switch ((data[0] >> 2) & 0x0f)
+ {
+ case 10: /* --1010-- */
+ ca = 14;
+ break;
+ case 11:
+ ca = 16;
+ break;
+ case 12:
+ ca = 20;
+ break;
+ case 13:
+ ca = 25;
+ break;
+ case 14:
+ ca = 32;
+ break;
+ case 15:
+ ca = 50;
+ break;
+ default:
+ ca = -1;
+ break;
+ }
+ }
+ OUTF("%s slots to spread TX : %u\n", BitRowFill(data[0], 0x3c), ca);
+ switch ((data[0] >> 1) & 0x01)
+ {
+ case 0:
+ OUTF("------0- The cell is barred : no\n");
+ break;
+ case 1:
+ OUTF("------1- The cell is barred : yes\n");
+ break;
+ }
+
+ switch (data[0] & 0x01)
+ {
+ case 0:
+ OUTF("-------0 Call reestabl.i.cell: allowed\n");
+ break;
+ case 1:
+ OUTF("-------1 Cell reestabl.i.cell: not allowed\n");
+ }
+
+ data++;
+ if (data >= end)
+ return;
+ switch ((data[0] >> 2) & 0x01)
+ {
+ case 0:
+ OUTF("-----0-- Emergency call EC 10: allowed\n");
+ break;
+ case 1:
+ OUTF("-----1-- Emergency call EC 10: not allowed\n");
+ break;
+ }
+ OUTF("%s Acc ctrl cl 11-15: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0xf8));
+ OUTF("%s Acc ctrl cl 8- 9: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0x03));
+ OUTF("%s Ordinary subscribers (8)\n", BitRowFill(data[0], 0x01));
+ OUTF("%s Ordinary subscribers (9)\n", BitRowFill(data[0], 0x02));
+ OUTF("%s Emergency call (10): %s\n", BitRowFill(data[0], 0x04), ((data[0] >> 4) & 1)?"Class 11-15 only":"Everyone");
+ OUTF("%s Operator Specific (11)\n", BitRowFill(data[0], 0x08));
+ OUTF("%s Security service (12)\n", BitRowFill(data[0], 0x10));
+ OUTF("%s Public service (13)\n", BitRowFill(data[0], 0x20));
+ OUTF("%s Emergency service (14)\n", BitRowFill(data[0], 0x40));
+ OUTF("%s Network Operator (15)\n", BitRowFill(data[0], 0x80));
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Acc ctrl cl 0- 7: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0xff));
+ OUTF("%s Ordinary subscribers (0-7)\n", BitRowFill(data[0], 0xff));
+ data++;
+}
+
+static char *
+BitRow(unsigned char c, int pos)
+{
+ unsigned char bit = 0;
+ static char buf[9];
+
+ if ((c >> pos) & 1)
+ bit = 1;
+
+ if (pos == 0)
+ snprintf(buf, sizeof buf, "-------%d", bit);
+ else if (pos == 1)
+ snprintf(buf, sizeof buf, "------%d-", bit);
+ else if (pos == 2)
+ snprintf(buf, sizeof buf, "-----%d--", bit);
+ else if (pos == 3)
+ snprintf(buf, sizeof buf, "----%d---", bit);
+ else if (pos == 4)
+ snprintf(buf, sizeof buf, "---%d----", bit);
+ else if (pos == 5)
+ snprintf(buf, sizeof buf, "--%d-----", bit);
+ else if (pos == 6)
+ snprintf(buf, sizeof buf, "-%d------", bit);
+ else if (pos == 7)
+ snprintf(buf, sizeof buf, "%d-------", bit);
+
+ return buf;
+}
+
+static char *
+BitRowFill(unsigned char c, unsigned char mask)
+{
+ static char buf[9];
+
+ memset(buf, '-', sizeof buf);
+ buf[sizeof buf - 1] = '\0';
+ int i = 0;
+ while (i < 8)
+ {
+ if ((mask >> i) & 1)
+ {
+ if ((c >> i) & 1)
+ buf[7 - i] = '1';
+ else
+ buf[7 - i] = '0';
+ }
+ i++;
+ }
+
+ return buf;
+}
+
+static void
+l2_RRsystemInfo2()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ l2_BcchAllocation();
+ if (data >= end)
+ RETTRUNK();
+
+ int c = 7;
+ while (c >= 0)
+ {
+ if ((data[0] >> c) & 1)
+ OUTF("%s BCCH carrier with NCC = %d is permitted for monitoring\n", BitRow(data[0], c), c);
+ c--;
+ }
+ data++;
+ if (data >= end)
+ RETTRUNK();
+
+ l2_RachControlParameters();
+
+ if (data > end) /* Note: not >= */
+ RETTRUNK();
+}
+
+#if 0
+static void
+l2_RRsystemInfo2ter()
+{
+ if (data >= end)
+ return;
+ if ((data[0] >> 7) == 0)
+ OUTF("%s Bitmap 0 format\n", BitRowFill(data[0], 0x8e));
+ else {
+ /* 0x8e = 10001110 */
+ if (((data[0] >> 1) & 0x07) == 0x04)
+ OUTF("1---100- 1024 range\nFIXME\n");
+ else if (((data[0] >> 1) & 0x07) == 0x05)
+ OUTF("1---101- 512 range\nFIXME\n");
+ else if (((data[0] >> 1) & 0x07) == 0x06)
+ OUTF("1---110- 128 range\nFIXME\n");
+ else if (((data[0] >> 1) & 0x07) == 0x07)
+ OUTF("1---111- variable Bitmap\nFIXME\n");
+ else
+ OUTF("1---xxx- UNKNOWN 0x%08x\n", data[0]);
+ }
+ OUTF("FIXME\n");
+}
+#endif
+
+
+/*
+ * RRsystemInfo4-C
+ */
+static void
+l2_RRsystemInfo4C()
+{
+ if (data + 2 >= end)
+ RETTRUNK();
+ l2_MccMncLac();
+ CellSelectionParameters();
+ l2_RachControlParameters();
+ if (data + 1 >= end)
+ RETTRUNK();
+
+ if (data[0] != 0x64)
+ {
+ OUTF("UNKNWON\n");
+ return;
+ }
+ OUTF("01100100 Channel Description\n");
+ data++;
+ ChannelDescriptionTwo();
+ if (data >= end)
+ RETTRUNK();
+ //OUTF("%s Training sequence code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
+ if (((data[0] >> 3) & 0x1) == 0)
+ {
+ l2_SingleChannelC();
+ } else {
+ l2_HoppingChannelC();
+ }
+
+ if (data >= end)
+ return;
+
+ if (data[0] != 0x72)
+ {
+ OUTF("UNKNOWN\n");
+ return;
+ }
+ OUTF("01110010 CBCH Mobile Allocation\n");
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ l2_MobileAllocation();
+
+// OUTF("FIXME\n");
+}
+
+/*
+ * Output MCC, MNC and LAC. consume 5 bytes.
+ */
+static void
+l2_MccMncLac()
+{
+ if (data + 2 >= end)
+ return;
+ unsigned short lac;
+
+ l2_MNCC("Mobile Country Code", data[0] & 0x0f, (data[0] >> 4) & 0x0f, data[1] & 0x0f);
+ data++;
+ l2_MNCC("Mobile Network Code", data[1] & 0x0f, (data[1] >> 4) & 0x0f, (data[0] >> 4) & 0x0f);
+ data += 2;
+
+ if (data + 1 >= end)
+ return;
+
+ lac = data[0];
+ lac = (lac << 8) | data[1];
+ OUTF("%-8u [0x%02x%02x] Local Area Code\n", lac, data[0], data[1]);
+ data += 2;
+}
+/*
+ * RRsystemINfo3-C
+ */
+static void
+l2_RRsystemInfo3C()
+{
+ CellIdentity();
+ l2_MccMncLac();
+
+ ControlChannelDescription();
+ CellOptionsBcch();
+ CellSelectionParameters();
+ l2_RachControlParameters();
+
+ /* FIXME: complete here */
+}
+
+static void
+l2_RRsystemInfo6()
+{
+ CellIdentity();
+ l2_MccMncLac();
+ CellOptionsBcch();
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Network Colour Code: %u\n", BitRowFill(data[0], 0xff), data[0]);
+}
+
+static void
+CellIdentity()
+{
+ unsigned short id;
+
+ if (data + 1 >= end)
+ return;
+
+ id = data[0];
+ id = (id << 8) | data[1];
+ OUTF("%-8u [0x%02x%02x] Cell identity\n", id, data[0], data[1]);
+ data += 2;
+}
+
+static void
+ControlChannelDescription()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Spare bit (should be 0)\n", BitRow(data[0], 7));
+ if ((data[0] >> 6) & 1)
+ OUTF("-1------ MSs in the cell shall apply IMSI attach/detach procedure\n");
+ else
+ OUTF("-0------ MSs in cell are not allowed attach/detach procedure\n");
+ OUTF("%s Number of blocks: %u\n", BitRowFill(data[0], 0x38), (data[0] >> 3) & 0x07);
+
+ switch (data[0] & 0x07)
+ {
+ case 0x00:
+ OUTF("-----000 1 basic physical channel for CCCH, not combined with SDCCHs\n");
+ break;
+ case 0x01:
+ OUTF("-----001 1 basic physical channel for CCCH, combined with SDCCHs\n");
+ break;
+ case 0x02:
+ OUTF("-----010 2 basic physical channel for CCCH, not combined with SDCCHs\n");
+ break;
+ case 0x04:
+ OUTF("-----100 3 basic physical channel for CCCH, not combined with SDCCHs\n");
+ break;
+ case 0x06:
+ OUTF("-----110 4 basic physical channel for CCCH, not combined with SDCCHs\n");
+ break;
+ default:
+ OUTF("%s Unknown CCCH config (ERROR)\n", BitRowFill(data[0], 0x07));
+ break;
+ }
+
+ data++;
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s spare bits (should be 0)\n", BitRowFill(data[0], 0xf8));
+ OUTF("%s %u multi frames period for paging request\n", BitRowFill(data[0], 0x07), (data[0] & 0x07) + 2);
+
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s T3212 TimeOut value: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+}
+
+static void
+CellOptionsBcch()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s spare bit (should be 0)\n", BitRowFill(data[0], 0x80));
+ if ((data[0] >> 6) & 1)
+ OUTF("-1------ Power control indicator is set\n");
+ else
+ OUTF("-0------ Power control indicator is not set\n");
+
+ if (((data[0] >> 4) & 0x03) == 0x00)
+ OUTF("--00---- MSs may use uplink DTX\n");
+ else if (((data[0] >> 4) & 0x03) == 0x01)
+ OUTF("--01---- MSs shall use uplink DTX\n");
+ else if (((data[0] >> 4) & 0x03) == 0x02)
+ OUTF("--10---- MSs shall not use uplink DTX\n");
+ else
+ OUTF("%s DTX UNKNOWN [ERROR]\n", BitRowFill(data[0], 0x30));
+
+ OUTF("%s Radio Link Timeout: %u\n", BitRowFill(data[0], 0x0f), ((data[0] & 0x0f) + 1 ) * 4);
+ data++;
+}
+
+static void
+l2_MNCC(const char *str, unsigned char a, unsigned char b, unsigned char c)
+{
+ char buf[128];
+ char f[12];
+
+ snprintf(f, sizeof f, "%x%x%x", a, b, c);
+ /* Nokia netmonitor shows NC's like '30F' and '10F' */
+ snprintf(buf, sizeof buf, "%-8s %s\n", f, str);
+
+#if 0
+ buf[0] = '\0';
+ if (a != 0x0f)
+ {
+ snprintf(buf, sizeof buf, "%x", a);
+ if (b != 0x0f)
+ {
+ snprintf(buf + 1, sizeof buf - 1, "%x", b);
+ if (c != 0x0f)
+ snprintf(buf + 2, sizeof buf - 2, "%x", c);
+ }
+ }
+ snprintf(buf + strlen(buf), sizeof buf - strlen(buf), " - %s\n", str);
+#endif
+
+ OUTF(buf);
+}
+
+static char *
+PageMode(unsigned char mode)
+{
+ switch (mode)
+ {
+ case 0:
+ return "------00 Page Mode: Normal paging";
+ case 1:
+ return "------01 Page Mode: Extended paging";
+ case 2:
+ return "------10 Page Mode: Paging reorganisation";
+ case 3:
+ return "------11 Page Mode: reserved / same as before";
+ }
+
+ return "------?? UNKNOWN\n";
+}
+
+static void
+l2_RRpagingrequest1()
+{
+ if (data >= end)
+ return;
+
+ OUTF("%s\n", PageMode(data[0] & 0x3));
+
+ /* FIXME complete here */
+
+ data++;
+ if (data >= end)
+ return;
+
+ l2_MobId();
+ if (data >= end)
+ return; /* sometimes it's end here */
+ if (data[0] == 0x17)
+ {
+ data++;
+ l2_MobId();
+ return;
+ }
+ OUTF("ERR: wrong data\n");
+}
+
+static void
+l2_ChannelNeeded(char *str, unsigned char ch)
+{
+ switch (ch)
+ {
+ case 0x00:
+ OUTF("%s Channel Needed: Any channel\n", str);
+ break;
+ case 0x01:
+ OUTF("%s Channel Needed: SDCCH\n", str);
+ break;
+ case 0x02:
+ OUTF("%s Channel Needed: TCH/F (Full rate)\n", str);
+ break;
+ case 0x03:
+ OUTF("%s Channel Needed: TCH/H or TCH/F (Dual rate)\n", str);
+ break;
+ }
+
+}
+
+static void
+l2_RRpagingrequest2()
+{
+ if (data >= end)
+ return;
+ OUTF("%s\n", PageMode(data[0] & 0x03));
+
+ l2_ChannelNeeded("--xx---- (first)", (data[0] >> 4) & 0x03);
+ l2_ChannelNeeded("xx------ (second)", data[0] >> 6);
+
+ data++;
+ if (data + 3 >= end)
+ RETTRUNK();
+ OUTF("........ Mob. Ident 1 (P)TMSI: %02X%02X%02X%02X\n", data[0], data[1], data[2], data[3]);
+ data += 4;
+ if (data + 3 >= end)
+ RETTRUNK();
+ OUTF("........ Mob. Ident 2 (P)TMSI: %02X%02X%02X%02X\n", data[0], data[1], data[2], data[3]);
+ data += 4;
+ if (data >= end)
+ RETTRUNK();
+
+ if (data[0] == 0x17)
+ {
+ data++;
+ l2_MobId();
+ return;
+ }
+
+ OUTF("FIXME, unknown\n");
+}
+
+static void
+l2_RRpagingrequest3()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s\n", PageMode(data[0] & 0x03));
+ l2_ChannelNeeded("--xx---- (first)", (data[0] >> 4) & 0x03);
+ l2_ChannelNeeded("xx------ (second)", data[0] >> 6);
+ data++;
+
+ int c = 0;
+ while (c++ < 4)
+ {
+ if (data + 3 >= end)
+ RETTRUNK();
+ OUTF("........ Mob. Ident %u (P)TMSI: %02X%02X%02X%02X\n", c, data[0], data[1], data[2], data[3]);
+ data += 4;
+ }
+}
+
+static void
+l2_MobId()
+{
+ const unsigned char *thisend = end;
+ unsigned char len = data[0];
+ char odd = 0;
+ int bcd = 0;
+
+ data++;
+ if (data >= end)
+ return;
+
+ if ((data[0] >> 3) & 1)
+ odd = 1;
+
+ switch (data[0] & 0x07)
+ {
+ case 0:
+ OUTF("-----000 Type of identity: No Identity\n");
+ break;
+ case 1:
+ OUTF("-----001 Type of identity: IMSI\n");
+ bcd = 1;
+ break;
+ case 2:
+ OUTF("-----010 Type of identity: IMEI\n");
+ bcd = 1;
+ break;
+ case 3:
+ OUTF("-----011 Type of identity: IMEISV\n");
+ bcd = 1;
+ break;
+ case 4:
+ OUTF("-----100 Type of identity: TMSI/P-TMSI\n");
+ break;
+ default:
+ OUTF("-----000 Type of identity: UNKNOWN\n");
+ return;
+ }
+ if (len <= 0)
+ return;
+
+ /* Nokia Netmonitor never outputs the first value */
+ //OUTF("%x", data[0] >> 4);
+ unsigned char c;
+ c = data[0] >> 4;
+ len--;
+ data++;
+ if (len <= 0)
+ return;
+
+ OUTF("-------- ID(%d/%s): ", len, odd?"odd":"even");
+
+ if (data + len < thisend)
+ thisend = data + len;
+ if (bcd)
+ {
+ OUT("%X", c);
+ while (data < thisend)
+ {
+ if ((data + 1 == thisend) && (!odd))
+ OUT("%X", data[0] & 0x0f);
+ else
+ OUT("%X%X", data[0] & 0x0f, (data[0] >> 4) & 0x0f);
+ data++;
+ }
+ } else {
+ while (data < thisend)
+ {
+ if ((data + 1 == thisend) && (odd))
+ OUT("%X", (data[0] >> 4 ) & 0x0f);
+ else
+ OUT("%X%X", (data[0] >> 4) & 0x0f, data[0] & 0x0f);
+ data++;
+ }
+ }
+ OUT("\n");
+}
+
+
+static void CellSelectionParameters()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ switch (data[0] >> 5)
+ {
+ case 0:
+ OUTF("000----- Cell Reselect Hyst. : 0 db RXLEV\n");
+ break;
+ case 1:
+ OUTF("001----- Cell Reselect Hyst. : 2 db RXLEV\n");
+ break;
+ case 2:
+ OUTF("010----- Cell Reselect Hyst. : 4 db RXLEV\n");
+ break;
+ case 3:
+ OUTF("011----- Cell Reselect Hyst. : 6 db RXLEV\n");
+ break;
+ case 4:
+ OUTF("100----- Cell Reselect Hyst. : 8 db RXLEV\n");
+ break;
+ case 5:
+ OUTF("101----- Cell Reselect Hyst. : 10 db RXLEV\n");
+ break;
+ case 6:
+ OUTF("110----- Cell Reselect Hyst. : 12 db RXLEV\n");
+ break;
+ case 7:
+ OUTF("111----- Cell Reselect Hyst. : 14 db RXLEV\n");
+ break;
+ }
+ OUTF("---xxxxx Max Tx power level: %d\n", data[0] & 0x1f);
+ data++;
+ if (data >= end)
+ RETTRUNK();
+
+ if (data[0] >> 7)
+ OUTF("1------- Additional cells in SysInfo 16,17\n");
+ else
+ OUTF("0------- No additional cells in SysInfo 7-8\n");
+ if ((data[0] >> 6) & 1)
+ OUTF("-1------ New establishm cause: supported\n");
+ else
+ OUTF("-0------ New establishm cause: not supported\n");
+ OUTF("--xxxxxx RXLEV Access Min permitted = -110 + %ddB\n", data[0] & 0x3f);
+ data++;
+}
+
+static void
+l2_RRimmAssTBFDirEncHoChaC()
+{
+ unsigned char maio = (data[0] & 0x0f) << 4;
+
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ maio |= (data[0] >> 6);
+ OUTF("xxxxxxxx MAIO: %u\n", maio);
+ OUTF("%s HSN: %u\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f);
+ data++;
+
+ RequestReference();
+
+ TimingAdvance();
+ l2_MobileAllocation();
+
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] == 0x7c)
+ {
+ StartingTime();
+ return;
+ }
+ OUTF("FIXME: implement me\n");
+}
+
+static void
+RequestReference()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ /* Request Reference */
+ if ((data[0] >> 5) == 0)
+ OUTF("000----- Establishing Cause : All other cases\n");
+ else if ((data[0] >> 5) == 0x01)
+ OUTF("001----- Establishing Cause : All other cases\n");
+ else if ((data[0] >> 5) == 0x02)
+ OUTF("010----- Establishing Cause : All other cases\n");
+ else if ((data[0] >> 5) == 0x03)
+ OUTF("011----- Establishing Cause : All other cases\n");
+ else if ((data[0] >> 5) == 0x04)
+ OUTF("100----- Establishing Cause: Answer to paging\n");
+ else if ((data[0] >> 5) == 0x05)
+ OUTF("101----- Establishing Cause: Emergency call\n");
+ else if ((data[0] >> 5) == 0x07)
+ OUTF("111----- Establishing Cause: Other services req. by user\n");
+/* Random refernce must be 5 bit long ?! */
+// else if ((data[0] >> 4) == 0x05)
+// OUTF("0101---- Establishing Cause: Originating data call from dual rate mobile station\n");
+// else if ((data[0] >> 4) == 0x02)
+// OUTF("0010---- Establishing Cause: Answer to paging\n");
+ else
+ OUTF("%s Establishing Cause: UNKNOWN [FIXME}\n", BitRowFill(data[0], 0xe0));
+
+ OUTF("---xxxxx Random Reference : %d\n", data[0] & 0x1f);
+
+ data++;
+ if (data + 1>= end)
+ RETTRUNK();
+
+ OUTF("xxxxxxxx T1/T2/T3\n");
+ data++;
+ OUTF("xxxxxxxx T1/T2/T3\n");
+ data++;
+ /* END Request Reference */
+}
+
+static void
+TimingAdvance()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("--xxxxxx Timing advance value: %d\n", data[0] & 0x3f);
+ data++;
+}
+
+static void
+StartingTime()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("01111100 Starting Time block\n");
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ unsigned char t3;
+ OUTF("%s T1 Frame Number: %u\n", BitRowFill(data[0], 0xf8), data[0] >> 3);
+ t3 = (data[0] & 0x07) << 5;
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ t3 |= (data[0] >> 5);
+ OUTF("%s T2 Frame Number: %u\n", BitRowFill(data[0], 0x1f), data[0] & 0x1f);
+ OUTF("........ T3 Frame Number: %u\n", t3);
+}
+
+/*
+ * RRsystemInfo5
+ */
+static void
+l2_NeighbourCellDescription()
+{
+ if (data >= end)
+ RETTRUNK();
+ l2_BcchAllocation();
+}
+
+
+static void
+l2_ChannelRelease()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s\n", id_list_get(list_ChannelRelease, data[0]));
+ data++;
+}
+
+static void
+l2_MMcmServiceRequest()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07);
+ OUTF("%s\n", id_list_get(list_RequestServiceType, data[0] & 0x0f));
+ data++;
+ MSClassMarkTwo();
+ if (data >= end)
+ RETTRUNK();
+
+ if (data[0] == 0x20)
+ {
+ OUTF("FIXME: classmark3\n");
+ return;
+ }
+
+ l2_MobId();
+}
+
+
+static void
+MSClassMarkOne()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ if (((data[0] >> 5) & 0x03) == 0)
+ OUTF("-00----- Revision Level: Phase 1\n");
+ else if (((data[0] >> 5) & 0x03) == 1)
+ OUTF("-01----- Revision Level: Phase 2\n");
+ else
+ OUTF("-xx----- Revision Level: Unknown\n");
+ if (((data[0] >> 4) & 1) == 0)
+ OUTF("---0---- Controlled early classmark sending: Not implemented\n");
+ else
+ OUTF("---1---- Controlled early classmark sending: Implemented\n");
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- A5/1 not available\n");
+ else
+ OUTF("----0--- A5/1 available\n");
+
+ OUTF("%s RF power class capability: Class %u\n", BitRowFill(data[0], 0x07), (data[0] & 0x07) + 1);
+
+ data++;
+}
+
+static void
+MSClassMarkTwo()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s MS Classmark 2 length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+ MSClassMarkOne();
+
+ if ((data[0] >> 6) & 1)
+ OUTF("-1------ Pseudo Sync Capability: present\n");
+ else
+ OUTF("-1------ Pseudo Sync Capability: not present\n");
+
+ if (((data[0] >> 4) & 0x03) == 0)
+ OUTF("--00---- SS Screening: Phase 1 default value\n");
+ else if (((data[0] >> 4) & 0x03) == 1)
+ OUTF("--01---- SS Screening: Phase 2 error handling\n");
+ else
+ OUTF("--xx---- SS Screening: UNKNOWN\n");
+
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- Mobile Terminated Point to Point SMS: supported\n");
+ else
+ OUTF("----0--- Mobile Terminated Point to Point SMS: not supported\n");
+
+ if ((data[0] >> 2) & 1)
+ OUTF("-----1-- VoiceBroadcastService: supported\n");
+ else
+ OUTF("-----0-- VoiceBroadcastService: not supported\n");
+
+ if ((data[0] >> 1) & 1)
+ OUTF("------1- VoiceGroupCallService: supported\n");
+ else
+ OUTF("------0- VoiceGroupCallService: not supported\n");
+
+ if (data[0] & 1)
+ OUTF("-------1 MS supports E-GSM or R-GSM: supported\n");
+ else
+ OUTF("-------0 MS supports E-GSM or R-GSM: not supported\n");
+
+ data++;
+ if (data >= end)
+ RETTRUNK();
+
+
+ if ((data[0] >> 7) & 1)
+ OUTF("1------- CM3 option: supported\n");
+ else
+ OUTF("0------- CM3 option: not supported\n");
+
+ if ((data[0] >> 5) & 1)
+ OUTF("--1----- LocationServiceValueAdded Capability: supported\n");
+ else
+ OUTF("--0----- LocationServiceValueAdded Capability: not supported\n");
+
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- SoLSA Capability: supported\n");
+ else
+ OUTF("----0--- SoLSA Capability: not supported\n");
+
+ if ((data[0] >> 1) & 1)
+ OUTF("------1- A5/3 available\n");
+ else
+ OUTF("------0- A5/3 not available\n");
+
+ if (data[0] & 1)
+ OUTF("-------1 A5/2: available\n");
+ else
+ OUTF("-------0 A5/2: not available\n");
+ data++;
+}
+
+static void
+l2_RRciphModCmd()
+{
+ if (data >= end)
+ RETTRUNK();
+ if (((data[0] >> 1) & 0x07) == 0x07)
+ OUTF("----111- Cipher: reserved [UNKNOWN]\n");
+ else
+ OUTF("%s Cipher: A5/%u\n", BitRowFill(data[0], 0x0e), ((data[0] >> 1) & 0x07) + 1);
+
+
+ if (data[0] & 1)
+ OUTF("-------1 Start ciphering\n");
+ else
+ OUTF("-------0 No ciphering\n");
+
+ if ((data[0] >> 4) & 1)
+ OUTF("---1---- Cipher Response: IMEISV shall be included\n");
+ else
+ OUTF("---0---- Cipher Response: IMEISV shall not be included\n");
+ data++;
+}
+
+static void
+l2_RRciphModCompl()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ if (data[0] != 0x17)
+ return;
+ if (++data >= end)
+ RETTRUNK();
+ l2_MobId();
+}
+
+static void
+l2_TmsiReallocCommand()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ l2_MccMncLac();
+ l2_MobId();
+}
+
+static void
+l2_sms()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ if ((data[0] == 0x04))
+ OUTF("00000100 Type: CP-ACK\n");
+ else if (data[0] == 0x10)
+ OUTF("00010000 Type: CP-ERROR\n");
+ else if (data[0] == 1) {
+ OUTF("00000001 Type: CP-DATA\n");
+ data++;
+ cpData();
+ } else
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff));
+}
+
+static void
+cpDataUp()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+ Address("SMSC");
+ if (data >= end)
+ RETTRUNK();
+
+ /* FIXME: Be more detailed here about message flags */
+ OUTF("%s Message Flags: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data + 1 >= end)
+ RETTRUNK();
+ int num = data[0] << 8;
+ OUTF("%s Reference Number [continue]\n", BitRowFill(data[0], 0xff));
+ data++;
+ num |= data[0];
+ OUTF("%s Reference Number: %u\n", BitRowFill(data[0], 0xff), num);
+ data++;
+
+ /* Destination address */
+ Address("Destination");
+ SmsProtocolDataValidity();
+ if (data >= end)
+ RETTRUNK();
+}
+
+/* From Network to MS */
+/* Called when a full 140 byte SMS is received */
+static void
+cpData()
+{
+ int n_symbols;
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ if ((data[0] & 1) == 0)
+ {
+ //OUTF("xxxxxxx0 cpDataUp FIXME\n");
+ //data++;
+ cpDataUp();
+ return;
+ }
+ OUTF("%s reserved\n", BitRowFill(data[0], 0xf8));
+ OUTF("%s Message Type Indicator(MTI): %s\n", BitRowFill(data[0], 0x07), id_list_get(list_MTI, data[0] & 0x07));
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Message Reference: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ return; /* Can happen that msg terminated here... */
+
+ /* RP-address */
+ Address("SMSC");
+ if (data >= end)
+ RETTRUNK();
+
+#if 0
+ OUTF("%s TP-MTI, TP-MMS, TP-SRI, TP-UDIH, TP-RP: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Reference number: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if ((data[0]) == 0x44)
+ {
+ OUTF("FIXME: ems_type\n");
+ return;
+ }
+ if (++data >= end)
+ RETTRUNK();
+
+ OUTF("%s Parameter\n", BitRowFill(data[0], 0xff));
+ data++;
+#endif
+
+ TPAddress("Destination");
+ OUTF("%s TP-MTI: %s\n", BitRowFill(data[0], 0x03), id_list_get(list_TP_MTI, data[0] & 0x03));
+
+ /* SMS-DELIVER and SMS-STATUS-REPORT.
+ * This may be different for other SMS-types! (FIXME) */
+ if ((data[0] >> 2) & 1)
+ OUTF("-----1-- More Messages (TP-MMS): No\n");
+ else
+ OUTF("-----0-- More Messages (TP-MMS): Yes\n");
+ OUTF("%s Status Report Indication (TP-SRI)\n", BitRowFill(data[0], 0x20));
+ if ((data[0] >> 6) & 1)
+ {
+ OUTF("-1------ User Data Header Indicator (TP-UDHI): Yes\n");
+ nfo.flags |= GSMSP_NFO_UDHI;
+ } else {
+ OUTF("-0------ User Data Header Indicator (TP-UDHI): No\n");
+ }
+ OUTF("%s Reply Path (TP-RP)\n", BitRowFill(data[0], 0x80));
+ /* SMS-DELIVER and SMS-STATUS-REPORT end */
+ data++;
+
+ /* FIXME: Why is TPAddress differently encoded as SMSC address?
+ * Am i doing something wrong or are the GSM people nuts?
+ */
+ TPAddress("Originating (TP-OA)");
+
+ SmsProtocolDataValidity();
+
+ SmscTimestamp();
+ if (data >= end)
+ RETTRUNK();
+ n_symbols = data[0];
+ OUTF("%s User Data Length (TP-UDL): %u symbols\n", BitRowFill(data[0], 0xff), data[0]);
+
+ data++;
+#if 0
+ if ((data[0] >> 6) & 1)
+ {
+ OUTF("-1------ TP User Data Header Indicator (TP-UDHI): yes\n");
+ data++;
+ OUTF("-------- FIXME: Decode header\n");
+ data += (data[0] + 1);
+ /* FIXME: Skip over fill bits as well. GSM 03.40 9.2.3.24 */
+ } else {
+ OUTF("-0------ TP User Data Header Indicator (TP-UDHI): no\n");
+ //data++; /* Contains directly the data!!! */
+ }
+#endif
+
+ if (sms_con.ptr == NULL)
+ sms_con.ptr = sms_con.buf;
+
+ if (nfo.flags & GSMSP_NFO_UDHI)
+ sms_udh();
+ if ((nfo.flags & GSMSP_NFO_SMSCON) && (!(nfo.flags & GSMSP_NFO_LASTSMSCHUNK)))
+ {
+ HEXDUMPF(data, end - data, "TP-UD\n");
+ /* If this is a concatendated SMS then wait for rest of data */
+ return;
+ }
+ if (sms_con.ptr > sms_con.buf)
+ {
+ /* was a concatenated sms. output concatendated TP-UD */
+ data = sms_con.buf;
+ start = data;
+ end = sms_con.ptr;
+ }
+
+ if (nfo.flags & GSMSP_NFO_DEFAULTALPHABET)
+ {
+ if (((end - data) * 8 ) / 7 < n_symbols)
+ n_symbols = ((end - data) * 8) / 7;
+ sms_default_alphabet(n_symbols);
+ } else if (nfo.flags & GSMSP_NFO_SIMDATADL) {
+ HEXDUMPF(data, end - data, "Format Sim Data Download\n");
+ simdatadownload();
+ } else {
+ HEXDUMPF(data, end - data, "TP-UD\n");
+ }
+ /* Reset concatendating sms counter again */
+ if ((sms_con.ptr > sms_con.buf) && (nfo.flags & GSMSP_NFO_LASTSMSCHUNK))
+ {
+ memset(&sms_con, 0, sizeof sms_con);
+ }
+}
+
+static unsigned char sms_default_alpha[] = ""
+"@_$__________\r__"
+"________________"
+" !\"#_%&`()*+,-./"
+"0123456789:;<=>?"
+"_ABCDEFGHIJKLMNO"
+"PQRSTUVWXYZ_____"
+"_abcdefghijklmno"
+"pqrstuvwxyz_____";
+
+/*
+ * Len is the number of symbols (not number of bytes)
+ */
+static void
+sms_default_alphabet(int len)
+{
+ unsigned char buf[512];
+ unsigned char *ptr = buf;
+ unsigned char *buf_end = buf + sizeof buf;
+
+ while (ptr < buf_end)
+ {
+ *ptr++ = sms_default_alpha[data[0] & 0x7f];
+ if (--len <= 0) break;
+ *ptr++ = sms_default_alpha[((data[0] >> 7) & 0x01) | ((data[1] & 0x3f) << 1)];
+ if (--len <= 0) break;
+ *ptr++ = sms_default_alpha[((data[1] >> 6) & 0x03) | ((data[2] & 0x1f) << 2)];
+ if (--len <= 0) break;
+ *ptr++ = sms_default_alpha[((data[2] >> 5) & 0x07) | ((data[3] & 0x0f) << 3)];
+ if (--len <= 0) break;
+ *ptr++ = sms_default_alpha[((data[3] >> 4) & 0x0f) | ((data[4] & 0x07) << 4)];
+ if (--len <= 0) break;
+ *ptr++ = sms_default_alpha[((data[4] >> 3) & 0x1f) | ((data[5] & 0x03) << 5)];
+ if (--len <= 0) break;
+ *ptr++ = sms_default_alpha[((data[5] >> 2) & 0x3f) | ((data[6] & 0x01) << 6)];
+ if (--len <= 0) break;
+ *ptr++ = sms_default_alpha[((data[6] >> 1) & 0x7f)];
+ if (--len <= 0) break;
+ data += 7;
+ }
+ data = end;
+ *ptr = '\0';
+ OUTF("-------- Content: %s\n", buf);
+}
+
+/* User Data Header (GSM 03.40:9.2.3.24) */
+static void
+sms_udh()
+{
+ int len_udh;
+ int len;
+ int seq_total;
+ const unsigned char *end_udh;
+ const unsigned char *next;
+
+ if (data >= end)
+ RETTRUNK();
+ len_udh = data[0];
+ end_udh = data + data[0] + 1;
+ OUTF("%s User Data Header Length: %u octets\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+
+ if (end_udh > end)
+ end_udh = end;
+
+ while (data < end_udh)
+ {
+ if ((data + 1 >= end_udh) || (data + data[1] + 2 > end_udh))
+ {
+ OUTF("ERR: Short data\n");
+ break;
+ }
+ next = data + data[1] + 2;
+ len = data[1];
+
+ if (data[0] == 0) {
+ OUTF("00000000 Concatenated short messages, 8-bit reference number\n");
+ data++;
+ OUTF("-------- Length: %u\n", data[0]);
+ data++;
+ OUTF("-------- Message Reference Number: %.2X\n", data[0]);
+ data++;
+ OUTF("-------- Number of Segments: %.2X\n", data[0]);
+ seq_total = data[0];
+ data++;
+ OUTF("-------- Seq Number: %.2X\n", data[0]);
+ //OUTF("DEBUG: %u += memcpy(%p, %p, %u)\n", sms_con.ptr - sms_con.buf, sms_con.ptr, end_udh, end-end_udh);
+ memcpy(sms_con.ptr, end_udh, end - end_udh);
+ sms_con.ptr += (end - end_udh);
+
+ nfo.flags |= GSMSP_NFO_SMSCON;
+ if (data[0] == seq_total)
+ nfo.flags |= GSMSP_NFO_LASTSMSCHUNK;
+ data++;
+ } else if (data[0] == 1)
+ OUTF("00000001 Special SMS Message Indication\n");
+ else if (data[0] == 4) {
+ OUTF("00000100 Application port address, 8 bit\n");
+ OUTF("-------- Desitnation Port: %u (0x%.2X)\n", data[1], data[1]);
+ OUTF("-------- Source Port: %u (0x%.2X)\n", data[2], data[2]);
+ data += 3;
+ } else if (data[0] == 5) {
+ unsigned short dport, sport;
+ dport = (data[2] << 8) + data[3];
+ sport = (data[4] << 8) + data[5];
+ OUTF("00000101 Application port address, 16 bit\n");
+ data++;
+ OUTF("-------- Length: %u\n", data[0]);
+ data++;
+ /* 0 - 15999 allocated by IANA
+ * 16000 - 16999 Available for allocation by application
+ * 17000 - 65535 reserved
+ */
+ OUTF("-------- Destination Port: %u\n", dport);
+ data += 2;
+ OUTF("-------- Source Port: %u\n", sport);
+ data += 2;
+ } else if (data[0] == 6)
+ OUTF("00000110 SMSC Control Parameters\n");
+ else if (data[0] == 7)
+ OUTF("00000111 UDH Source Indicator\n");
+ else if (data[0] == 8) {
+ OUTF("00001000 Concatenated short messages, 16-bit reference number\n");
+ data++;
+ OUTF("-------- Message Reference Number: %.4X\n", (data[0]<<8) + data[1]);
+ data += 2;
+ OUTF("-------- Number of Segments: %.2X\n", data[0]);
+ seq_total = data[0];
+ data++;
+ OUTF("-------- Seq Number: %.2X\n", data[0]);
+ memcpy(sms_con.ptr, end_udh, end - end_udh);
+ sms_con.ptr += (end - end_udh);
+
+ nfo.flags |= GSMSP_NFO_SMSCON;
+ if (data[0] == seq_total)
+ nfo.flags |= GSMSP_NFO_LASTSMSCHUNK;
+ data++;
+ } else if (data[0] == 9)
+ OUTF("00001001 Wireless Control Message Protocol\n");
+ else if ((data[0] >= 0x70) && (data[0] <= 0x7f))
+ OUTF("%s SIM Toolkit Security Header\n", BitRowFill(data[0], 0xff));
+ else if ((data[0] >= 0x80) && (data[0] <= 0x9f))
+ OUTF("%s SME to SME specific use\n", BitRowFill(data[0], 0xff));
+ else if ((data[0] >= 0xc0) && (data[0] <= 0xdf))
+ OUTF("%s SC specific use\n", BitRowFill(data[0], 0xff));
+ else
+ OUTF("%s reserved\n", BitRowFill(data[0], 0xff));
+
+ data = next;
+ }
+
+}
+
+static void
+TPAddress(const char *str)
+{
+ int len;
+
+ if (data >= end)
+ RETTRUNK();
+
+ len = data[0];
+ OUTF("%s %s Address Length: %u\n", BitRowFill(data[0], 0xff), str, data[0]);
+ data++;
+ if (len <= 0)
+ {
+ data++;
+ return;
+ }
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] >> 7)
+ OUTF("1------- Extension\n");
+
+ OUTF("%s\n", id_list_get(list_SMSCAddressType, (data[0] >> 4) & 0x07));
+ OUTF("%s\n", id_list_get(list_SMSCAddressNumberingPlan, data[0] & 0x0f));
+ data++;
+
+ OUTF("-------- Number(%u): ", len);
+ while (len > 0)
+ {
+ if ((data[0] >> 4) == 0x0f)
+ OUT("%X", data[0] & 0x0f);
+ else
+ OUT("%X%X", data[0] & 0x0f, data[0] >> 4);
+ len -= 2;
+ data++;
+ }
+ OUT("\n");
+}
+
+static void
+Address(const char *str)
+{
+ int len;
+
+ if (data >= end)
+ RETTRUNK();
+ len = data[0];
+ OUTF("%s %s Address Length: %u\n", BitRowFill(data[0], 0xff), str, data[0]);
+ data++;
+ if (len <= 0)
+ {
+ data++;
+ return;
+ }
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] >> 7)
+ OUTF("1------- Extension\n");
+
+ OUTF("%s\n", id_list_get(list_SMSCAddressType, (data[0] >> 4) & 0x07));
+ OUTF("%s\n", id_list_get(list_SMSCAddressNumberingPlan, data[0] & 0x0f));
+ len--;
+ data++;
+ if (len <= 0)
+ return;
+ const unsigned char *thisend = data + len;
+ if (thisend > end)
+ thisend = end;
+
+ OUTF("-------- Number(%d): ", len);
+ while (data < thisend)
+ {
+ if ((data[0] >> 4) == 0x0f)
+ OUT("%X", data[0] & 0x0f);
+ else
+ OUT("%X%X", data[0] & 0x0f, data[0] >> 4);
+ data++;
+ }
+ OUT("\n");
+}
+
+
+static void
+l2_RRpagingresponse()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ if ((data[0] & 0x07) == 0x07)
+ OUTF("-----111 Cipher key sequence: Key not available!\n");
+ else
+ OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x07), data[0] & 0x07);
+
+ OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07);
+
+ data++;
+ MSClassMarkTwo();
+ if (data >= end)
+ RETTRUNK();
+ l2_MobId();
+}
+
+static void
+l2_RRassignCommand()
+{
+ ChannelDescriptionTwo();
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s Training seq. code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
+ if (((data[0] >> 2) & 0x07) == 0x00)
+ l2_SingleChannelAssCom();
+ else if (((data[0] >> 4) & 1) == 0x01)
+ l2_HoppingChannelAssCom();
+ else
+ OUTF("xxx0??xxx UNKNOWN %d\n", (data[0] >> 3) & 0x3);
+}
+
+static void
+l2_RRassignComplete()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s\n", id_list_get(list_ChannelRelease, data[0]));
+ data++;
+}
+
+static void
+ChannelDescriptionTwo()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Timeslot number: %d\n", BitRowFill(data[0], 0x07), data[0] & 0x07);
+ OUTF("%s Channel Description: %s\n", BitRowFill(data[0], 0xf8), id_list_get(list_ChannelDescriptionTwo, data[0] >> 3));
+
+ data++;
+}
+
+static void
+l2_SingleChannelAssCom()
+{
+ int freq = (data[0] & 0x03) << 8;
+
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ freq |= data[0];
+ OUTF("........ Absolute RF channel number: %u\n", freq);
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Power Level: %u\n", BitRowFill(data[0], 0x1f), data[0] & 0x1f);
+ if (++data >= end)
+ RETTRUNK();
+ if (data[0] != 0x63)
+ return;
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s\n", id_list_get(list_ChannelMode, data[0]));
+}
+
+static void
+l2_HoppingChannelAssCom()
+{
+ OUTF("FIXME %s\n", __func__);
+}
+
+static void
+CCalerting()
+{
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] != 0x1e)
+ return;
+
+ data++;
+ ProgressIndicator();
+}
+
+static void
+ProgressIndicator()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s Length of IE Progress Indicator: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Coding: %s\n", BitRowFill(data[0], 0x60), id_list_get(list_CodingStandard, (data[0] >> 5) & 0x03));
+ OUTF("%s Location: %s\n", BitRowFill(data[0], 0x0f), id_list_get(list_Location, data[0] & 0x0f));
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s\n", id_list_get(list_Progress, data[0] & 0x7f));
+ data++;
+}
+
+static void
+CCsetup()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ while (data < end)
+ {
+ if (data[0] == 0x04)
+ {
+ OUTF("00000100 Bearer Capability\n");
+ data++;
+ BearerCap();
+ } else if (data[0] == 0x1e) {
+ OUTF("00011110 Progress Indicator\n");
+ ProgressIndicator();
+ return;
+ } else if (data[0] == 0x5e) {
+ OUTF("01011110 Called Party BCD Number\n");
+ data++;
+ BCDNumber();
+ } else {
+ OUTF("%s FIXME\n", BitRowFill(data[0], 0xff));
+ break;
+ }
+ }
+
+ data++;
+}
+
+static void
+Cause()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s Length of Cause: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+
+ OUTF("%s Coding: %s\n", BitRowFill(data[0], 0x60), id_list_get(list_CodingStandard, (data[0] >> 5) & 0x03));
+ OUTF("%s Location: %s\n", BitRowFill(data[0], 0x0f), id_list_get(list_Location, data[0] & 0x0f));
+ if (++data >= end)
+ RETTRUNK();
+
+ OUTF("%s Cause: %s\n", BitRowFill(data[0], 0x7f), id_list_get(list_Cause, data[0] & 0x7f));
+ data++;
+}
+
+static void
+l2_RRclassmarkChange()
+{
+ if (data >= end)
+ RETTRUNK();
+ MSClassMarkTwo();
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] == 0x20)
+ {
+ OUTF("00100000 Class Mark 3\n");
+ data++;
+ ClassMarkThree();
+ }
+}
+
+static void
+MultiSupportTwo()
+{
+ int c = 0;
+ if (data + 1 >= end)
+ RETTRUNK();
+ OUTF("0110---- P-GSM, E-GSM, R-GSM supported, DSC 1800 not supported\n");
+
+ for (c = 3; c >= 0; c--)
+ {
+ if ((data[0] >> c) & 0x1)
+ OUTF("%s A5/%d available\n", BitRowFill(data[0], 1<<c), 4+c);
+ else
+ OUTF("%s A5/%d not available\n", BitRowFill(data[0], 1<<c), 4+c);
+ }
+ data++;
+ OUTF("%s Associated Radio capability 1 Power Class: %d\n", BitRowFill(data[0], 0xf), data[0] & 0xf);
+ OUTF("%s Associated Radio capability 2 Power Class: %d\n", BitRowFill(data[0], 0xf0), data[0] >> 4);
+}
+
+static void
+ClassMarkThree()
+{
+ unsigned char c;
+
+ if (data + 1 >= end)
+ RETTRUNK();
+ OUTF("%s Length: %d\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+
+ c = data[0] >> 4;
+ if ((c == 0x5) || (c == 0x6))
+ MultiSupportTwo();
+ else
+ OUTF("FIXME\n");
+}
+
+static void
+SmsProtocolDataValidity()
+{
+ unsigned char b7,b6,b5,b4;
+
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Protocol Identifier: 0x%.2X\n", BitRowFill(data[0], 0xff), data[0]);
+
+ b7 = (data[0] >> 7) & 0x1;
+ b6 = (data[0] >> 6) & 0x1;
+ b5 = (data[0] >> 5) & 0x1;
+ b4 = (data[0] >> 4) & 0x1;
+
+ if ( !b7 && !b6 && b5) {
+ OUTF("001----- Telematic Interworking\n");
+ }
+ if ( !b7 && b6 ) {
+ switch ( (data[0] & 0x3f ) ) {
+ case 0x1f:
+ OUTF("01011111 Return Call Message\n");
+ break;
+ case 0x3d:
+ OUTF("01111101 ME Data Download\n");
+ break;
+ case 0x3e:
+ OUTF("01111110 ME De-personalization SMS\n");
+ break;
+ case 0x3f:
+ OUTF("01111111 SIM Data download\n");
+ break;
+ default:break;
+ }
+
+ }
+
+ if (data[0] == 0x00)
+ OUTF("00000000 normal\n");
+
+ if (data[0] == 0x40)
+ OUTF("00101000 SMS PING\n");
+
+ if (data[0] == 0x7f) {
+ nfo.flags |= GSMSP_NFO_SIMDATADL;
+ // printf("set GSMSP_NFO_SIMDATADL=1\n");
+ } else
+ nfo.flags &= ~GSMSP_NFO_SIMDATADL;
+
+ data++;
+ sms_dcs();
+}
+
+static void
+BearerCap()
+{
+ int len;
+ char extension = 0;
+
+ if (data >= end)
+ RETTRUNK();
+
+ len = data[0];
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (data + len > end)
+ len = end - data;
+ if (++data >= end)
+ RETTRUNK();
+
+ if ((data[0] >> 7) & 0x1)
+ {
+ extension = 1;
+ OUTF("1------- Extension: yes\n");
+ } else {
+ OUTF("0------- Extension: no\n");
+ // extenstion = 0;
+ }
+
+ OUTF("%s Radio Channel: %s\n", BitRowFill(data[0], 0x60), id_list_get(list_RadioChannelReq, (data[0] >> 5) & 0x03));
+ if ((data[0] >> 4) & 1)
+ OUTF("---1---- Coding Standard: reserved\n");
+ else
+ OUTF("---0---- Coding Standard: GSM\n");
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- Transfer Mode: Packet\n");
+ else
+ OUTF("----0--- Transfer Mode: Circuit\n");
+
+ OUTF("%s Transfer Capability: %s\n", BitRowFill(data[0], 0x07), id_list_get(list_TransferCap, data[0] & 0x07));
+ data++;
+
+ if (extension)
+ {
+ OUTF("FIXME: Stuff missing here\n");
+ /* FIXME: can be followed by antoher estension etc!*/
+ }
+
+ if ((data[0] >> 7) & 0x1)
+ {
+ extension = 1;
+ OUTF("1------- Extension: yes\n");
+ } else {
+ OUTF("0------- Extension: no\n");
+ // extenstion = 0;
+ }
+
+ if ((data[0] >> 6) & 0x01)
+ OUTF("-1------ Compression: yes\n");
+ else
+ OUTF("-0------ Compression: no\n");
+
+ OUTF("%s Duplex Mode: %s\n", BitRowFill(data[0], 0x8), id_list_get(list_Duplex, data[0] & 0x8));
+ if ((data[0] >> 1) & 0x1)
+ OUTF("------1- Rate Request: Data 4.8 kb/s, full rate, n. transp. 6kb req\n");
+ data++;
+
+ if ((data[0] >> 7) & 0x1)
+ {
+ extension = 1;
+ OUTF("1------- Extension: yes\n");
+ } else {
+ OUTF("0------- Extension: no\n");
+ // extenstion = 0;
+ }
+ OUTF("%s Rate Adaptation: %s\n", BitRowFill(data[0], 0x18), id_list_get(list_Rate, data[0] & 0x18));
+ OUTF("%s Signalling Access Protocol: %s\n", BitRowFill(data[0], 0x7), id_list_get(list_Signalling, data[0] & 0x7));
+ data++;
+ if ((data[0] & 0x1) == 1)
+ OUTF("-------1 Asynchronous\n");
+ else
+ OUTF("-------0 Synchronous\n");
+ data++;
+ /* FIXME: some octets might continue here, depending
+ * on extension */
+ OUTF("FIXME: some data might be in extentions\n");
+}
+
+static void
+AuthenticationRequest()
+{
+ char rand[16 * 2 + 1];
+
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s Cipher Key Sequence Number: %u\n", BitRowFill(data[0], 0x07), data[0] & 0x07);
+ data++;
+ if (data + 16 > end)
+ RETTRUNK();
+
+ snprintf(rand, sizeof rand, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
+ OUTF("-------- RAND: %s\n", rand);
+ data += 16;
+}
+
+static void
+LocationUpdateRequest()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Cipher Key Sequence Number: %d\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x7);
+ if (data[0] & 0x8)
+ OUTF("----1--- Follow-on request pending\n");
+ else
+ OUTF("----0--- No follow-on request pending\n");
+ OUTF("%s Location Update: %s\n", BitRowFill(data[0], 0x3), id_list_get(list_TypeOfLocationUpdate, data[0] & 0x03));
+ data++;
+ l2_MccMncLac();
+ MSClassMarkOne();
+ l2_MobId();
+}
+
+
+static void
+AuthenticationResponse()
+{
+ char sres[4 * 2 + 1];
+
+ if (data + 4 > end)
+ RETTRUNK();
+ snprintf(sres, sizeof sres, "%02x%02x%02x%02x", data[0], data[1], data[2], data[3]);
+ OUTF("-------- SRES: %s\n", sres);
+ data += 4;
+}
+
+
+static void
+sms_dcs()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ if (data[0] == 0)
+ {
+ OUTF("00000000 Default Data Coding Scheme (default Alphabet)\n");
+ nfo.flags |= GSMSP_NFO_DEFAULTALPHABET;
+ data++;
+ return;
+ }
+
+ if (((data[0] >> 6) & 0x03) == 0)
+ {
+ OUTF("00------ General Data Coding\n");
+ if ((data[0] >> 5) & 1)
+ OUTF("--1----- Compressed (TS 03.42)\n");
+ else
+ OUTF("--0----- Not compressed\n");
+ if ((data[0] >> 4) & 1)
+ OUTF("---1---- Message class meaning: yes\n");
+ else
+ OUTF("---0---- Message class meaning: no\n");
+
+
+ OUTF("%s Coding: %s\n", BitRowFill(data[0], 0x0c), id_list_get(list_alphabet, (data[0] >> 5) & 0x03));
+ /* If bit 4 is set then bit 0..1 have a Message Class meaning */
+ if ((data[0] >> 4) & 1)
+ {
+ OUTF("%s Message Class: %s\n", BitRowFill(data[0], 0x03), id_list_get(list_MessageClassMeaning, data[0] & 0x03));
+ } else {
+
+ OUTF("%s Message Class: No meaning (see bit4)\n", BitRowFill(data[0], 0x03));
+ }
+ } else if ((((data[0] >> 6) & 0x03) == 0x03) && (((data[0] >> 4) & 0x03) != 0x03)) {
+ if (((data[0] >> 4) & 0x0f) == 0x0c) {
+ OUTF("1100---- Message Waiting Indicator Group: Discard Message\n");
+ } else if (((data[0] >> 4) & 0x0f) == 0x0d) {
+ OUTF("1101---- Message Waiting Indicator Group: Store Message\n");
+ } else if (((data[0] >> 4) & 0x0f) == 0x0e) {
+ OUTF("1110---- Message Waiting Indicator Group: Store Message\n");
+ }
+ OUTF("FIXME GSM 03.38\n");
+ } else if (((data[0] >> 4) & 0x0f) == 0x0f) {
+ OUTF("1111---- Data Coding/Message Class\n");
+ OUTF("%s reserved\n", BitRowFill(data[0], 0x08));
+ if ((data[0] >> 2) & 1)
+ OUTF("-----1-- Message coding: 8 bit\n");
+ else {
+ OUTF("-----0-- Message coding: default alphabet\n");
+ nfo.flags |= GSMSP_NFO_DEFAULTALPHABET;
+ }
+ OUTF("%s Message Class: %s\n", BitRowFill(data[0], 0x03), id_list_get(list_MessageClassMeaning, data[0] & 0x03));
+ } else {
+ OUTF("%s reserved\n", BitRowFill(data[0], 0xff));
+ }
+
+ data++;
+}
+
+#define FlipBCD(val) ((val & 0x0f) << 4) | (val >> 4)
+
+static void
+SmscTimestamp()
+{
+ if (data + 6 >= end)
+ RETTRUNK();
+
+ OUTF("-------- SMSC Timestamp: %02x-%02x-%02x %02x:%02x:%02x (TZ %02x)\n", FlipBCD(data[0]), FlipBCD(data[1]), FlipBCD(data[2]), FlipBCD(data[3]), FlipBCD(data[4]), FlipBCD(data[5]), FlipBCD(data[6]));
+
+ data += 7;
+}
+
+
+static void
+simdatadownload()
+{
+ unsigned char chl; /* command header length */
+ int i;
+
+ OUTF("-------- Length of CPL: 0x%.4X (%u)\n", (data[0]<<8)+data[1],(data[0]<<8)+data[1]);
+ data+=2;
+ chl = data[0];
+ OUTF("-------- Command Header Length: 0x%.2X (%u)\n",chl,chl);
+ data++;
+ // SPI
+ OUTF("%s SPI : 0x%.2X\n",BitRowFill(data[0], 0xff), data[0]);
+ switch (data[0] & 0x3) {
+ case 0x00:
+ OUTF("------00 No RC, CC or DS\n");
+ break;
+ case 0x01:
+ OUTF("------01 Redudancy Check\n");
+ break;
+ case 0x02:
+ OUTF("------10 Cryptographic Checksum\n");
+ break;
+ case 0x03:
+ OUTF("------11 Digital Signature\n");
+ break;
+ default: break;
+ }
+ if ( ((data[0]>>2)& 0x01) )
+ OUTF("-----1-- Ciphering\n");
+ else
+ OUTF("-----0-- No Ciphering\n");
+
+ switch ( (data[0]>>3) & 0x03 ) {
+ case 0x00:
+ OUTF("---00--- No counter available\n");
+ break;
+ case 0x01:
+ OUTF("---01--- Counter available; no replay or sequence checking\n");
+ break;
+ case 0x02:
+ OUTF("---10--- Process if counter is higher\n");
+ break;
+ case 0x03:
+ OUTF("---11--- Process if counter is 1 higher\n");
+ break;
+ default:break;
+ }
+ data++;
+ OUTF("%s PoR : 0x%.2X\n", BitRowFill(data[0], 0xff), data[0]); //FIXME:implement me
+ switch (data[0] & 0x03) {
+ case 0x00:
+ OUTF("------00 No PoR-reply to sending entity\n");
+ break;
+ case 0x01:
+ OUTF("------01 PoR required to be send to sending entity\n");
+ break;
+ case 0x02:
+ OUTF("------10 PoR required only on error\n");
+ break;
+ case 0x03:
+ OUTF("-------- reserved\n");
+ break;
+ default:break;
+ }
+ switch ( (data[0]>>2) & 0x03) {
+ case 0x00:
+ OUTF("----00-- No RC/CC/DS applied to PoR\n");
+ break;
+ case 0x01:
+ OUTF("----01-- PoR with simple RC\n");
+ break;
+ case 0x02:
+ OUTF("----10-- PoR with CC\n");
+ break;
+ case 0x03:
+ OUTF("----11-- PoR with DS\n");
+ break;
+ default:break;
+ }
+ if ( (data[0]>>4) & 0x01 )
+ OUTF("---1---- PoR via SMS-SUBMIT\n");
+ else
+ OUTF("---0---- PoR via SMS-Deliver-Report\n");
+
+
+ data++;
+
+ // KIc
+ OUTF("%s KIc: 0x%.2X\n",BitRowFill(data[0], 0xff), data[0]);
+
+ switch(data[0] & 0x03) {
+ case 0x00:
+ OUTF("------00 Algorithm known implicitly\n");
+ break;
+ case 0x01:
+ OUTF("------01 DES\n");
+ break;
+ case 0x02:
+ OUTF("------10 Reserved.\n");
+ break;
+ case 0x03:
+ OUTF("------11 properietary Implementation\n");
+ break;
+ default:break;
+ }
+
+ switch ( (data[0]>>2) & 0x03) {
+ case 0x00:
+ OUTF("----00-- DES-CBC\n");
+ break;
+ case 0x01:
+ OUTF("----01-- 3DES-outer-CBC 2 different Keys\n");
+ break;
+ case 0x02:
+ OUTF("----10-- 3DES-outer-CBC 3 different Keys\n");
+ break;
+ case 0x03:
+ OUTF("----11-- DES-ECB\n");
+ break;
+ default:break;
+ }
+ OUTF("XXX----- Key Number: %.2X\n", data[0]>>4 );
+ data++;
+
+ // KId
+ OUTF("%s KId: 0x%.2X\n",BitRowFill(data[0], 0xff), data[0]);
+
+ switch(data[0] & 0x03) {
+ case 0x00:
+ OUTF("------00 Algorithm known implicitly\n");
+ break;
+ case 0x01:
+ OUTF("------01 DES\n");
+ break;
+ case 0x02:
+ OUTF("------10 Reserved.\n");
+ break;
+ case 0x03:
+ OUTF("------11 properietary Implementation\n");
+ break;
+ default:break;
+ }
+
+ switch ( (data[0]>>2) & 0x03) {
+ case 0x00:
+ OUTF("----00-- DES-CBC\n");
+ break;
+ case 0x01:
+ OUTF("----01-- 3DES-outer-CBC 2 different Keys\n");
+ break;
+ case 0x02:
+ OUTF("----10-- 3DES-outer-CBC 3 different Keys\n");
+ break;
+ case 0x03:
+ OUTF("----11-- DES-ECB\n");
+ break;
+ default:break;
+ }
+ OUTF("XXX----- Key Number: %.2X\n", data[0]>>5 );
+ data++;
+
+ OUTF("-------- Toolkit Application Reference (TAR): 0x%.2X 0x%.2X 0x%.2X\n", data[0],data[1],data[2]);
+ data+=3;
+ OUTF("-------- Counter (CNTR): 0x%.2X 0x%.2X 0x%.2X 0x%.2X 0x%.2X\n",data[0], data[1], data[2], data[3], data[4]);
+ data+=5;
+
+ // print the remaining bytes of the header, may be redudancy check eg
+ for (i=0; i<chl-12;i++) {
+ OUTF("%s %.2X\n",BitRowFill(data[0], 0xff), data[0]);
+ data++;
+ }
+
+}
+
+
+static void
+TypeOfIdentity()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s Type of Identity: %s\n", BitRowFill(data[0], 0x07), id_list_get(list_TypeOfIdentity, data[0] & 0x07));
+ data++;
+}
+
+static void
+l2_NonCallSS()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s SendSequenceNumber: %u\n", BitRowFill(data[0], 0xc0), data[0] >> 6);
+ if ((data[0] & 0x3f) == 0x3b)
+ {
+ OUTF("--111011 Facility Register\n");
+ data++;
+ l2_FacilityRegister();
+ } else if ((data[0] & 0x3f) == 0x2a) {
+ OUTF("--101010 CCReleaseComplete\n");
+ data++;
+ l2_CCReleaseComplete();
+ } else {
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0x3f));
+ data++;
+ }
+}
+
+static void
+l2_FacilityRegister()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ if (data[0] != 0x1c)
+ {
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff));
+ return;
+ }
+ OUTF("00011100 Information Element: Facility\n");
+ data++;
+ l2_Facility();
+}
+
+static void
+l2_Facility()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ switch (data[0])
+ {
+ case 0xa1: /* 10100001 */
+ OUTF("10100001 Invoke\n");
+ data++;
+ l2_FacilityInvoke();
+ break;
+ case 0xa2: /* 10100010 */
+ OUTF("10100010 ReturnResult\n");
+ data++;
+ l2_FacilityReturnResult();
+ break;
+ default:
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff));
+ break;
+ }
+}
+
+static void
+l2_FacilityHeader()
+{
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ if (data[0] != 0x02)
+ {
+ OUTF("%s Type: UNKNOWN\n", BitRowFill(data[0], 0xff));
+ return;
+ }
+ OUTF("00000010 Type: Integer\n");
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Invoke ID: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+}
+
+static void
+l2_FacilityInvoke()
+{
+ l2_FacilityHeader();
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] != 0x02)
+ {
+ OUTF("%s Type: UNKNOWN\n", BitRowFill(data[0], 0xff));
+ return;
+ }
+ OUTF("00000010 Type: Integer\n");
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+
+ switch (data[0])
+ {
+ case 0x3b:
+ OUTF("00111011 Unstructured SS Request\n");
+ data++;
+ l2_UssRequest();
+ break;
+ case 0x13:
+ OUTF("00010011 Unsturcutred SS Data\n");
+ data++;
+ l2_UssData();
+ break;
+ default:
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff));
+ break;
+ }
+}
+
+static void
+l2_UssRequest()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ if (data[0] != 0x30)
+ {
+ OUTF("%s Sequence: UNKNOWN\n", BitRowFill(data[0], 0xff));
+ return;
+ }
+ OUTF("00110000 Sequence: ussd-Arg\n");
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ if (data[0] != 0x04)
+ {
+ OUTF("%s Octet String: UNKNOWN\n", BitRowFill(data[0], 0xff));
+ return;
+ }
+ OUTF("00000100 Octet String\n");
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+
+ OUTF("%s Coding Sheme Number: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ if (data[0] != 0x04)
+ {
+ OUTF("%s Octet String: UNKNOWN\n", BitRowFill(data[0], 0xff));
+ return;
+ }
+ OUTF("00000100 Octet String\n");
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+}
+
+static void
+l2_UssData()
+{
+ char buf[32];
+ int len;
+
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] != 0x16)
+ {
+ OUTF("%s UNKNWON\n", BitRowFill(data[0], 0xff));
+ return;
+ }
+ if (++data >= end)
+ RETTRUNK();
+ len = data[0];
+ OUTF("%s Length: %d\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ if (data + len > end)
+ RETTRUNK();
+ snprintf(buf, sizeof buf, "%s", data);
+ buf[len] = '\0';
+ OUTF("-------- String: %s\n", buf);
+ data += len;
+}
+
+static void
+l2_CCReleaseComplete()
+{
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] == 0x08)
+ {
+ OUTF("00001000 Cause [FIXME]\n");
+ data++;
+ return;
+ } else if (data[0] == 0x1c) { /* 00011100 */
+ OUTF("00011100 Facility\n");
+ data++;
+ l2_Facility();
+ } else {
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff));
+ data++;
+ return;
+ }
+}
+
+static void
+l2_FacilityReturnResult()
+{
+ l2_FacilityHeader();
+ if (data >= end)
+ RETTRUNK();
+ if (data[0] != 0x30) /* 00110000 */
+ goto err;
+ OUTF("00110000 Sequence: Result Info\n");
+ if (++data >= end)
+ RETTRUNK();
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ if (++data >= end)
+ RETTRUNK();
+ if (data[0] != 2)
+ goto err;
+ OUTF("00000010 Integer\n");
+ if (++data >= end)
+ RETTRUNK();
+ if (data[0] != 1)
+ goto err;
+ OUTF("00000001 Length: 1\n");
+ if (++data >= end)
+ RETTRUNK();
+ switch (data[0])
+ {
+ case 0x13:
+ OUTF("00010011 Unsturcutred SS Data\n");
+ data++;
+ l2_UssData();
+ break;
+ default:
+ goto err;
+ }
+
+ return;
+err:
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff));
+ data++;
+}
+
+static void
+MeasurmentReport()
+{
+ int c, max;
+
+ if (data + 1 >= end)
+ RETTRUNK();
+
+ if ((data[0] >> 7) & 0x1)
+ OUTF("1------- BA used: yes\n");
+ else
+ OUTF("0------- BA used: no\n");
+
+ if ((data[0] >> 6) & 0x1)
+ OUTF("-1------ Discontinous Transmission: yes\n");
+ else
+ OUTF("-0------ Discontinous Transmission: no\n");
+ OUTF("%s RxLev Full Serving Cell: %d dB\n", BitRowFill(data[0], 0x3f), -110 + (data[0] & 0x3f));
+ data++;
+ if ((data[0] >> 7) & 0x1)
+ OUTF("1------- BA used: yes\n");
+ else
+ OUTF("0------- BA used: no\n");
+ if ((data[0] >> 6) & 0x1)
+ OUTF("-1------ MEAS Valid: no\n");
+ else
+ OUTF("-0------ MEAS Valid: yes\n");
+ OUTF("%s RxLev Sub Serving Cell: %d dB\n", BitRowFill(data[0], 0x3f), -110 + (data[0] & 0x3f));
+ data++;
+
+ OUTF("%s Rx Quality Full Serving Cell: %s\n", BitRowFill(data[0], 0x70), id_list_get(list_RxQual, (data[0] >> 3) & 0x07));
+ OUTF("%s Rx Quality Sub Serving Cell: %s\n", BitRowFill(data[0], 0x7), id_list_get(list_RxQual, data[0] & 0x07));
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ max = data[0] & 0x7;
+ OUTF("%s Number of neighbouring cell measurements: %d\n", BitRowFill(data[0], 0x7), data[0] & 0x7);
+ c = 1;
+ data++;
+ while (c <= max)
+ {
+ if (data + 2 >= end)
+ RETTRUNK();
+ OUTF("%s RxLev Neighbour Cell %d: %d dB\n", BitRowFill(data[0], 0x3f), c, -100 + (data[0] & 0x3f));
+ data++;
+ OUTF("%s Bcch Freq MCell %d: %d\n", BitRowFill(data[0], 0x1f), c, data[0] & 0x1f);
+ data++;
+ OUTF("%s BTS Identity Code: %d\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f);
+ data++;
+ c++;
+ }
+ /* FIXME: I think something iswrong here */
+ OUTF("FIXME\n");
+}
+
+static void
+BCDNumber()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+ OUTF("%s Type of number: %s\n", BitRowFill(data[0], 0x70), id_list_get(list_TypeNumber, data[0] & 0x70));
+ //OUTF("%s Number plan: %s\n", BitRowFill(data[0], 0xf), id_list_get(list_data[0] & 0xf);
+}
+
personal git repositories of Harald Welte. Your mileage may vary