summaryrefslogtreecommitdiff
path: root/gsmdecode
diff options
context:
space:
mode:
Diffstat (limited to 'gsmdecode')
-rw-r--r--gsmdecode/INSTALL11
-rw-r--r--gsmdecode/Makefile.am6
-rwxr-xr-xgsmdecode/bootstrap45
-rw-r--r--gsmdecode/configure.in84
-rw-r--r--gsmdecode/src/Makefile.am3
-rw-r--r--gsmdecode/src/common.c86
-rw-r--r--gsmdecode/src/common.h50
-rw-r--r--gsmdecode/src/data_out.c3867
-rw-r--r--gsmdecode/src/data_out.h5
-rw-r--r--gsmdecode/src/gsm_desc.h262
-rw-r--r--gsmdecode/src/gsmdecode.c289
-rw-r--r--gsmdecode/src/id_list.c19
-rw-r--r--gsmdecode/src/id_list.h15
-rw-r--r--gsmdecode/src/mcc_list.c1433
-rw-r--r--gsmdecode/src/mcc_list.h5
15 files changed, 6180 insertions, 0 deletions
diff --git a/gsmdecode/INSTALL b/gsmdecode/INSTALL
new file mode 100644
index 0000000..9a8b266
--- /dev/null
+++ b/gsmdecode/INSTALL
@@ -0,0 +1,11 @@
+
+ The GSM Scanner Project
+ 2007/04/27, http://www.thc.org/gsm
+
+GSMDECODE decodes layer1/layer2 messages. It either takes raw hex input
+or xml input generated by gammu & nokia dct3 debug trace mobile.
+
+$ ./configure
+$ make all
+$ src/gsmdecode -x <example_sms2.xml
+
diff --git a/gsmdecode/Makefile.am b/gsmdecode/Makefile.am
new file mode 100644
index 0000000..69fd6b1
--- /dev/null
+++ b/gsmdecode/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = src
+EXTRA_DIST = config VERSION bootstrap INSTALL example_sms2.xml
+
+test:
+ @echo "foobar"
+
diff --git a/gsmdecode/bootstrap b/gsmdecode/bootstrap
new file mode 100755
index 0000000..f32d6de
--- /dev/null
+++ b/gsmdecode/bootstrap
@@ -0,0 +1,45 @@
+#! /bin/bash
+
+DIE=0
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed."
+ DIE=1
+}
+
+# libtool --version check not done...
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have automake installed."
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+echo Removing old files...
+rm -f configure Makefile Makefile.in src/Makefile src/Makefile.in config.h config.status aclocal.m4 config.cache config.log
+
+mkdir config
+echo "aclocal -I config"
+aclocal -I config
+if test $? -ne 0; then
+ exit 1
+fi
+echo "autoheader"
+autoheader
+if test $? -ne 0; then
+ exit 1
+fi
+echo "automake --foreign --add-missing"
+automake --foreign --add-missing
+if test $? -ne 0; then
+ exit 1
+fi
+echo "autoconf"
+autoconf
+echo "BOOTSTRAP complete"
+
diff --git a/gsmdecode/configure.in b/gsmdecode/configure.in
new file mode 100644
index 0000000..1bce538
--- /dev/null
+++ b/gsmdecode/configure.in
@@ -0,0 +1,84 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(src/gsmdecode.c)
+VER=`cat ${srcdir}/VERSION`
+AC_MSG_RESULT(Begining autoconfiguration process for gsmdecode-$VER...)
+
+AC_CONFIG_AUX_DIR(config)
+AC_CANONICAL_SYSTEM
+
+dnl we use automake
+AM_INIT_AUTOMAKE(gsmdecode, $VER)
+AM_CONFIG_HEADER(config.h)
+dnl for --enable-maintainer-mode fun use:
+dnl AM_MAINTAINER_MODE
+dnl we use automake anyway...no need for AC_CONFIG_HEADER
+dnl AC_CONFIG_HEADER(config.h)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+AC_C_CONST
+dnl
+dnl Use these compiler flags if we have gcc.
+dnl
+if test $ac_cv_prog_gcc = yes; then
+ CCOPTS='-O2 -Wall'
+ CFLAGS="$CCOPTS"
+fi
+test "x$prefix" != "xNONE" || prefix="/usr/local"
+test "x$exec_prefix" != "xNONE" || exec_prefix="${prefix}"
+dnl AC_CHECK_LIB(nsl, gethostbyname)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(sys/time.h unistd.h string.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_PID_T
+AC_HEADER_TIME
+
+dnl Checks for library functions.
+AC_FUNC_MEMCMP
+
+AC_TYPE_SIGNAL
+dnl If size_t is not defined, define size_t to be unsigned.
+AC_TYPE_SIZE_T
+dnl If uid_t is not defined, define uid_t to be int and gid_t to be int.
+AC_TYPE_UID_T
+
+dnl check if we are on a bigendian b0x
+dnl We dont check for this because autoconf maintainers are pussies and
+dnl yell a warning everytime. Guys, introduce AC_C_BIGENDIAN_CROSS for
+dnl gods sake!
+dnl AC_C_BIGENDIAN
+
+AC_CHECK_FUNCS(gettimeofday memcpy strchr)
+dnl FIXME: repair this later
+dnl SNPRINTF=''
+dnl AC_CHECK_FUNC(snprintf, AC_DEFINE(HAVE_SNPRINTF), SNPRINTF='snprintf.o')
+dnl AC_SUBST(SNPRINTF)
+
+AC_ARG_ENABLE(debug,
+[ --enable-debug Enable debug information],
+ AC_DEFINE(GSMSP_DEBUG, 1, [Debug infos])
+)
+
+B=`eval echo ${bindir}` ; B=`eval echo ${B}`
+D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}`
+AC_OUTPUT(Makefile src/Makefile)
+
+dnl Just to show the correct values...
+
+echo "gsmdecode has been configured with the following options:"
+echo " User binaries: $B"
+echo ""
+echo " Host: ${host}"
+echo " Compiler: ${CC}"
+echo " Compiler flags: ${CFLAGS}"
+echo "Preprocessor flags: ${CPPFLAGS}"
+echo " Linker flags: ${LDFLAGS}"
+echo " Libraries: ${LIBS}"
+echo "Configuration complete. Now type: make; src/gsmdecode -x <example_sms2.xml"
diff --git a/gsmdecode/src/Makefile.am b/gsmdecode/src/Makefile.am
new file mode 100644
index 0000000..ec2b21d
--- /dev/null
+++ b/gsmdecode/src/Makefile.am
@@ -0,0 +1,3 @@
+bin_PROGRAMS = gsmdecode
+gsmdecode_SOURCES = data_out.c gsmdecode.c id_list.c common.c mcc_list.c
+noinst_HEADERS = data_out.h gsm_desc.h id_list.h common.h mcc_list.h
diff --git a/gsmdecode/src/common.c b/gsmdecode/src/common.c
new file mode 100644
index 0000000..decea53
--- /dev/null
+++ b/gsmdecode/src/common.c
@@ -0,0 +1,86 @@
+/*
+ */
+
+#include "common.h"
+#include <stdio.h>
+#include <string.h>
+
+void
+hexdump(const unsigned char *data, size_t len)
+{
+ size_t n = 0;
+ int line = 0;
+
+ if (!len)
+ return;
+
+ printf("%03x: ", line++);
+ while (1)
+ {
+ printf("%2.2x ", data[n++]);
+ if (n >= len)
+ break;
+ if ((n % 8 == 0) && (n % 16 != 0))
+ printf(" - ");
+ if (n % 16 == 0)
+ printf("\n%03x: ", line++);
+ }
+ printf("\n");
+}
+
+#ifndef HAVE_STRLCPY
+/*
+ * bsd'sh strlcpy().
+ * The strlcpy() function copies up to size-1 characters from the
+ * NUL-terminated string src to dst, NUL-terminating the result.
+ * Return: total length of the string tried to create.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t size)
+{
+ size_t len = strlen(src);
+ size_t ret = len;
+
+ if (size <= 0)
+ return 0;
+ if (len >= size)
+ len = size - 1;
+ memcpy(dst, src, len);
+ dst[len] = 0;
+
+ return ret;
+}
+#endif
+
+/*
+ * Debuggging...
+ * Convert an interger to a bit string and output it.
+ * Most significatn bit first.
+ */
+char *
+int2bit(unsigned int val)
+{
+ static char buf[33 + 3];
+ char *ptr = buf;
+ unsigned int i = 0x1 << 31;
+ int round = 0;
+
+ while (i > 0)
+ {
+
+ if (val & i)
+ *ptr++ = '1';
+ else
+ *ptr++ = '0';
+
+ i = i >> 1;
+
+ if ((++round % 8 == 0) && (i > 0))
+ *ptr++ = '.';
+ }
+
+ *ptr = '\0';
+
+ return buf;
+}
+
diff --git a/gsmdecode/src/common.h b/gsmdecode/src/common.h
new file mode 100644
index 0000000..61abc5f
--- /dev/null
+++ b/gsmdecode/src/common.h
@@ -0,0 +1,50 @@
+#ifndef __GSMSP_COMMON_H__
+#define __GSMSP_COMMON_H__ 1
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+/* DISABLE me for release build. Otherwise with debug output. */
+//#define GSMSP_DEBUG 1
+
+#ifdef GSMSP_DEBUG
+# define DEBUGF(a...) do { \
+ fprintf(stderr, "DEBUG %s:%d ", __func__, __LINE__); \
+ fprintf(stderr, a); \
+} while (0)
+#else
+# define DEBUGF(a...)
+#endif
+
+/* True if bit at position 'pos' in 'data' is set */
+#define BIT(data, pos) ((data) >> (pos)) & 1
+
+# define HEXDUMPF(data, len, a...) do { \
+ printf("HEX %s:%d ", __func__, __LINE__); \
+ printf(a); \
+ hexdump(data, len); \
+} while (0)
+
+void hexdump(const unsigned char *data, size_t len);
+
+struct _opt
+{
+ char format;
+ char flags;
+};
+
+#define MSG_FORMAT_BBIS (1)
+#define MSG_FORMAT_B (2)
+#define MSG_FORMAT_XML (3)
+
+#define FL_MOTOROLA (0x01)
+
+#endif /* !__GSMSP_COMMON_H__ */
+
+
diff --git a/gsmdecode/src/data_out.c b/gsmdecode/src/data_out.c
new file mode 100644
index 0000000..1f69d2e
--- /dev/null
+++ b/gsmdecode/src/data_out.c
@@ -0,0 +1,3867 @@
+/*
+ * 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"
+#include "mcc_list.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;
+
+/* Prototype helper functions */
+static unsigned int Bit_extract_val(unsigned char *data, int bit_pos, int numbits);
+
+
+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_RRsystemInfo2bis();
+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 int l2_MNCC(int mcc, unsigned char a, unsigned char b, unsigned char c);
+
+static void maio();
+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 Number(int len);
+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 int CellAllocation(unsigned char format, char *str);
+static void ChannelMode();
+
+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;
+ int direction; /* 0 == downlink, 1 == uplink */
+};
+#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;
+ int logicalchannel;
+};
+/* Is initialized to 0 (do not remove from .bss) */
+static struct _sms_con sms_con;
+
+struct _con con[8];
+struct _con conuplink[8];
+struct _con *conptr;
+
+
+
+/*
+ * B-format (and also A-Format)
+ */
+void
+l2_data_out_B(int fn, const unsigned char *input_data, int len, int logicalchannel, int direction)
+{
+ const unsigned char *from;
+ int val;
+
+ data = input_data;
+ start = data;
+ end = data + len;
+
+ HEXDUMPF(data, 23 /*len*/, "Format B DATA (%s)\n", direction?"up":"down");
+
+ /* Do not analyze dummy octets */
+ if (memcmp(data + 3, "\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b\x2b", 20) == 0)
+ return;
+
+ //printf("Logical channel: %d\n", logicalchannel);
+
+ /* Need at least 3 octets */
+ if (data + 2 >= end)
+ RETTRUNK();
+
+ memset(&nfo, 0, sizeof nfo);
+ nfo.direction = direction;
+ 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');
+
+ /* 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;
+
+ if ((data[0] >> 1) & 1)
+ {
+ /* Segmentation: y */
+ if ((logicalchannel != conptr->logicalchannel) && (conptr->ptr > conptr->buf))
+ {
+ /* Currently we only support 1 segmented stream
+ * at the same time per direction.
+ * If downlink sends two segments on two different
+ * logical channels then we can not handle this..
+ */
+ OUTF("WARN: Two segmented streams at the same time..\n");
+ /* Reset */
+ conptr->ptr = conptr->buf;
+ }
+ nfo.flags |= GSMSP_NFO_SEGMENTATION;
+ conptr->logicalchannel = logicalchannel;
+ }
+
+ val = data[0] >> 2;
+ OUTF("%s Length: %u\n", BitRowFill(data[0], 0xfc), val);
+ if (data + val < end)
+ {
+ end = data + val + 1;
+ }
+
+ data++;
+ if (data >= end)
+ return;
+
+ /* 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 ((logicalchannel == conptr->logicalchannel) && ((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 (conptr->ptr > conptr->buf)
+ {
+ if (nfo.flags & GSMSP_NFO_SEGMENTATION)
+ {
+ OUTF("-------- [SEGMENTED MESSAGE. MORE DATA FOLLOWS...]\n");
+ /* More fragments follow. No need to decode yet */
+ return;
+ } else if (logicalchannel == conptr->logicalchannel)
+ OUTF("-------- [SEGMENTED MESSAGE. LAST...]\n");
+ }
+
+ /* Here: segmentation == No */
+ /* See if we get an SMS message and if this was the last fragment */
+ /* Currently only 1 logical channel can contain segmented data.
+ * If there are two channels that both send segmented data
+ * then it's gettin muddled up.
+ */
+ if ((logicalchannel == conptr->logicalchannel) && (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;
+ if (nfo.direction == 1)
+ {
+ conptr = &conuplink[nfo.sapi];
+ } else {
+ 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);
+ }
+ if (data < end)
+ OUTF("XXXXXXXX UNKNOWN DATA (%d bytes)\n", end - data);
+ if (data > end)
+ {
+ OUTF("INTERNAL ERROR. Processed to many data\n");
+ return;
+ }
+
+ while (1)
+ {
+ if (end >= start + 23)
+ break;
+ if (*end == 0x2b)
+ break;
+ end++;
+ }
+ if (end > data)
+ {
+ OUTF("YYYYYYYY REST OCTETS (%d)\n", end - data);
+ }
+}
+
+/*
+ * Extract up to 24 bit from a data field and return as integer.
+ */
+static unsigned int
+Bit_extract_val(unsigned char *data, int bit_pos, int numbits)
+{
+ unsigned int ofs;
+ unsigned int val = 0;
+ unsigned int bit_ofs;
+ char len;
+ char overlap;
+ int i;
+
+ ofs = bit_pos / 8;
+ bit_ofs = bit_pos % 8;
+
+ len = ((7 - bit_ofs) + numbits + 7) / 8;
+ //OUTF("len = %u\n", len);
+
+ i = 0;
+ while (i < len)
+ {
+ val = val << 8;
+ val = val | data[i + ofs];
+ i++;
+ }
+ overlap = (numbits + (7 - bit_ofs)) % 8;
+ //OUTF("overlap = %u bit\n", overlap);
+ if (overlap != 0)
+ {
+ val = val >> (8 - overlap);
+ }
+ val = val & (((unsigned int)1 << numbits) - 1);
+
+ return val;
+}
+
+/*
+ * 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 0x02:
+ OUTF("00000010 System Information Type 2bis\n");
+ data++;
+ l2_RRsystemInfo2bis();
+ break;
+ case 0x03:
+ OUTF("00000011 System Information Type 2ter\n");
+ data++;
+ l2_RRsystemInfo2ter();
+ break;
+ case 0x05:
+ OUTF("00000101 System Information Type 5bis\n");
+ data++;
+ l2_BcchAllocation();
+ 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 assign 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()
+{
+ OUTF("%s Training seq. code : %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
+
+ maio();
+ RequestReference();
+ TimingAdvance();
+ l2_MobileAllocation();
+ if (data >= end)
+ return; /* finished. not truncated! */
+
+ OUTF("FIXME, more data left here???\n");
+}
+
+static void
+maio()
+{
+ unsigned char maio = 0;
+
+ OUTF("---1---- HoppingChannel\n");
+ maio = (data[0] & 0x0f) << 2;
+ data++;
+ if (data >= end)
+ RETTRUNK();
+ maio |= (data[0] >> 6);
+ OUTF("........ Mobile Allocation Index Offset (MAIO) %d\n", maio);
+ OUTF("%s Hopping Seq. Number: %d\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f);
+
+ data++;
+}
+
+static void
+l2_HoppingChannelC()
+{
+ OUTF("FIXME-2\n");
+}
+
+static void
+l2_MobileAllocation()
+{
+ int pos;
+ const unsigned char *thisend;
+ int len;
+
+ if (data >= end)
+ RETTRUNK();
+ OUTF("%s Length of Mobile Allocation: %d\n", BitRowFill(data[0], 0xff), data[0]);
+
+ len = data[0];
+
+ thisend = data + len + 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;
+
+ /* This is the index into the list of arfcn's */
+ pos = 7;
+ while (data < thisend)
+ {
+ while (pos >= 0)
+ {
+ if ((data[0] >> pos) & 1)
+ {
+ OUTF("%s Mobile Allocation ARFCN #%d\n", BitRow(data[0], pos), 8 * len - (7 - pos));
+
+ }
+ pos--;
+ }
+ pos = 7;
+ len--;
+ data++;
+ }
+}
+
+/*
+ * From RRsystemInfo2
+ */
+static void
+l2_BcchAllocation()
+{
+ OUTF("---x---- BCCH alloc. seq. num: %d\n", (data[0] >> 4) & 1);
+ CellAllocation(data[0], "BCCH Allocation : ARFCN");
+}
+
+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)
+ return;
+ /* FIXME: rest octets?? */
+ OUTF("FIXME: implenet\n");
+}
+
+static void
+CellAllocationBitmapZero(char *str)
+{
+ int ca;
+
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- %s 124\n", str);
+ if ((data[0] >> 2) & 1)
+ OUTF("-----1-- %s 123\n", str);
+ if ((data[0] >> 1) & 1)
+ OUTF("------1- %s 122\n", str);
+ if (data[0] & 1)
+ OUTF("-------1 %s 121\n", str);
+
+ ca = 120;
+ while (ca > 0)
+ {
+ data++;
+ if (data >= end)
+ return;
+ if ((data[0] >> 7) & 1)
+ OUTF("1------- %s %d\n", str, ca);
+ if ((data[0] >> 6) & 1)
+ OUTF("-1------ %s %d\n", str, ca - 1);
+ if ((data[0] >> 5) & 1)
+ OUTF("--1----- %s %d\n", str, ca - 2);
+ if ((data[0] >> 4) & 1)
+ OUTF("---1---- %s %d\n", str, ca - 3);
+ if ((data[0] >> 3) & 1)
+ OUTF("----1--- %s %d\n", str, ca - 4);
+ if ((data[0] >> 2) & 1)
+ OUTF("-----1-- %s %d\n", str, ca - 5);
+ if ((data[0] >> 1) & 1)
+ OUTF("------1- %s %d\n", str, ca - 6);
+ if (data[0] & 1)
+ OUTF("-------1 %s %d\n", str, ca - 7);
+
+ ca -= 8;
+ }
+ data++;
+}
+
+/*
+ * Return number of bits required to store val.
+ */
+static int
+num_bits(unsigned int val)
+{
+ int i = 32;
+
+ while (1)
+ {
+ i--;
+ if (i <= 0)
+ break;
+ if ((((unsigned int)1) << i) <= val)
+ break;
+ }
+
+ return i + 1;
+}
+
+static int
+Bitmap256_extract_frequency(unsigned short *w, int index)
+{
+ int j;
+ int n = w[index];
+
+ j = 1 << (num_bits(index) - 1);
+ //OUTF("j = %d\n", j);
+ while (index > 1)
+ {
+ if (2 * index < 3 * j)
+ {
+ index = index - j / 2;
+ n = (n + w[index] - 256 / j - 1) % (512 / j - 1) + 1;
+ } else {
+ index = index - j;
+ n = (n + w[index] - 1) % (512 / j - 1) + 1;
+ }
+ j = j / 2;
+ }
+ //OUTF("freq %d\n", (w[0] + n) % 1024);
+
+ return (w[0] + n) % 1024;
+}
+
+
+static void
+CellAllocationBitmap256(char *str)
+{
+ int arfcn = 0;
+ int i;
+ unsigned short w[30];
+ int pos, len, border;
+ int ii;
+
+ memset(w, 0, sizeof w);
+
+ arfcn = (data[0] & 1) << 9;
+ data++;
+ arfcn |= (data[0] << 1);
+ data++;
+ arfcn |= (data[0] >> 7);
+ w[0] = arfcn;
+
+#if 0
+ w[0] = 0xff;
+ w[1] = 0x00;
+ w[2] = 0xff;
+ w[3] = 0x00;
+ OUTF("XXX 6,8 254 %u\n", Bit_extract_val(w, 6, 8));
+ OUTF("XXX 7,7 127 %u\n", Bit_extract_val(w, 7, 7));
+ OUTF("XXX 7,8 255 %u\n", Bit_extract_val(w, 7, 8));
+ OUTF("XXX 6,7 127 %u\n", Bit_extract_val(w, 6, 7));
+ OUTF("XXX 0,8 128 %u\n", Bit_extract_val(w, 0, 8));
+ OUTF("XXX 7,16 65280 %u\n", Bit_extract_val(w, 7, 16));
+ OUTF("XXX 7,1 1 %u\n", Bit_extract_val(w, 7, 1));
+ OUTF("XXX 8,1 0 %u\n", Bit_extract_val(w, 8, 1));
+#endif
+
+ pos = 6;
+ len = 8;
+ border = 2;
+ for (i = 1; i <= 29; i++)
+ {
+ if (i == border)
+ {
+ border = border * 2;
+ len--;
+ if (len <= 0)
+ {
+ i--;
+ break;
+ }
+ }
+ w[i] = Bit_extract_val((unsigned char *)data, pos, len);
+ if (w[i] == 0)
+ break;
+ pos += len;
+ }
+ //OUTF("%d entries\n", i);
+
+ OUTF("xxxxxxxx %s %d (original)\n", str, w[0]);
+ for (ii = 1; ii <= i; ii++)
+ {
+ OUTF("xxxxxxxx %s %d\n", str, Bitmap256_extract_frequency(w, ii));
+ }
+ data += (pos + 7) / 8;
+
+}
+
+static void
+CellAllocationBitmapVariable(char *str)
+{
+ int arfcn = 0;
+ int i;
+ const unsigned char *thisend;
+
+ arfcn = (data[0] & 1) << 9;
+ data++;
+ arfcn |= (data[0] << 1);
+ data++;
+ arfcn |= (data[0] >> 7);
+
+ OUTF("........ %s %d (original)\n", str, arfcn);
+
+ for (i = 1; i < 8; i++)
+ {
+ if (BIT(data[0], 7-i))
+ OUTF("%s %s %d\n", BitRow(data[0], 7-i), str, (arfcn + i) % 1024);
+ }
+ data++;
+
+ thisend = data + 13;
+ while (data < thisend)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ if (BIT(data[0], 7 - i))
+ OUTF("%s %s %d\n", BitRow(data[0], 7-i), str, (arfcn + (104 + i)) % 1024);
+ }
+ data++;
+ }
+}
+
+/*
+ * Return 0 on success (e.g. caller continues processing).
+ * Cell Channel Description (for example SystemInformationType 1)
+ */
+static int
+CellAllocation(unsigned char format, char *str)
+{
+ const unsigned char *orig_data = data;
+
+ if ((format >> 6) == 0x00)
+ {
+ OUTF("00------ Bitmap 0 format\n");
+ CellAllocationBitmapZero(str);
+ data = orig_data + 16;
+ return 0;
+ }
+ if (((format >> 3) & 1) == 0x00)
+ {
+ OUTF("-------- Bitmap format: 1024 Range (FIXME)\n");
+ data = orig_data + 16;
+ return -1;
+ }
+
+ switch ((format >> 1) & 0x07)
+ {
+ case 0x04:
+ OUTF("10--100- Bitmap format: 512 Range (FIXME)\n");
+ data = orig_data + 16;
+ return -1;
+ case 0x05:
+ OUTF("10--101- Bitmap format: 256 Range\n");
+ CellAllocationBitmap256(str);
+ data = orig_data + 16;
+ return 0;
+ case 0x06:
+ OUTF("10--110- Bitmap format: 128 Range (FIXME)\n");
+ data = orig_data + 16;
+ return -1;
+ case 0x07:
+ OUTF("10--111- Bitmap format: Variable Range\n");
+ CellAllocationBitmapVariable(str);
+ data = orig_data + 16;
+ return 0;
+ }
+
+ return -1;
+}
+
+static void
+l2_RRsystemInfo1()
+{
+
+ if (data + 1 >= end)
+ return;
+
+ if (CellAllocation(data[0], "Cell Allocation : ARFCN") != 0)
+ return;
+
+ 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;
+}
+
+/*
+ * GSM 04.08-9.1.32
+ */
+static void
+l2_RRsystemInfo2()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ /* Neighbour Cell Description. 16 octets */
+ 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();
+}
+
+static void
+l2_RRsystemInfo2bis()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ /* Extended BCCH Frequency List. 16 octets */
+ /* Neighbour Cell Description. 10.5.2.22 */
+ l2_BcchAllocation();
+
+ /* 3 octets */
+ l2_RachControlParameters();
+}
+
+static void
+l2_RRsystemInfo2ter()
+{
+ if (data >= end)
+ RETTRUNK();
+
+ /* Neighbour Cell Description 2 */
+ l2_BcchAllocation();
+}
+
+
+/*
+ * 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()
+{
+ int mcc;
+
+ if (data + 2 >= end)
+ return;
+ unsigned short lac;
+
+ mcc = l2_MNCC(0, data[0] & 0x0f, (data[0] >> 4) & 0x0f, data[1] & 0x0f);
+ data++;
+ l2_MNCC(mcc, 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]);
+ data++;
+}
+
+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++;
+}
+
+/*
+ * If mcc is 0 then output MCC and return MCC as value.
+ * Otherwise output MNC.
+ */
+static int
+l2_MNCC(int mcc, unsigned char a, unsigned char b, unsigned char c)
+{
+ char buf[128];
+ char f[12];
+ const char *country;
+ const char *mnc;
+
+ snprintf(f, sizeof f, "%x%x%x", a, b, c);
+ /* Nokia netmonitor shows NC's like '30F' and '10F' */
+ if (mcc == 0)
+ {
+ /* Find out MCC */
+ mcc = atoi(f);
+ country = mcc_get(mcc);
+ if (country == NULL)
+ country = "UNKNOWN";
+ snprintf(buf, sizeof buf, "%-8s %s (%s)\n", f, "Mobile Country Code", country);
+ } else {
+ mnc = mnc_get(mcc, atoi(f));
+ snprintf(buf, sizeof buf, "%-8s %s (%s)\n", f, "Mobile Network Code", mnc);
+ }
+
+#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);
+
+ return mcc;
+}
+
+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 Mobile Allocation Index Offset (MAIO): %u\n", maio);
+ OUTF("%s Hopping Sequence Number: %u\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f);
+ data++;
+
+ RequestReference();
+
+ TimingAdvance();
+ l2_MobileAllocation();
+
+ if (data >= end)
+ return;
+ 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");
+ cpData();
+ } else
+ OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff));
+ data++;
+}
+
+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++;
+ Number(len);
+}
+
+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();
+}
+
+/*
+ * 04.08-9.1.2
+ */
+static void
+l2_RRassignCommand()
+{
+ ChannelDescriptionTwo();
+ if (data >= end)
+ RETTRUNK();
+
+ OUTF("%s Training seq. code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
+
+ /* Power Command 10.5.2.28 */
+ /* Frequency List 10.5.2.13 */
+ /* Cell Channel Description 10.5.2.1b */
+ /* Multislot allocation... */
+ 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
+PowerLevel()
+{
+ OUTF("%s Power Level: %u\n", BitRowFill(data[0], 0x1f), data[0] & 0x1f);
+ 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();
+ PowerLevel();
+ if (data[0] != 0x63)
+ return;
+ if (++data >= end)
+ RETTRUNK();
+ ChannelMode();
+}
+
+static void
+FrequencyList()
+{
+ /* Should be 16 */
+ OUTF("%s Length: %d\n", BitRowFill(data[0], 0xff), data[0]);
+ data++;
+ CellAllocation(data[0], "Cell Allocation : ARFCN");
+}
+
+static void
+ChannelMode()
+{
+ OUTF("%s\n", id_list_get(list_ChannelMode, data[0]));
+ data++;
+}
+
+static void
+l2_HoppingChannelAssCom()
+{
+ maio();
+ PowerLevel();
+ while (data < end)
+ {
+ if (data[0] == 0x05)
+ {
+ data++;
+ FrequencyList();
+ } else if (data[0] == 0x63) {
+ data++;
+ ChannelMode();
+ } else {
+ OUTF("UNKNOWN. FIXME\n");
+ break;
+ }
+
+ }
+}
+
+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 if (data[0] == 0xa1) {
+ OUTF("10100001 CLIR supression\n");
+ data++;
+ } else if (data[0] == 0xa2) {
+ OUTF("10100010 CLIR invocation\n");
+ data++;
+ } 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);
+ data++;
+}
+
+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
+Number(int len)
+{
+ 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
+BCDNumber()
+{
+ int len;
+
+ if (data >= end)
+ RETTRUNK();
+
+ len = data[0];
+ 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) >> 4));
+ data++;
+ len--;
+ Number(len * 2);
+}
+
diff --git a/gsmdecode/src/data_out.h b/gsmdecode/src/data_out.h
new file mode 100644
index 0000000..6d3f740
--- /dev/null
+++ b/gsmdecode/src/data_out.h
@@ -0,0 +1,5 @@
+
+
+void l2_data_out_Bbis(int fn, const unsigned char *data, int len);
+void l2_data_out_B(int fn, const unsigned char *data, int len, int logicalchannel, int direction);
+
diff --git a/gsmdecode/src/gsm_desc.h b/gsmdecode/src/gsm_desc.h
new file mode 100644
index 0000000..ccaac17
--- /dev/null
+++ b/gsmdecode/src/gsm_desc.h
@@ -0,0 +1,262 @@
+
+
+struct _id_list list_ChannelRelease[] = {
+{0, "00000000 RR-Cause (reason of event) = Normal event"},
+{1, "00000001 RR-Cause (reason of event) = Abnormal release, unspecified"},
+{2, "00000010 RR-Cause (reason of event) = Abnormal release, channel unacceptable"},
+{3, "00000011 RR-Cause (reason of event) = Abnormal release, timer expired"},
+{4, "00000100 RR-Cause (reason of event) = Abnormal release, no activity on the radio path"},
+{5, "00000101 RR-Cause (reason of event) = Preemptive release"},
+{8, "00001000 RR-Cause (reason of event) = Handover impossible, timing advance out of range"},
+{9, "00001001 RR-Cause (reason of event) = Channel mode unacceptable"},
+{10, "00001010 RR-Cause (reason of event) = Frequency not implemented"},
+{0x81, "01000001 RR-Cause (reason of event) = Call already cleared"},
+{0x5f, "01011111 RR-Cause (reason of event) = Semantically incorrect message"},
+{0x60, "01100000 RR-Cause (reason of event) = Invalid mandatory information"},
+{0x61, "01100001 RR-Cause (reason of event) = Message type non-existent or not implemented"},
+{0x62, "01100010 RR-Cause (reason of event) = Message type not compatible with protocol state"},
+{0x64, "01100100 RR-Cause (reason of event) = Conditional IE error"},
+{0x65, "01100101 RR-Cause (reason of event) = Nocell allocation available"},
+{0x6f, "01101111 RR-Cause (reason of event) = Protocol error unspecified"},
+{-1, NULL}
+};
+
+struct _id_list list_RequestServiceType[] = {
+{1, "----0001 Request Service Type: MS originated call"},
+{2, "----0010 Request Service Type: Emergency call"},
+{4, "----0100 Request Service Type: SMS"},
+{8, "----1000 Request Service Type: Supplementary Service Activation"},
+{9, "----1001 Request Service Type: Voice Group call"},
+{10, "----1010 Request Service Type: Voice Broadcast call"},
+{11, "----1011 Request Service Type: Location Services"},
+{-1, NULL}
+};
+
+struct _id_list list_SMSCAddressType[] = {
+{0, "-000---- Unknown Number Type"},
+{1, "-001---- International Number"},
+{2, "-010---- National Number"},
+{3, "-011---- Network specific number"},
+{4, "-100---- Subscriber number"},
+{5, "-101---- Alphanumeric number"},
+{6, "-110---- Abbreviated number"},
+{-1, NULL}
+};
+
+struct _id_list list_SMSCAddressNumberingPlan[] = {
+{0, "----0000 Numbering plan: Unknown"},
+{1, "----0001 Numbering plan: ISDN/telephone (E164/E.163)"},
+{3, "----0011 Numbering plan: Data(X.121)"},
+{4, "----0100 Numbering plan: Telex"},
+{8, "----1000 Numbering plan: National"},
+{9, "----1001 Numbering plan: Private"},
+{10, "----1010 Numbering plan: ERMES (ESTI DE/PS3 01-3)"},
+{15, "----1111 Numbering plan: Unknown"},
+{-1, NULL}
+};
+
+struct _id_list list_ChannelDescriptionTwo[] = {
+{0x01, "TCH/F + ACCHs"},
+{0x02, "TCH/H + ACCHs, subchannel 0"},
+{0x03, "TCH/H + ACCHs, subchannel 1"},
+{0x04, "SDCCH/4 + SACCH/C4 or CBCH (SDCCH/4), SC0"},
+{0x05, "SDCCH/4 + SACCH/C4 or CBCH (SDCCH/4), SC1"},
+{0x06, "SDCCH/4 + SACCH/C4 or CBCH (SDCCH/4), SC2"},
+{0x07, "SDCCH/4 + SACCH/C4 or CBCH (SDCCH/4), SC3"},
+{0x08, "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), SC0"},
+{0x09, "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), SC1"},
+{0x0a, "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), SC2"},
+{0x0b, "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), SC3"},
+{0x0c, "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), SC4"},
+{0x0d, "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), SC5"},
+{0x0e, "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), SC6"},
+{0x0f, "SDCCH/8 + SACCH/C8 or CBCH (SDCCH/8), SC7"},
+{-1, NULL}
+};
+
+struct _id_list list_ChannelMode[] = {
+{0x00, "00000000 Channel Mode: signaling only"},
+{0x01, "00000001 Channel Mode: TCH/F or TCH/H rev 1"},
+{0x21, "00100001 Channel Mode: TCH/F or TCH/H rev 2"},
+{0x41, "01000001 Channel Mode: TCH/F or TCH/H rev 3"},
+{0x0f, "00001111 Channel Mode: Data, 14.5 kbit/s"},
+{0x03, "00000011 Channel Mode: Data, 12.0 kbit/s"},
+{0x0b, "00001011 Channel Mode: Data, 6.0 kbit/s"},
+{0x13, "00010011 Channel Mode: Data, 3.6 kbit/s"},
+{-1, NULL}
+};
+
+struct _id_list list_CodingStandard[] = {
+{0x00, "CCITT"},
+{0x01, "Reserved for international standards"},
+{0x02, "National standard"},
+{0x03, "GSM-PLMNS"},
+{-1, NULL}
+};
+
+
+struct _id_list list_Location[] = {
+{0x00, "User"},
+{0x01, "Private network serving local user"},
+{0x02, "Public network serving local user"},
+{0x04, "Public network serving remote user"},
+{0x05, "Private network serving remote user"},
+{0x0a, "Network beyong interworking point"},
+{-1, NULL}
+};
+
+struct _id_list list_Progress[] = {
+{0x01, "-0000001 Progress: Call is not end-to-end PLMN/ISDN"},
+{0x02, "-0000010 Progress: Destination address in non-PLMN/ISDN"},
+{0x03, "-0000011 Progress: Origination address in non-PLMN/ISDN"},
+{0x04, "-0000100 Progress: Call has returned to the PLMN/ISDN"},
+{0x08, "-0001000 Progress: In-band information or appr. pattern available"},
+{0x20, "-0100000 Progress: Call is end-to-end PLMN/ISDN"},
+{0x40, "-1000000 Progress: Queueing"},
+{-1, NULL}
+};
+
+struct _id_list list_Cause[] = {
+{0x01, "Unassigned number"},
+{0x03, "No route to destination"},
+{0x06, "Channel unacceptable"},
+{0x08, "Operator determined barring"},
+{0x10, "Normal call clearing"},
+{0x11, "User busy"},
+{0x12, "No user responding"},
+{0x13, "User alerting, no answer"},
+{0x15, "Call rejected"},
+{0x16, "Number changed, New destination"},
+{0x19, "Pre-emption"},
+{0x1a, "Non selected user clearing"},
+{0x1b, "Destination out of order"},
+{0x1c, "Invalid number format (incomplete number)"},
+{0x1d, "Fascility rejected"},
+{0x1e, "Response to Status Enquiry"},
+{0x1f, "Normal"},
+{0x22, "No channel available"},
+{0x26, "Network out of order"},
+/* FIXME: fill in others.. */
+{-1, NULL}
+};
+
+struct _id_list list_RadioChannelReq[] = {
+{0x00, "reserved"},
+{0x01, "full rate MS"},
+{0x02, "dual rate MS/half rate preferred"},
+{0x03, "dual rate MS/full rate preferred"},
+{-1, NULL}
+};
+
+struct _id_list list_TransferCap[] = {
+{0x00, "speech"},
+{0x01, "unrestricted digital information"},
+{0x02, "3.1 kHz audio, exx PLMN"},
+{0x03, "facsimile group 3"},
+{0x05, "Other ITC"},
+{-1, NULL}
+};
+
+struct _id_list list_alphabet[] = {
+{0x00, "default"},
+{0x01, "8 bit data"},
+{0x02, "UCS2 (16 bit)"},
+{0x03, "reserved"},
+{-1, NULL}
+};
+
+struct _id_list list_MessageClassMeaning[] = {
+{0x00, "Class 0"},
+{0x01, "Class 1: Default meaning: ME-specific"},
+{0x02, "Class 2: SIM specific message"},
+{0x03, "Class 3: Default meaning: TE specific (GSM 07.05[8])"},
+{-1, NULL}
+};
+
+struct _id_list list_MTI[] = {
+{0x00, "RP-DATA (ms->network)"},
+{0x01, "RP-DATA (network->ms)"},
+{0x02, "RP-ACK (ms->network)"},
+{0x03, "RP-ACK (network->ms)"},
+{0x04, "RP-ERROR (ms->network)"},
+{0x05, "RP-ERROR (network->ms)"},
+{0x06, "RP-SMMA (ms->network)"},
+{-1, NULL}
+};
+
+
+struct _id_list list_TP_MTI[] = {
+{0x00, "SMS-DELIVER (->MS) or SMS-DELIVER-REPORT (->SC)"},
+{0x01, "SMS-SUBMIT (->SC) or SMS-SUBMIT-REPORT (->MS)"},
+{0x02, "SMS-STATUS-REPORT (->MS) or SMS-COMMAND (->SC)"},
+{0x03, "reserved"},
+{-1, NULL}
+};
+
+struct _id_list list_TypeOfIdentity[] = {
+{0x01, "IMSI"},
+{0x02, "IMEI"},
+{0x03, "IMEISV"},
+{0x04, "TMSI"},
+{-1, NULL}
+};
+
+struct _id_list list_TypeOfLocationUpdate[] = {
+{0x00, "Normal"},
+{0x01, "Periodic"},
+{0x02, "IMSI attach"},
+{0x03, "reserved"},
+{-1, NULL}
+};
+
+struct _id_list list_RxQual[] = {
+{0x00, "~0.14%% error bit"},
+{0x01, "~0.s28%% error bit"},
+{0x02, "~0.57%% error bit"},
+{0x03, "~1.13%% error bit"},
+{0x04, "~2.25%% error bit"},
+{0x05, "~4.53%% error bit"},
+{0x06, "~9.05%% error bit"},
+{0x07, "~18.10%% error bit"},
+{-1, NULL}
+};
+
+struct _id_list list_Duplex[] = {
+{0x00, "half"},
+{0x01, "full"},
+{-1, NULL}
+};
+
+struct _id_list list_Rate[] = {
+{0x00, "no rate adaption"},
+{0x01, "V.100/X.30"},
+{0x02, "CCITT X.31 falg stuffing"},
+{0x03, "other"},
+{-1, NULL}
+};
+
+struct _id_list list_Signalling[] = {
+{0x01, "I.440/450"},
+{0x02, "X.21"},
+{0x03, "X.28 - dedicated PAD, individual NUI"},
+{0x04, "X.28 - dedicated PAD, universal NUI"},
+{0x05, "X.28 - non dedicated PAD"},
+{0x06, "X.32"},
+{-1, NULL}
+};
+
+struct _id_list list_Extension[] = {
+{0x00, "no"},
+{0x01, "yes"},
+{-1, NULL}
+};
+
+struct _id_list list_TypeNumber[] = {
+{0x00, "unknown"},
+{0x01, "international"},
+{0x02, "national"},
+{0x03, "network specifc number"},
+{-1, NULL}
+};
+
+
diff --git a/gsmdecode/src/gsmdecode.c b/gsmdecode/src/gsmdecode.c
new file mode 100644
index 0000000..04d30ab
--- /dev/null
+++ b/gsmdecode/src/gsmdecode.c
@@ -0,0 +1,289 @@
+#include "common.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "data_out.h"
+
+/*
+ * B: 112, 176, 128
+ * Bbis: 96, 80,
+ */
+
+#if 0
+- if there is layer 2 always use layer 2 (BBIS!)
+- if there is layer 1 but no layer 2 then generate layer2 from l1! (BBIS!)
+
+or
+
+- if there is layer1 use layer 1
+- if there is layer2 but no layer 1 generate layer1 msg
+#endif
+
+struct _opt opt;
+
+struct _ch_info
+{
+ unsigned char flags;
+ int logical;
+ int physical;
+ int direction;
+ int fn;
+ unsigned char data[23];
+ int data_len;
+};
+
+#define FL_CH_UP (0x01)
+#define FL_CH_DOWN (0x02)
+
+static int hex2bin(unsigned char *out, unsigned char *in);
+
+static void
+usage(char *str)
+{
+ fprintf(stderr,
+"Usage: gsmdecode [ options ]\n"
+" Raw hex input: It decodes one line at a time. The input format should look\n"
+" like this:\n"
+" 00 01 02 03 04 05 2b 2b 2b 2b 2b 2b 2b ...\n"
+" Nokia DCT3 trace debug input (XML) is supported with the -x option.\n"
+"\n"
+" Options:\n"
+" -h This message\n"
+" -b Force Format B (e.g. raw hex SDCCH)\n"
+" -i Force Format Bbis (e.g. raw hex BCCH)\n"
+" -x Force OpenGPA xml input format [default]\n"
+" -m Accept Motorola input (experimental)\n"
+"");
+
+ if (str)
+ {
+ fprintf(stderr, str);
+ exit(-1);
+ }
+ exit(0);
+}
+
+static int
+xml_get_int(int *val, const unsigned char *str, const unsigned char *pattern)
+{
+ char *ptr;
+ char *start, *end;
+ char buf[32];
+
+ ptr = strstr((char *)str, (char *)pattern);
+ if (ptr == NULL)
+ return -1;
+ start = strchr(ptr, '"');
+ if (start == NULL)
+ return -2;
+ start++;
+ end = strchr(start, '"');
+ if (end == NULL)
+ return -3;
+
+ memcpy(buf, start, end - start);
+ buf[end - start] = '\0';
+ *val = atoi(buf);
+ return 0;
+}
+
+/*
+ * - if there is layer1 use layer 1
+ * - if there is layer2 but no layer 1 generate layer1 msg
+ * Return -1 if no structure has been found.
+ */
+static int
+xml_in(struct _ch_info *chinfo, unsigned char *str)
+{
+ unsigned char *dst;
+ char *ptr;
+ int len;
+ int layer = 0;
+
+ if (memcmp(str, "<l1 ", 4) == 0)
+ {
+ memset(chinfo, 0, sizeof *chinfo);
+ memset(chinfo->data, 0x2b, sizeof chinfo->data);
+ layer = 1;
+ } else if (memcmp(str, "<l2 ", 4) == 0) {
+ /* If layer2 exists but layer1 also then do not decode
+ * layer2 again.
+ */
+ if (chinfo->data_len > 0)
+ return -1;
+ layer = 2;
+ } else
+ return -1;
+
+ /* First read all kind of meta information (logical channel, fn, ..) */
+ xml_get_int(&chinfo->logical, str, (const unsigned char *)"logicalchannel");
+// fprintf(stderr, "logical %u\n", chinfo->logical);
+
+ if (strstr((char *)str, "direction=\"up\"") != NULL)
+ {
+ chinfo->direction = 1;
+ } else if (strstr((char *)str, "direction=\"down\"") != NULL) {
+ chinfo->direction = 0;
+ }
+
+ /* Last see if there is a data="..." section. if so convert it into
+ * binary and prefix it with pseudo length and up/down indicator
+ * if required
+ */
+ ptr = strstr((char *)str, "data=\"");
+ /* Return 0 (true) here so that caller can decide if data_len
+ * contains other data to decode them...
+ * (This can happen if there is l1 but no l2 data)
+ */
+ if (ptr == NULL)
+ return 0;
+
+ ptr += 6;
+ dst = chinfo->data;
+ /* For layer 2 the xml input is missing the length data */
+ /* We prefix it! */
+ if (layer == 2)
+ {
+ /* HERE: Layer 1 missing, layer 2 available */
+ if ((chinfo->logical == 112) || (chinfo->logical == 176) || (chinfo->logical == 128))
+ {
+ /* B header */
+ memcpy(dst, "\x01\x01", 3);
+ chinfo->data_len = 3;
+ } else {
+ /* BBis header */
+ chinfo->data_len = 1;
+ }
+ dst += chinfo->data_len;
+ }
+
+ len = hex2bin(dst, (unsigned char *)ptr);
+ if (len <= 0)
+ return -3;
+ chinfo->data_len += len;
+ /* If layer 2 exist but not layer1 then we add a fake header */
+ if (layer == 2)
+ *(dst - 1) = len << 2;
+
+ return 0;
+}
+
+static void
+init_defaults()
+{
+ opt.format = MSG_FORMAT_XML;
+}
+
+static void
+do_getopt(int argc, char *argv[])
+{
+ int c;
+
+ while ((c = getopt(argc, argv, "hbixm")) != -1)
+ {
+ switch (c)
+ {
+ case 'm':
+ opt.flags |= FL_MOTOROLA;
+ break;
+ case 'x':
+ opt.format = MSG_FORMAT_XML;
+ break;
+ case 'b':
+ opt.format = MSG_FORMAT_B;
+ break;
+ case 'i':
+ opt.format = MSG_FORMAT_BBIS;
+ break;
+ case 'h':
+ default:
+ usage(NULL);
+ }
+
+ }
+}
+
+static int
+hc2b(unsigned char hex)
+{
+ hex = tolower(hex);
+ if ((hex >= '0') && (hex <= '9'))
+ return hex - '0';
+ if ((hex >= 'a') && (hex <= 'f'))
+ return hex - 'a' + 10;
+ return -1;
+}
+
+static int
+hex2bin(unsigned char *out, unsigned char *in)
+{
+ unsigned char *out_start = out;
+ unsigned char *end = in + strlen((char *)in);
+ int is_low = 0;
+ int c;
+
+ while (in < end)
+ {
+ c = hc2b(in[0]);
+ if (c < 0)
+ {
+ in++;
+ continue;
+ }
+ if (is_low == 0)
+ {
+ out[0] = c << 4;
+ is_low = 1;
+ } else {
+ out[0] |= (c & 0x0f);
+ is_low = 0;
+ out++;
+ }
+ in++;
+ }
+
+ return out - out_start;
+}
+
+int
+main(int argc, char *argv[])
+{
+ unsigned char buf[1024];
+ unsigned char bin[sizeof buf / 2 + 1];
+ int len;
+ struct _ch_info chi;
+
+ init_defaults();
+ do_getopt(argc, argv);
+ while (fgets((char *)buf, sizeof buf, stdin) != NULL)
+ {
+ if (opt.format == MSG_FORMAT_XML)
+ {
+ if (xml_in(&chi, buf) != 0)
+ continue;
+ if (chi.data_len <= 0)
+ continue;
+ if ((chi.logical == 112) || (chi.logical == 176) || (chi.logical == 128))
+ {
+ l2_data_out_B(0, chi.data, chi.data_len, chi.logical, chi.direction);
+ } else {
+ l2_data_out_Bbis(0, chi.data, chi.data_len);
+ }
+
+ memset(buf, 0, sizeof buf);
+ continue;
+ }
+ memset(bin, 0, sizeof bin);
+ len = hex2bin(bin, buf);
+ if (opt.format == MSG_FORMAT_B)
+ l2_data_out_B(0, bin, len, chi.logical, chi.direction);
+ else
+ l2_data_out_Bbis(0, bin, len);
+ }
+
+ exit(0);
+ return 0;
+}
+
diff --git a/gsmdecode/src/id_list.c b/gsmdecode/src/id_list.c
new file mode 100644
index 0000000..6736993
--- /dev/null
+++ b/gsmdecode/src/id_list.c
@@ -0,0 +1,19 @@
+#include "common.h"
+#include <string.h>
+#include "id_list.h"
+
+const char *
+id_list_get(struct _id_list *id_list, int id)
+{
+ struct _id_list *idptr = id_list;
+
+ while (idptr->string != NULL)
+ {
+ if (idptr->id == id)
+ return idptr->string;
+ idptr++;
+ }
+
+ return "UNKNOWN";
+}
+
diff --git a/gsmdecode/src/id_list.h b/gsmdecode/src/id_list.h
new file mode 100644
index 0000000..4493687
--- /dev/null
+++ b/gsmdecode/src/id_list.h
@@ -0,0 +1,15 @@
+
+#ifndef __GSMSP_ID_LIST_H__
+#define __GSMSP_ID_LIST_H__ 1
+
+struct _id_list
+{
+ int id;
+ const char *string;
+};
+
+const char *id_list_get(struct _id_list *id_list, int id);
+
+#endif /* !__GSMSP_COMMON_H__ */
+
+
diff --git a/gsmdecode/src/mcc_list.c b/gsmdecode/src/mcc_list.c
new file mode 100644
index 0000000..f9e6f28
--- /dev/null
+++ b/gsmdecode/src/mcc_list.c
@@ -0,0 +1,1433 @@
+
+#include "common.h"
+
+struct _mnc
+{
+ int mcc;
+ int mnc;
+ char *data;
+};
+
+struct _mcc
+{
+ int mcc;
+ char *data;
+};
+
+static struct _mcc mcc_list[] = {
+{202 , "Greece"},
+{204 , "Netherlands"},
+{206 , "Belgium"},
+{208 , "France"},
+{212 , "Monaco"},
+{213 , "Andorra"},
+{214 , "Spain"},
+{216 , "Hungary"},
+{218 , "Bosnia and Herzegovina"},
+{219 , "Croatia"},
+{220 , "Serbia and Montenegro"},
+{222 , "Italy"},
+{225 , "Vatican City State"},
+{226 , "Romania"},
+{228 , "Switzerland"},
+{230 , "Czech Republic"},
+{231 , "Slovakia"},
+{232 , "Austria"},
+{234 , "United Kingdom"},
+{235 , "United Kingdom"},
+{238 , "Denmark"},
+{240 , "Sweden"},
+{242 , "Norway"},
+{244 , "Finland"},
+{246 , "Lithuania"},
+{247 , "Latvia"},
+{248 , "Estonia"},
+{250 , "Russian Federation"},
+{255 , "Ukraine"},
+{257 , "Belarus"},
+{259 , "Moldova"},
+{260 , "Poland"},
+{262 , "Germany"},
+{266 , "Gibraltar (UK)"},
+{268 , "Portugal"},
+{270 , "Luxembourg"},
+{272 , "Ireland"},
+{274 , "Iceland"},
+{276 , "Albania"},
+{278 , "Malta"},
+{280 , "Cyprus"},
+{282 , "Georgia"},
+{283 , "Armenia"},
+{284 , "Bulgaria"},
+{286 , "Turkey"},
+{288 , "Faroe Islands (Denmark)"},
+{290 , "Greenland (Denmark)"},
+{292 , "San Marino"},
+{293 , "Slovenia"},
+{294 , "Republic of Macedonia"},
+{295 , "Liechtenstein"},
+{302 , "Canada"},
+{308 , "Saint Pierre and Miquelon (France)"},
+{310 , "United States of America"},
+{311 , "United States of America"},
+{312 , "United States of America"},
+{313 , "United States of America"},
+{314 , "United States of America"},
+{315 , "United States of America"},
+{316 , "United States of America"},
+{330 , "Puerto Rico (US)"},
+{332 , "United States Virgin Islands (US)"},
+{334 , "Mexico"},
+{338 , "Jamaica"},
+{340 , "Guadeloupe (France)"},
+{340 , "Martinique (France)"},
+{342 , "Barbados"},
+{344 , "Antigua and Barbuda"},
+{346 , "Cayman Islands (UK)"},
+{348 , "British Virgin Islands (UK)"},
+{350 , "Bermuda (UK)"},
+{352 , "Grenada"},
+{354 , "Montserrat (UK)"},
+{356 , "Saint Kitts and Nevis"},
+{358 , "Saint Lucia"},
+{360 , "Saint Vincent and the Grenadines"},
+{362 , "Netherlands Antilles (Netherlands)"},
+{363 , "Aruba (Netherlands)"},
+{364 , "Bahamas"},
+{365 , "Anguilla"},
+{366 , "Dominica"},
+{368 , "Cuba"},
+{370 , "Dominican Republic"},
+{372 , "Haiti"},
+{374 , "Trinidad and Tobago"},
+{376 , "Turks and Caicos Islands (UK)"},
+{400 , "Azerbaijani Republic"},
+{401 , "Kazakhstan"},
+{402 , "Bhutan"},
+{404 , "India"},
+{405 , "India"},
+{410 , "Pakistan"},
+{412 , "Afghanistan"},
+{413 , "Sri Lanka"},
+{414 , "Myanmar"},
+{415 , "Lebanon"},
+{416 , "Jordan"},
+{417 , "Syria"},
+{418 , "Iraq"},
+{419 , "Kuwait"},
+{420 , "Saudi Arabia"},
+{421 , "Yemen"},
+{422 , "Oman"},
+{424 , "United Arab Emirates"},
+{425 , "Israel"},
+{426 , "Bahrain"},
+{427 , "Qatar"},
+{428 , "Mongolia"},
+{429 , "Nepal"},
+{430 , "United Arab Emirates (Abu Dhabi)"},
+{431 , "United Arab Emirates (Dubai)"},
+{432 , "Iran"},
+{434 , "Uzbekistan"},
+{436 , "Tajikistan"},
+{437 , "Kyrgyz Republic"},
+{438 , "Turkmenistan"},
+{440 , "Japan"},
+{441 , "Japan"},
+{450 , "Korea, South"},
+{452 , "Viet Nam"},
+{454 , "Hong Kong (PRC)"},
+{455 , "Macao (PRC)"},
+{456 , "Cambodia"},
+{457 , "Laos"},
+{460 , "China"},
+{466 , "Taiwan"},
+{467 , "Korea, North"},
+{470 , "Bangladesh"},
+{472 , "Maldives"},
+{502 , "Malaysia"},
+{505 , "Australia"},
+{510 , "Indonesia"},
+{514 , "East Timor"},
+{515 , "Philippines"},
+{520 , "Thailand"},
+{525 , "Singapore"},
+{528 , "Brunei Darussalam"},
+{530 , "New Zealand"},
+{534 , "Northern Mariana Islands (US)"},
+{535 , "Guam (US)"},
+{536 , "Nauru"},
+{537 , "Papua New Guinea"},
+{539 , "Tonga"},
+{540 , "Solomon Islands"},
+{541 , "Vanuatu"},
+{542 , "Fiji"},
+{543 , "Wallis and Futuna (France)"},
+{544 , "American Samoa (US)"},
+{545 , "Kiribati"},
+{546 , "New Caledonia (France)"},
+{547 , "French Polynesia (France)"},
+{548 , "Cook Islands (NZ)"},
+{549 , "Samoa"},
+{550 , "Federated States of Micronesia"},
+{551 , "Marshall Islands"},
+{552 , "Palau"},
+{602 , "Egypt"},
+{603 , "Algeria"},
+{604 , "Morocco"},
+{605 , "Tunisia"},
+{606 , "Libya"},
+{607 , "Gambia"},
+{608 , "Senegal"},
+{609 , "Mauritania"},
+{610 , "Mali"},
+{611 , "Guinea"},
+{612 , "Cte d'Ivoire"},
+{613 , "Burkina Faso"},
+{614 , "Niger"},
+{615 , "Togolese Republic"},
+{616 , "Benin"},
+{617 , "Mauritius"},
+{618 , "Liberia"},
+{619 , "Sierra Leone"},
+{620 , "Ghana"},
+{621 , "Nigeria"},
+{622 , "Chad"},
+{623 , "Central African Republic"},
+{624 , "Cameroon"},
+{625 , "Cape Verde"},
+{626 , "So Tom and Prncipe"},
+{627 , "Equatorial Guinea"},
+{628 , "Gabonese Republic"},
+{629 , "Republic of the Congo"},
+{630 , "Democratic Republic of the Congo"},
+{631 , "Angola"},
+{632 , "Guinea-Bissau"},
+{633 , "Seychelles"},
+{634 , "Sudan"},
+{635 , "Rwandese Republic"},
+{636 , "Ethiopia"},
+{637 , "Somalia"},
+{638 , "Djibouti"},
+{639 , "Kenya"},
+{640 , "Tanzania"},
+{641 , "Uganda"},
+{642 , "Burundi"},
+{643 , "Mozambique"},
+{645 , "Zambia"},
+{646 , "Madagascar"},
+{647 , "Runion (France)"},
+{648 , "Zimbabwe"},
+{649 , "Namibia"},
+{650 , "Malawi"},
+{651 , "Lesotho"},
+{652 , "Botswana"},
+{653 , "Swaziland"},
+{654 , "Comoros"},
+{655 , "South Africa"},
+{657 , "Eritrea"},
+{702 , "Belize"},
+{704 , "Guatemala"},
+{706 , "El Salvador"},
+{708 , "Honduras"},
+{710 , "Nicaragua"},
+{712 , "Costa Rica"},
+{714 , "Panama"},
+{716 , "Peru"},
+{722 , "Argentine Republic"},
+{724 , "Brazil"},
+{730 , "Chile"},
+{732 , "Colombia"},
+{734 , "Venezuela"},
+{736 , "Bolivia"},
+{738 , "Guyana"},
+{740 , "Ecuador"},
+{742 , "French Guiana (France)"},
+{744 , "Paraguay"},
+{746 , "Suriname"},
+{748 , "Uruguay"},
+{901, "SATALITE"},
+};
+
+static struct _mnc mnc_list[] = {
+{202, 10, "Telestet"},
+{202, 1, "Cosmote"},
+{202, 5, "Vodafone - Panafon"},
+{202, 9, "Info Quest S.A."},
+{204, 12, "BT Ignite Nederland B.V."},
+{204, 16, "BEN Nederland B.V."},
+{204, 20, "Dutchtone N.V."},
+{204, 21, "NS Railinfrabeheer B.V."},
+{204, 2, "Tele2 (Netherlands) B.V."},
+{204, 4, "Vodafone Libertel N.V."},
+{204, 8, "KPN Telecom B.V."},
+{206, 10, "Mobistar"},
+{206, 1, "Proximus"},
+{206, 20, "Base"},
+{208, 10, "S.F.R."},
+{208, 11, "S.F.R. (UMTS)"},
+{208, 13, "SFR (Zones Blanches)"},
+{208, 1, "Orange France"},
+{208, 20, "Bouygues Telecom"},
+{208, 21, "Bouygues Telecom"},
+{208, 2, "Orange France"},
+{208, 5, "Globalstar Europe"},
+{208, 6, "Globalstar Europe"},
+{208, 7, "Globalstar Europe"},
+{208, 88, "Bouygues Telecom (Zones Blanches)"},
+{213, 3, "Mobiland"},
+{214, 1, "Vodafone"},
+{214, 3, "Amena"},
+{214, 4, "Xfera"},
+{214, 7, "Movistar"},
+{216, 1, "Pannon GSM"},
+{216, 30, "Westel Mobile"},
+{216, 70, "Vodafone"},
+{218, 3, "Eronet Mobile Communications Ltd."},
+{218, 5, "MOBI'S (Mobilina Srpske)"},
+{218, 90, "GSMBIH"},
+{219, 10, "VIPnet/VIPnet d.o.o."},
+{219, 1, "T-Mobile Hrvatska d.o.o./T-Mobile Croatia LLC"},
+{219, 2, "Tele2/Tele2 d.o.o."},
+{220, 1, "Telenor d.o.o."},
+{220, 3, "Telekom Srbija a.d."},
+{220, 5, "Vip mobile d.o.o."},
+{222, 10, "Omnitel Pronto Italia (OPI)"},
+{222, 1, "Telecom Italia Mobile (TIM)"},
+{222, 2, "Elsacom"},
+{222, 77, "IPSE 2000"},
+{222, 88, "Wind"},
+{222, 98, "Blu"},
+{222, 99, "H3G"},
+{226, 10, "Orange Romania"},
+{226, 1, "Vodafone Romania SA"},
+{226, 3, "Cosmorom"},
+{228, 12, "TDC Switzerland AG"},
+{228, 1, "Swisscom Mobile AG"},
+{228, 2, "TDC Switzerland AG"},
+{228, 3, "Orange Communications SA"},
+{228, 51, "Bebbicell AG"},
+{228, 5, "Comfone AG"},
+{228, 6, "SBB AG"},
+{228, 7, "IN&Phone SA"},
+{228, 8, "Tele2 Telecommunications AG"},
+{230, 1, "T-Mobile Czech Republic a.s."},
+{230, 2, "Telefnica O2 Czech Republic a.s."},
+{230, 3, "Vodafone Czech Republic a.s."},
+{230, 4, "Mobilkom a.s."},
+{230, 98, "Sprava Zeleznicni Dopravni Cesty"},
+{230, 99, "Vodafone Czech Republic a.s. R&D Centre"},
+{231, 1, "Orange, GSM"},
+{231, 2, "Eurotel, GSM & NMT"},
+{231, 4, "Eurotel, UMTS"},
+{231, 5, "Orange, UMTS"},
+{232, 10, "Hutchison 3G Austria"},
+{232, 1, "A1"},
+{232, 3, "T-Mobile"},
+{232, 5, "One"},
+{232, 7, "tele.ring"},
+{232, 8, "Telefonica Austria"},
+{232, 9, "One"},
+{234, 0, "British Telecom"},
+{234, 10, "O2 UK Ltd."},
+{234, 11, "O2 UK Ltd."},
+{234, 12, "Ntework Rail Infrastructure Ltd"},
+{234, 13, "Ntework Rail Infrastructure Ltd"},
+{234, 14, "Hay Systems Ltd"},
+{234, 15, "Vodafone Ltd."},
+{234, 16, "Opal Telecom Ltd"},
+{234, 17, "Flextel Ltd"},
+{234, 18, "Wire9 Telecom plc"},
+{234, 19, "Teleware plc"},
+{234, 1, "Mapesbury Communications Ltd."},
+{234, 20, "Hutchison 3G UK Ltd."},
+{234, 2, "O2 UK Ltd."},
+{234, 30, "T-Mobile UK"},
+{234, 31, "T-Mobile UK"},
+{234, 32, "T-Mobile UK"},
+{234, 33, "Orange"},
+{234, 34, "Orange"},
+{234, 3, "Jersey Telenet Ltd"},
+{234, 4, "FMS Solutions Ltd"},
+{234, 50, "Jersey Telecom"},
+{234, 55, "Cable and Wireless Guensey Ltd"},
+{234, 58, "Manx Telecom"},
+{234, 5, "Colt Mobile Telecommunications Ltd"},
+{234, 6, "Internet One Ltd"},
+{234, 75, "Inquam Telecom (Holdings) Ltd."},
+{234, 76, "British Telecom"},
+{234, 78, "Airwave mmO2 Ltd"},
+{234, 7, "Cable and Wireless plc"},
+{234, 9, "Wire9 Telecom plc"},
+{238, 10, "TDC Mobil"},
+{238, 1, "TDC Mobil"},
+{238, 20, "Telia"},
+{238, 2, "Sonofon"},
+{238, 30, "Telia Mobile"},
+{238, 3, "MIGway A/S"},
+{238, 6, "Hi3G"},
+{238, 77, "Tele2"},
+{238, 7, "Barablu Mobile Ltd."},
+{240, 10, "Spring Mobil AB"},
+{240, 11, "Linholmen Science Park AB"},
+{240, 12, "Barablu Mobile Scandinavia Ltd"},
+{240, 13, "Ventelo Sverige AB"},
+{240, 14, "TDC Mobil A/S"},
+{240, 15, "Wireless Maingate Nordic AB"},
+{240, 16, "42IT AB"},
+{240, 1, "Telia Sonera AB"},
+{240, 20, "Wireless Maingate Message Services AB"},
+{240, 21, "Banverket"},
+{240, 2, "H3G Access AB"},
+{240, 3, "Nordisk Mobiltelefon AS"},
+{240, 4, "3G Infrastructure Services AB"},
+{240, 5, "Svenska UMTS-Nt AB"},
+{240, 6, "Telenor Sverige AB"},
+{240, 7, "Tele2 Sverige AB"},
+{240, 8, "Telenor Sverige AB"},
+{240, 9, "Telenor Mobile Sverige"},
+{242, 1, "Telenor Mobil AS"},
+{242, 2, "Netcom GSM AS"},
+{242, 3, "Teletopia Mobile Communications AS"},
+{242, 4, "Tele2 Norge AS"},
+{244, 12, "Finnet Networks Ltd."},
+{244, 14, "Alands Mobiltelefon AB"},
+{244, 16, "Oy Finland Tele2 AB"},
+{244, 21, "Saunalahti Group Ltd."},
+{244, 4, "Finnet Networks Ltd."},
+{244, 5, "Elisa Matkapuhelinpalvelut Ltd."},
+{244, 91, "Sonera Carrier Networks Oy"},
+{244, 9, "Finnet Group"},
+{246, 1, "Omnitel"},
+{246, 2, "Bit GSM"},
+{246, 3, "Tele2"},
+{247, 1, "Latvian Mobile Phone"},
+{247, 2, "Tele2"},
+{247, 3, "Telekom Baltija"},
+{247, 4, "Beta Telecom"},
+{248, 1, "EMT GSM"},
+{248, 2, "RLE"},
+{248, 3, "Tele2"},
+{248, 4, "OY Top Connect"},
+{248, 5, "AS Bravocom Mobiil"},
+{248, 6, "OY ViaTel"},
+{248, 71, "Siseministeerium (Ministry of Interior)"},
+{248, 7, "Televrgu AS"},
+{250, 10, "Don Telecom"},
+{250, 11, "Orensot"},
+{250, 12, "Baykal Westcom"},
+{250, 13, "Kuban GSM"},
+{250, 16, "New Telephone Company"},
+{250, 17, "Ermak RMS"},
+{250, 19, "Volgograd Mobile"},
+{250, 1, "Mobile Telesystems"},
+{250, 20, "ECC"},
+{250, 28, "Extel"},
+{250, 2, "Megafon"},
+{250, 39, "Uralsvyazinform"},
+{250, 3, "Nizhegorodskaya Cellular Communications"},
+{250, 44, "Stuvtelesot"},
+{250, 4, "Sibchallenge"},
+{250, 5, "Mobile Comms System"},
+{250, 7, "BM Telecom"},
+{250, 92, "Printelefone"},
+{250, 93, "Telecom XXI"},
+{250, 99, "Bec Line GSM"},
+{255, 1, "Ukrainian Mobile Communication, UMC"},
+{255, 21, "CJSC - Telesystems of Ukraine"},
+{255, 2, "Ukranian Radio Systems, URS"},
+{255, 3, "Kyivstar GSM"},
+{255, 4, "International Telecommunications Ltd."},
+{255, 5, "Golden Telecom"},
+{255, 6, "Astelit"},
+{255, 7, "Ukrtelecom"},
+{257, 1, "MDC Velcom"},
+{257, 2, "MTS"},
+{259, 1, "Orange Moldova GSM"},
+{259, 2, "Moldcell GSM"},
+{259, 4, "Eventis Mobile GSM"},
+{260, 10, "Telefony Opalenickie"},
+{260, 1, "Plus GSM (Polkomtel S.A.)"},
+{260, 2, "ERA GSM (Polska Telefonia Cyfrowa Sp. Z.o.o.)"},
+{260, 3, "Idea (Polska Telefonia Komrkowa Centertel Sp. Z.o.o)"},
+{260, 4, "Tele2 Polska (Tele2 Polska Sp. Z.o.o.)"},
+{260, 5, "IDEA (UMTS)/PTK Centertel sp. Z.o.o."},
+{260, 6, "Netia Mobile"},
+{260, 7, "Premium internet"},
+{260, 8, "E-Telko"},
+{260, 9, "Telekomunikacja Kolejowa (GSM-R)"},
+{262, 10, "Arcor AG & Co."},
+{262, 11, "O2 (Germany) GmbH & Co. OHG"},
+{262, 12, "Dolphin Telecom (Deutschland) GmbH"},
+{262, 13, "Mobilcom Multimedia GmbH"},
+{262, 14, "Group 3G UMTS GmbH (Quam)"},
+{262, 15, "Airdata AG"},
+{262, 1, "T-Mobile Deutschland GmbH"},
+{262, 2, "Vodafone D2 GmbH"},
+{262, 3, "E-Plus Mobilfunk GmbH & Co. KG"},
+{262, 4, "Vodafone D2 GmbH"},
+{262, 5, "E-Plus Mobilfunk GmbH & Co. KG"},
+{262, 6, "T-Mobile Deutschland GmbH"},
+{262, 76, "Siemens AG, ICMNPGUSTA"},
+{262, 77, "E-Plus Mobilfunk GmbH & Co. KG"},
+{262, 7, "O2 (Germany) GmbH & Co. OHG"},
+{262, 8, "O2 (Germany) GmbH & Co. OHG"},
+{262, 9, "Vodafone D2 GmbH"},
+{266, 1, "Gibtelecom GSM"},
+{266, 9, "Cloud9 Mobile Communications"},
+{268, 1, "Vodafone Telecel - Comunicaes Pessoais, S.A."},
+{268, 3, "Optimus - Telecomunicaes, S.A."},
+{268, 5, "Oniway - Inforcomunicaes, S.A."},
+{268, 6, "TMN - Telecomunicaes Movis Nacionais, S.A."},
+{270, 1, "P&T Luxembourg"},
+{270, 77, "Tango"},
+{270, 99, "Voxmobile S.A."},
+{272, 1, "Vodafone Ireland Plc"},
+{272, 2, "Digifone mm02 Ltd."},
+{272, 3, "Meteor Mobile Communications Ltd."},
+{272, 7, "Eircom"},
+{272, 9, "Clever Communications Ltd."},
+{274, 1, "Iceland Telecom Ltd."},
+{274, 2, "Tal hf"},
+{274, 3, "Islandssimi GSM ehf"},
+{274, 4, "IMC Islande ehf"},
+{274, 7, "IceCell ehf"},
+{276, 1, "AMC"},
+{276, 2, "Vodafone Albania"},
+{276, 3, "Eagle Mobile"},
+{278, 1, "Vodafone Malta"},
+{278, 21, "go mobile"},
+{280, 10, "Scancom (Cyprus) Ltd."},
+{280, 1, "CYTA"},
+{282, 1, "Geocell Ltd."},
+{282, 2, "Magti GSM Ltd."},
+{282, 3, "Iberiatel Ltd."},
+{282, 4, "Mobitel Ltd."},
+{284, 1, "M-Tel GSM BG"},
+{284, 5, "Globul"},
+{286, 1, "Turkcell"},
+{286, 2, "Telsim GSM"},
+{286, 3, "Aria"},
+{286, 4, "Aycell"},
+{288, 1, "Faroese Telecom - GSM"},
+{288, 2, "Kall GSM"},
+{290, 1, "Tele Greenland"},
+{292, 1, "SMT - San Marino Telecom"},
+{293, 40, "SI Mobil"},
+{293, 41, "Mobitel"},
+{293, 64, "T-2 d.o.o."},
+{293, 70, "Tusmobil d.o.o."},
+{294, 1, "T-Mobile"},
+{294, 2, "Cosmofon"},
+{294, 3, "Nov Operator"},
+{295, 1, "Telecom FL AG"},
+{295, 2, "Viag Europlatform AG"},
+{295, 5, "Mobilkom (Liechstein) AG"},
+{295, 77, "Tele2 AG"},
+{297, 3, "MTEL d.o.o. Podgorica"},
+{302, 36, "Clearnet"},
+{302, 37, "Microcell"},
+{302, 62, "Ice Wireless"},
+{302, 63, "Aliant Mobility"},
+{302, 64, "Bell Mobility"},
+{302, 656, "Tbay Mobility"},
+{302, 66, "MTS Mobility"},
+{302, 67, "CityTel Mobility"},
+{302, 68, "Sask Tel Mobility"},
+{302, 71, "Globalstar"},
+{302, 72, "Rogers Wireless"},
+{302, 86, "Telus Mobility"},
+{308, 1, "St. Pierre-et-Miquelon Tlcom"},
+{310, 100, "New Mexico RSA 4 East Ltd. Partnership"},
+{310, 10, "MCI"},
+{310, 110, "Pacific Telecom Inc"},
+{310, 120, "Sprint"},
+{310, 12, "Verizon Wireless"},
+{310, 130, "Carolina West Wireless"},
+{310, 13, "Mobile Tel Inc."},
+{310, 140, "GTA Wireless LLC"},
+{310, 150, "Cingular Wireless"},
+{310, 160, "T-Mobile USA"},
+{310, 16, "Cricket Communications"},
+{310, 170, "Cingular Wireless"},
+{310, 17, "North Sight Communications Inc."},
+{310, 180, "West Central Wireless"},
+{310, 190, "Alaska Wireless Communications LLC"},
+{310, 200, "T-Mobile USA"},
+{310, 20, "Union Telephone Company"},
+{310, 210, "T-Mobile USA"},
+{310, 220, "T-Mobile USA"},
+{310, 230, "T-Mobile USA"},
+{310, 240, "T-Mobile USA"},
+{310, 250, "T-Mobile USA"},
+{310, 260, "T-Mobile USA"},
+{310, 270, "T-Mobile USA"},
+{310, 280, "Contennial Puerto Rio License Corp."},
+{310, 290, "Nep Cellcorp Inc."},
+{310, 30, "Centennial Communications"},
+{310, 310, "T-Mobile USA"},
+{310, 320, "Smith Bagley Inc, dba Cellular One"},
+{310, 330, "AN Subsidiary LLC"},
+{310, 340, "High Plains Midwest LLC, dba Wetlink Communications"},
+{310, 34, "Nevada Wireless LLC"},
+{310, 350, "Mohave Cellular L.P."},
+{310, 360, "Cellular Network Partnership dba Pioneer Cellular"},
+{310, 370, "Guamcell Cellular and Paging"},
+{310, 380, "New Cingular Wireless PCS, LLC"},
+{310, 390, "TX-11 Acquistion LLC"},
+{310, 400, "Wave Runner LLC"},
+{310, 40, "MTA Communications dba MTA Wireless"},
+{310, 410, "Cingular Wireless"},
+{310, 420, "Cincinnati Bell Wireless LLC"},
+{310, 430, "Alaska Digitel LLC"},
+{310, 440, "Numerex Corp."},
+{310, 450, "North East Cellular Inc."},
+{310, 460, "TMP Corporation"},
+{310, 480, "Choice Phone LLC"},
+{310, 490, "SunCom Wireless"},
+{310, 500, "Public Service Cellular, Inc."},
+{310, 50, "ACS Wireless Inc."},
+{310, 510, "Airtel Wireless LLC"},
+{310, 520, "VeriSign"},
+{310, 540, "Oklahoma Western Telephone Company"},
+{310, 550, "Wireless Solutions International"},
+{310, 560, "American Cellular Corporation"},
+{310, 570, "MTPCS LLC"},
+{310, 580, "Inland Cellular Telephone Company"},
+{310, 590, "Western Wireless Corporation"},
+{310, 600, "New Cell Inc. dba Cellcom"},
+{310, 60, "Consolidated Telcom"},
+{310, 610, "Elkhart Telephone Co. Inc. dba Epic Touch Co."},
+{310, 620, "Coleman County Telecommunications Inc. (Trans Texas PCS)"},
+{310, 640, "Airadigm Communications"},
+{310, 650, "Jasper Wireless Inc."},
+{310, 660, "T-Mobile USA"},
+{310, 670, "AT&T Mobility Vanguard Services"},
+{310, 690, "Conestoga Wireless Company"},
+{310, 700, "Cross Valiant Cellular Partnership"},
+{310, 70, "Highland Cellular, Inc."},
+{310, 710, "Arctic Slopo Telephone Association Cooperative"},
+{310, 720, "Wireless Solutions International Inc."},
+{310, 730, "Sea Mobile"},
+{310, 750, "East Kentucky Network LLC dba Appalachian Wireless"},
+{310, 760, "Panhandle Telecommunications Systems Inc."},
+{310, 770, "Iowa Wireless Services LLC dba I Wireless"},
+{310, 780, "Connect Net Inc"},
+{310, 790, "PinPoint Communications Inc."},
+{310, 800, "T-Mobile USA"},
+{310, 80, "Corr Wireless Communications LLC"},
+{310, 810, "Brazos Cellular Communications Ltd."},
+{310, 820, "South Canaan Cellular Communications Co. LP"},
+{310, 830, "Caprock Cellular Ltd. Partnership"},
+{310, 840, "Edge Mobile LLC"},
+{310, 850, "Aeris Communications, Inc."},
+{310, 860, "TX RSA 15B2, LP dba Five Star Wireless"},
+{310, 870, "Kaplan Telephone Company Inc."},
+{310, 880, "Advantage Cellular Systems, Inc."},
+{310, 890, "Rural Cellular Corporation"},
+{310, 900, "Taylor Telecommunications Ltd."},
+{310, 90, "Edge Wireless LLC"},
+{310, 910, "Southern IL RSA Partnership dba First Cellular of Southern Illinois"},
+{310, 920, "Get Mobile"},
+{310, 930, "Copper Valley Wireless"},
+{310, 950, "Texas RSA 1 dba XIT Cellular"},
+{310, 960, "UBET Wireless"},
+{310, 970, "Globalstar USA"},
+{310, 980, "New Cingular Wireless PCS LLC"},
+{311, 0, "Mid-Tex Cellular Ltd."},
+{311, 10, "Chariton Valley Communications Corp., Inc."},
+{311, 110, "Alltel Communications Inc"},
+{311, 120, "Choice Phone LLC"},
+{311, 140, "MBO Wireless Inc./Cross Telephone Company"},
+{311, 150, "Wilkes Cellular Inc."},
+{311, 170, "PetroCom LLC"},
+{311, 180, "Cingular Wireless, Licensee Pacific Telesis Mobile "},
+{311, 190, "Cellular Properties Inc."},
+{311, 200, "ARINC"},
+{311, 20, "Missouri RSA No. 5 Partnership"},
+{311, 210, "Farmers Cellular Telephone"},
+{311, 230, "Cellular South Inc."},
+{311, 240, "Cordova Wireless Communications Inc"},
+{311, 250, "Wave Runner LLC"},
+{311, 260, "SLO Cellular Inc. dba CellularOne of San Luis Obispo"},
+{311, 270, "Alltel Communications Inc."},
+{311, 271, "Alltel Communications Inc."},
+{311, 272, "Alltel Communications Inc."},
+{311, 273, "Alltel Communications Inc."},
+{311, 274, "Alltel Communications Inc."},
+{311, 275, "Alltel Communications Inc."},
+{311, 276, "Alltel Communications Inc."},
+{311, 277, "Alltel Communications Inc."},
+{311, 278, "Alltel Communications Inc."},
+{311, 279, "Alltel Communications Inc."},
+{311, 280, "Verizon Wireless"},
+{311, 281, "Verizon Wireless"},
+{311, 282, "Verizon Wireless"},
+{311, 283, "Verizon Wireless"},
+{311, 284, "Verizon Wireless"},
+{311, 285, "Verizon Wireless"},
+{311, 286, "Verizon Wireless"},
+{311, 287, "Verizon Wireless"},
+{311, 288, "Verizon Wireless"},
+{311, 289, "Verizon Wireless"},
+{311, 290, "Pinpoint Wireless Inc."},
+{311, 300, "Rutal Cellular Corporation"},
+{311, 30, "Indigo Wireless, Inc."},
+{311, 310, "Leaco Rural Telephone Company Inc"},
+{311, 320, "Commnet Wireless LLC"},
+{311, 330, "Bag Tussel Wireless LLC"},
+{311, 340, "Illinois Valley Cellular"},
+{311, 350, "Torrestar Networks Inc"},
+{311, 360, "Stelera Wireless LLC"},
+{311, 370, "GCI Communications Corp."},
+{311, 380, "GreenFly LLC"},
+{311, 390, "Midwest Wireless Holdings LLC"},
+{311, 400, "New Cingular Wireless PCS LLC"},
+{311, 40, "Commet Wireless, LLC"},
+{311, 410, "Iowa RSA No.2 Ltd Partnership"},
+{311, 420, "Northwest Missouri Cellular Limited Partnership"},
+{311, 430, "RSA 1 Limited Partnership dba Cellular 29 Plus"},
+{311, 440, "Bluegrass Cellular LLC"},
+{311, 450, "Panhandle Telecommunication Systems Inc."},
+{311, 460, "Fisher Wireless Services Inc"},
+{311, 470, "Vitelcom Cellular Inc dba Innovative Wireless"},
+{311, 480, "Verizon Wireless"},
+{311, 481, "Verizon Wireless"},
+{311, 482, "Verizon Wireless"},
+{311, 483, "Verizon Wireless"},
+{311, 484, "Verizon Wireless"},
+{311, 485, "Verizon Wireless"},
+{311, 486, "Verizon Wireless"},
+{311, 487, "Verizon Wireless"},
+{311, 488, "Verizon Wireless"},
+{311, 489, "Verizon Wireless"},
+{311, 490, "Strata8 Networks Inc/Wirefree Partners LLC"},
+{311, 500, "CTC Telecom Inc"},
+{311, 50, "Thumb Cellular Limited Partnership"},
+{311, 510, "Benton-Lian Wireless"},
+{311, 520, "Crossroads Wireless Inc"},
+{311, 530, "Wireless Communications Venture"},
+{311, 540, "Keystone Wireless Inc"},
+{311, 550, "Commnet Midwest LLC"},
+{311, 60, "Space Data Corporation"},
+{311, 70, "Easterbrooke Cellular Corporation"},
+{311, 80, "Pine Telephone Company dba Pine Cellular"},
+{311, 90, "Siouxland PCS"},
+{316, 10, "Nextel Communications Inc."},
+{316, 11, "Southern Communications Services Inc."},
+{334, 20, "Telcel"},
+{338, 20, "Cable & Wireless Jamaica Ltd."},
+{338, 50, "Mossel (Jamaica) Ltd."},
+{340, 1, "Orange Carabe Mobiles"},
+{340, 20, "Bouygues Telecom Carabe"},
+{340, 2, "Outremer Telecom"},
+{340, 3, "Saint Martin et Saint Barthelemy Telcell Sarl"},
+{342, 600, "Cable & Wireless (Barbados) Ltd."},
+{342, 820, "Sunbeach Communications"},
+{344, 30, "APUA PCS"},
+{344, 920, "Cable & Wireless (Antigua)"},
+{344, 930, "AT&T Wireless (Antigua)"},
+{346, 140, "Cable & Wireless (Cayman)"},
+{348, 570, "Caribbean Cellular Telephone, Boatphone Ltd."},
+{362, 51, "TELCELL GSM"},
+{362, 69, "CT GSM"},
+{362, 91, "SETEL GSM"},
+{363, 1, "Setar GSM"},
+{365, 10, "Weblinks Limited"},
+{368, 1, "ETECSA"},
+{370, 1, "Orange Dominicana, S.A."},
+{370, 2, "Verizon Dominicana S.A."},
+{370, 3, "Tricom S.A."},
+{370, 4, "CentennialDominicana"},
+{372, 1, "Comcel"},
+{372, 2, "Digicel"},
+{372, 3, "Rectel"},
+{374, 12, "TSTT Mobile"},
+{374, 130, "Digicel Trinidad and Tobago Ltd."},
+{374, 140, "LaqTel Ltd."},
+{376, 352, "IslandCom Communications Ltd."},
+{400, 1, "Azercell Limited Liability Joint Venture"},
+{400, 2, "Bakcell Limited Liabil ity Company"},
+{400, 3, "Catel JV"},
+{400, 4, "Azerphone LLC"},
+{401, 1, "Kar-Tel llc"},
+{401, 2, "TSC Kazak Telecom"},
+{402, 11, "Bhutan Telecom Ltd"},
+{402, 17, "B-Mobile of Bhutan Telecom"},
+{404, 10, "Bharti Cellular Ltd."},
+{404, 11, "Sterling Cellular Ltd."},
+{404, 12, "Escotel Mobile Communications Pvt Ltd."},
+{404, 13, "Hutchinson Essar South Ltd."},
+{404, 14, "Spice Communications Ltd."},
+{404, 15, "Aircell Digilink India Ltd."},
+{404, 16, "Hexcom India"},
+{404, 18, "Reliance Telecom Private Ltd."},
+{404, 19, "Escotel Mobile Communications Pvt Ltd."},
+{404, 1, "Aircell Digilink India Ltd.,"},
+{404, 20, "Hutchinson Max Telecom"},
+{404, 21, "BPL Mobile Communications Ltd."},
+{404, 22, "Idea Cellular Ltd."},
+{404, 24, "Idea Cellular Ltd."},
+{404, 27, "BPL Cellular Ltd."},
+{404, 2, "Bharti Mobile Ltd."},
+{404, 30, "Usha Martin Telecom Ltd."},
+{404, 31, "Bharti Mobinet Ltd."},
+{404, 34, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 36, "Reliance Telecom Private Ltd."},
+{404, 38, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 3, "Bharti Telenet Ltd."},
+{404, 40, "Bharti Mobinet Ltd."},
+{404, 41, "RPG Cellular"},
+{404, 42, "Aircel Ltd."},
+{404, 43, "BPL Mobile Cellular Ltd."},
+{404, 44, "Spice Communications Ltd."},
+{404, 46, "BPL Cellular Ltd."},
+{404, 49, "Bharti Mobile Ltd."},
+{404, 4, "Idea Cellular Ltd."},
+{404, 50, "Reliance Telecom Private Ltd."},
+{404, 51, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 52, "Reliance Telecom Private Ltd."},
+{404, 53, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 54, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 55, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 56, "Escotel Mobile Communications Pvt Ltd."},
+{404, 57, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 58, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 59, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 5, "Fascel Ltd."},
+{404, 60, "Aircell Digilink India Ltd."},
+{404, 62, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 64, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 66, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 67, "Reliance Telecom Private Ltd."},
+{404, 68, "Mahanagar Telephone Nigam Ltd."},
+{404, 69, "Mahanagar Telephone Nigam Ltd."},
+{404, 6, "Bharti Mobile Ltd."},
+{404, 70, "Hexicom India"},
+{404, 71, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 72, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 73, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 74, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 75, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 76, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 77, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 78, "BTA Cellcom Ltd."},
+{404, 7, "Idea Cellular Ltd."},
+{404, 80, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 81, "Bharat Sanchar Nigam Ltd. (BSNL)"},
+{404, 82, "Escorts Telecom Ltd."},
+{404, 83, "Reliable Internet Services Ltd."},
+{404, 84, "Hutchinson Essar South Ltd."},
+{404, 85, "Reliance Telecom Private Ltd."},
+{404, 86, "Hutchinson Essar South Ltd."},
+{404, 87, "Escorts Telecom Ltd."},
+{404, 88, "Escorts Telecom Ltd."},
+{404, 89, "Escorts Telecom Ltd."},
+{404, 90, "Bharti Cellular Ltd."},
+{404, 92, "Bharti Cellular Ltd."},
+{404, 93, "Bharti Cellular Ltd."},
+{404, 94, "Bharti Cellular Ltd."},
+{404, 95, "Bharti Cellular Ltd."},
+{404, 96, "Bharti Cellular Ltd."},
+{404, 97, "Bharti Cellular Ltd."},
+{404, 98, "Bharti Cellular Ltd."},
+{404, 9, "Reliance Telecom Private Ltd."},
+{410, 1, "Mobilink"},
+{410, 3, "PAK Telecom Mobile Ltd. (UFONE)"},
+{412, 1, "AWCC"},
+{412, 20, "Roshan"},
+{412, 30, "New1"},
+{412, 40, "Areeba Afghanistan"},
+{412, 88, "Afghan Telecom"},
+{413, 2, "MTN Network Ltd."},
+{413, 3, "Celtel Lanka Ltd."},
+{414, 1, "Myanmar Post and Telecommunication"},
+{415, 32, "Cellis"},
+{415, 33, "Cellis"},
+{415, 34, "Cellis"},
+{415, 35, "Cellis"},
+{415, 36, "Libancell"},
+{415, 37, "Libancell"},
+{415, 38, "Libancell"},
+{415, 39, "Libancell"},
+{416, 1, "Fastlink"},
+{416, 2, "Xpress"},
+{416, 3, "Umniah"},
+{416, 77, "Mobilecom"},
+{417, 1, "Syriatel"},
+{417, 2, "Spacetel Syria"},
+{417, 9, "Syrian Telecom"},
+{419, 2, "Mobile Telecommunications Company"},
+{419, 3, "Wataniya Telecom"},
+{420, 1, "Saudi Telecom"},
+{420, 3, "Etihad Etisalat Company (Mobily)"},
+{421, 1, "Yemen Mobile Phone Company"},
+{421, 2, "Spacetel Yemen"},
+{422, 2, "Oman Mobile Telecommunications Company (Oman Mobile)"},
+{422, 3, "Oman Qatari Telecommunications Company (Nawras)"},
+{422, 4, "Oman Telecommunications Company (Omantel)"},
+{424, 2, "Etisalat"},
+{425, 1, "Partner Communications Co. Ltd."},
+{425, 2, "Cellcom Israel Ltd."},
+{425, 3, "Pelephone Communications Ltd."},
+{426, 1, "BHR Mobile Plus"},
+{427, 1, "QATARNET"},
+{428, 99, "Mobicom"},
+{429, 1, "Nepal Telecommunications"},
+{432, 11, "Telecommunication Company of Iran (TCI)"},
+{432, 14, "Telecommunication Kish Co. (KIFZO)"},
+{432, 19, "Telecommunication Company of Iran (TCI) - Isfahan Celcom "},
+{434, 1, "Buztel"},
+{434, 2, "Uzmacom"},
+{434, 4, "Daewoo Unitel"},
+{434, 5, "Coscom"},
+{434, 7, "Uzdunrobita"},
+{436, 1, "JC Somoncom"},
+{436, 2, "CJSC Indigo Tajikistan"},
+{436, 3, "TT mobile"},
+{436, 4, "Josa Babilon-T"},
+{436, 5, "CTJTHSC Tajik-tel"},
+{437, 1, "Bitel GSM"},
+{438, 1, "Barash Communication Technologies (BCTI)"},
+{438, 2, "TM-Cell"},
+{440, 10, "NTT DoCoMo Kansai Inc."},
+{440, 11, "NTT DoCoMo Tokai Inc."},
+{440, 12, "NTT DoCoMo Inc."},
+{440, 13, "NTT DoCoMo Inc."},
+{440, 14, "NTT DoCoMo Tohoku Inc."},
+{440, 15, "NTT DoCoMo Inc."},
+{440, 16, "NTT DoCoMo Inc."},
+{440, 17, "NTT DoCoMo Inc."},
+{440, 18, "NTT DoCoMo Tokai Inc."},
+{440, 19, "NTT DoCoMo Hokkaido"},
+{440, 1, "NTT DoCoMo, Inc."},
+{440, 20, "NTT DoCoMo Hokuriku Inc."},
+{440, 21, "NTT DoCoMo Inc."},
+{440, 22, "NTT DoCoMo Kansai Inc."},
+{440, 23, "NTT DoCoMo Tokai Inc."},
+{440, 24, "NTT DoCoMo Chugoku Inc."},
+{440, 25, "NTT DoCoMo Hokkaido Inc."},
+{440, 26, "NTT DoCoMo Kyushu Inc."},
+{440, 27, "NTT DoCoMoTohoku Inc."},
+{440, 28, "NTT DoCoMo Shikoku Inc."},
+{440, 29, "NTT DoCoMo Inc."},
+{440, 2, "NTT DoCoMo Kansai, Inc."},
+{440, 30, "NTT DoCoMo Inc."},
+{440, 31, "NTT DoCoMo Kansai Inc."},
+{440, 32, "NTT DoCoMo Inc."},
+{440, 33, "NTT DoCoMo Tokai Inc."},
+{440, 34, "NTT DoCoMo Kyushu Inc."},
+{440, 35, "NTT DoCoMo Kansai Inc."},
+{440, 36, "NTT DoCoMo Inc."},
+{440, 37, "NTT DoCoMo Inc."},
+{440, 38, "NTT DoCoMo Inc."},
+{440, 39, "NTT DoCoMo Inc."},
+{440, 3, "NTT DoCoMo Hokuriku, Inc."},
+{440, 40, "Vodafone"},
+{440, 41, "Vodafone"},
+{440, 42, "Vodafone"},
+{440, 43, "Vodafone"},
+{440, 44, "Vodafone"},
+{440, 45, "Vodafone"},
+{440, 46, "Vodafone"},
+{440, 47, "Vodafone"},
+{440, 48, "Vodafone"},
+{440, 49, "NTT DoCoMo Inc."},
+{440, 4, "Vodafone"},
+{440, 50, "KDDI Corporation"},
+{440, 51, "KDDI Corporation"},
+{440, 52, "KDDI Corporation"},
+{440, 53, "KDDI Corporation"},
+{440, 54, "KDDI Corporation"},
+{440, 55, "KDDI Corporation"},
+{440, 56, "KDDI Corporation"},
+{440, 58, "NTT DoCoMo Kansai Inc."},
+{440, 60, "NTT DoCoMo Kansai Inc."},
+{440, 61, "NTT DoCoMo Chugoku Inc."},
+{440, 62, "NTT DoCoMo Kyushu Inc."},
+{440, 63, "NTT DoCoMo Inc."},
+{440, 64, "NTT DoCoMo Inc."},
+{440, 65, "NTT DoCoMo Shikoku Inc."},
+{440, 66, "NTT DoCoMo Inc."},
+{440, 67, "NTT DoCoMo Tohoku Inc."},
+{440, 68, "NTT DoCoMo Kyushu Inc."},
+{440, 69, "NTT DoCoMo Inc."},
+{440, 6, "Vodafone"},
+{440, 70, "KDDI Corporation"},
+{440, 71, "KDDI Corporation"},
+{440, 72, "KDDI Corporation"},
+{440, 73, "KDDI Corporation"},
+{440, 74, "KDDI Corporation"},
+{440, 75, "KDDI Corporation"},
+{440, 76, "KDDI Corporation"},
+{440, 77, "KDDI Corporation"},
+{440, 78, "Okinawa Cellular Telephone"},
+{440, 79, "KDDI Corporation"},
+{440, 7, "KDDI Corporation"},
+{440, 80, "TU-KA Cellular Tokyo Inc."},
+{440, 81, "TU-KA Cellular Tokyo Inc."},
+{440, 82, "TU-KA Phone Kansai Inc."},
+{440, 83, "TU-KA Cellular Tokai Inc."},
+{440, 84, "TU-KA Phone Kansai Inc."},
+{440, 85, "TU-KA Cellular Tokai Inc."},
+{440, 86, "TU-KA Cellular Tokyo Inc."},
+{440, 87, "NTT DoCoMo Chugoku Inc."},
+{440, 88, "KDDI Corporation"},
+{440, 89, "KDDI Corporation"},
+{440, 8, "KDDI Corporation"},
+{440, 90, "Vodafone"},
+{440, 92, "Vodafone"},
+{440, 93, "Vodafone"},
+{440, 94, "Vodafone"},
+{440, 95, "Vodafone"},
+{440, 96, "Vodafone"},
+{440, 97, "Vodafone"},
+{440, 98, "Vodafone"},
+{440, 99, "NTT DoCoMo Inc."},
+{440, 9, "NTT DoCoMo Kansai Inc."},
+{441, 40, "NTT DoCoMo Inc."},
+{441, 41, "NTT DoCoMo Inc."},
+{441, 42, "NTT DoCoMo Inc."},
+{441, 43, "NTT DoCoMo Kansai Inc."},
+{441, 44, "NTT DoCoMo Chugoku Inc."},
+{441, 45, "NTT DoCoMo Shikoku Inc."},
+{441, 50, "TU-KA Cellular Tokyo Inc."},
+{441, 51, "TU-KA Phone Kansai Inc."},
+{441, 61, "Vodafone"},
+{441, 62, "Vodafone"},
+{441, 63, "Vodafone"},
+{441, 64, "Vodafone"},
+{441, 65, "Vodafone"},
+{441, 70, "KDDI Corporation"},
+{441, 90, "NTT DoCoMo Inc."},
+{441, 91, "NTT DoCoMo Inc."},
+{441, 92, "NTT DoCoMo Inc."},
+{441, 93, "NTT DoCoMo Hokkaido Inc."},
+{441, 94, "NTT DoCoMo Tohoku Inc."},
+{441, 98, "NTT DoCoMo Kyushu Inc."},
+{441, 99, "NTT DoCoMo Kyushu Inc."},
+{452, 1, "Mobifone"},
+{452, 2, "Vinaphone"},
+{454, 0, "GSM900/HKCSL"},
+{454, 10, "GSM1800New World PCS Ltd."},
+{454, 11, "MVNO/CHKTL"},
+{454, 12, "GSM1800/Peoples Telephone Company Ltd."},
+{454, 15, "3G Radio System/SMT3G"},
+{454, 16, "GSM1800/Mandarin Communications Ltd."},
+{454, 18, "GSM7800/Hong Kong CSL Ltd."},
+{454, 19, "3G Radio System/Sunday3G"},
+{454, 1, "MVNO/CITIC"},
+{454, 2, "3G Radio System/HKCSL3G"},
+{454, 20, "Public Mobile Networks/Reserved"},
+{454, 21, "Public Mobile Networks/Reserved"},
+{454, 22, "Public Mobile Networks/Reserved"},
+{454, 23, "Public Mobile Networks/Reserved"},
+{454, 24, "Public Mobile Networks/Reserved"},
+{454, 25, "Public Mobile Networks/Reserved"},
+{454, 26, "Public Mobile Networks/Reserved"},
+{454, 27, "Public Mobile Networks/Reserved"},
+{454, 28, "Public Mobile Networks/Reserved"},
+{454, 29, "Public Mobile Networks/Reserved"},
+{454, 3, "3G Radio System/Hutchison 3G"},
+{454, 30, "Public Mobile Networks/Reserved"},
+{454, 31, "Public Mobile Networks/Reserved"},
+{454, 32, "Public Mobile Networks/Reserved"},
+{454, 33, "Public Mobile Networks/Reserved"},
+{454, 34, "Public Mobile Networks/Reserved"},
+{454, 35, "Public Mobile Networks/Reserved"},
+{454, 36, "Public Mobile Networks/Reserved"},
+{454, 37, "Public Mobile Networks/Reserved"},
+{454, 38, "Public Mobile Networks/Reserved"},
+{454, 39, "Public Mobile Networks/Reserved"},
+{454, 4, "GSM900/GSM1800/Hutchison"},
+{454, 5, "CDMA/Hutchison"},
+{454, 6, "GSM900/SmarTone"},
+{454, 7, "MVNO/China Unicom International Ltd."},
+{454, 8, "MVNO/Trident"},
+{454, 9, "MVNO/China Motion Telecom (HK) Ltd."},
+{455, 0, "Smartone Mobile Communications (Macao) Ltd."},
+{455, 1, "CTM GSM"},
+{455, 3, "Hutchison Telecom"},
+{456, 18, "Camshin (Shinawatra)"},
+{456, 1, "Mobitel (Cam GSM)"},
+{456, 2, "Samart (Casacom)"},
+{456, 3, "S Telecom (CDMA) (reserved)"},
+{457, 1, "Lao Telecommunications"},
+{457, 2, "ETL Mobile"},
+{457, 8, "Millicom"},
+{460, 0, "China Mobile"},
+{460, 1, "China Unicom"},
+{460, 3, "China Unicom CDMA"},
+{460, 4, "China Satellite Global Star Network"},
+{470, 1, "GramenPhone"},
+{470, 2, "Aktel"},
+{470, 3, "Mobile 2000"},
+{472, 1, "DhiMobile"},
+{502, 0, "Art900"},
+{502, 12, "Maxis"},
+{502, 13, "TM Touch"},
+{502, 16, "DIGI"},
+{502, 17, "TimeCel"},
+{502, 18, "MITV Corporation Sdn. Bhd."},
+{502, 19, "CelCom"},
+{505, 11, "Telstra Corporation Ltd."},
+{505, 12, "Hutchison Telecommunications (Australia) Pty. Ltd."},
+{505, 14, "AAPT Ltd."},
+{505, 15, "3GIS Pty Ltd. (Telstra & Hutchison 3G)"},
+{505, 1, "Telstra Corporation Ltd."},
+{505, 24, "Advanced Communications Technologies Pty. Ltd."},
+{505, 2, "Optus Mobile Pty. Ltd."},
+{505, 3, "Vodafone Network Pty. Ltd."},
+{505, 4, "Department of Defence"},
+{505, 5, "The Ozitel Network Pty. Ltd."},
+{505, 6, "Hutchison 3G Australia Pty. Ltd."},
+{505, 71, "Telstra Corporation Ltd."},
+{505, 72, "Telstra Corporation Ltd."},
+{505, 7, "Vodafone Network Pty. Ltd."},
+{505, 88, "Localstar Holding Pty. Ltd."},
+{505, 8, "One.Tel GSM 1800 Pty. Ltd."},
+{505, 90, "Optus Ltd."},
+{505, 99, "One.Tel GSM 1800 Pty. Ltd."},
+{505, 9, "Airnet Commercial Australia Ltd."},
+{510, 0, "PSN"},
+{510, 10, "Telkomsel"},
+{510, 11, "Excelcomindo"},
+{510, 1, "Satelindo"},
+{510, 21, "Indosat - M3"},
+{510, 28, "Komselindo"},
+{510, 8, "Natrindo (Lippo Telecom)"},
+{515, 1, "Islacom"},
+{515, 2, "Globe Telecom"},
+{515, 3, "Smart Communications"},
+{515, 5, "Digitel"},
+{520, 0, "CAT CDMA"},
+{520, 15, "ACT Mobile"},
+{520, 1, "AIS GSM"},
+{525, 12, "Digital Trunked Radio Network"},
+{525, 1, "SingTel ST GSM900"},
+{525, 2, "SingTel ST GSM1800"},
+{525, 3, "MobileOne"},
+{525, 5, "Starhub"},
+{528, 11, "DST Com"},
+{530, 0, "Reserved for AMPS MIN based IMSI's"},
+{530, 1, "Vodafone New Zealand GSM Network"},
+{530, 24, "NZ Communications - UMTS Network"},
+{530, 2, "Teleom New Zealand CDMA Network"},
+{530, 3, "Woosh Wireless - CDMA Network"},
+{530, 4, "TelstraClear - GSM Network"},
+{530, 5, "Telecom New Zealand - UMTS Ntework"},
+{537, 1, "Bmobile"},
+{537, 2, "Greencom"},
+{537, 3, "Digicel Ltd"},
+{539, 1, "Tonga Communications Corporation"},
+{539, 43, "Shoreline Communication"},
+{541, 1, "SMILE"},
+{542, 1, "Vodafone"},
+{546, 1, "OPT Mobilis"},
+{547, 20, "Tikiphone"},
+{548, 1, "Telecom Cook"},
+{549, 1, "Telecom Samoa Cellular Ltd."},
+{549, 27, "GoMobile SamoaTel Ltd"},
+{550, 1, "FSM Telecom"},
+{552, 1, "Palau National Communications Corp. (a.k.a. PNCC)"},
+{602, 1, "EMS - Mobinil"},
+{602, 2, "Vodafone Egypt"},
+{603, 1, "Algrie Telecom"},
+{603, 2, "Orascom Telecom Algrie"},
+{604, 0, "Mditlcom (GSM)"},
+{604, 1, "Ittissalat Al Maghrid"},
+{605, 2, "Tunisie Telecom"},
+{605, 3, "Orascom Telecom"},
+{607, 1, "Gamcel"},
+{607, 2, "Africell"},
+{607, 3, "Comium Services Ltd"},
+{608, 1, "Sonatel"},
+{608, 2, "Sentel GSM"},
+{609, 10, "Mauritel Mobiles"},
+{609, 1, "Mattel S.A."},
+{609, 2, "Chinguitel S.A."},
+{610, 1, "Malitel"},
+{611, 1, "Spacetel"},
+{611, 2, "Sotelgui"},
+{611, 5, "Cellcom Guine SA"},
+{612, 2, "Atlantique Cellulaire"},
+{612, 3, "Orange Cte d'Ivoire"},
+{612, 4, "Comium Cte d'Ivoire"},
+{612, 5, "Loteny Telecom"},
+{612, 6, "Oricel Cte d'Ivoire"},
+{612, 7, "Aircomm Cte d'Ivoire"},
+{613, 2, "Celtel"},
+{613, 3, "Telecel"},
+{614, 1, "Sahel.Com"},
+{614, 2, "Celtel"},
+{614, 3, "Telecel"},
+{615, 1, "Togo Telecom"},
+{616, 1, "Libercom"},
+{616, 2, "Telecel"},
+{616, 3, "Spacetel Benin"},
+{617, 10, "Emtel"},
+{617, 1, "Cellplus"},
+{617, 2, "Mahanagar Telephone (Mauritius) Ltd."},
+{618, 4, "Comium Liberia"},
+{619, 1, "Celtel"},
+{619, 25, "Mobitel"},
+{619, 2, "Millicom"},
+{619, 3, "Africell"},
+{619, 40, "Datatel (SL) Ltd GSM"},
+{619, 4, "Comium (Sierra Leone) Ltd."},
+{619, 50, "Dtatel (SL) Ltd CDMA"},
+{619, 5, "Lintel (Sierra Leone) Ltd."},
+{620, 1, "Spacefon"},
+{620, 2, "Ghana Telecom Mobile"},
+{620, 3, "Mobitel"},
+{620, 4, "Kasapa Telecom Ltd."},
+{621, 20, "Econet Wireless Nigeria Ltd."},
+{621, 30, "MTN Nigeria Communications"},
+{621, 40, "Nigeria Telecommunications Ltd."},
+{622, 1, "Celtel"},
+{622, 2, "Tchad Mobile"},
+{623, 1, "Centrafrique Telecom Plus (CTP)"},
+{623, 2, "Telecel Centrafrique (TC)"},
+{623, 3, "Celca (Socatel)"},
+{624, 1, "Mobile Telephone Networks Cameroon"},
+{624, 2, "Orange Cameroun"},
+{625, 1, "Cabo Verde Telecom"},
+{625, 2, "T+Telecomunicaes"},
+{626, 1, "Companhia Santomese de Telecomunicaes"},
+{627, 1, "Guinea Ecuatorial de Telecomunicaciones Sociedad Annima "},
+{628, 1, "Libertis S.A."},
+{628, 2, "Telecel Gabon S.A."},
+{628, 3, "Celtel Gabon S.A."},
+{629, 10, "Libertis Telecom"},
+{629, 1, "Celtel"},
+{630, 1, "Vodacom Congo RDC sprl"},
+{630, 5, "Supercell Sprl"},
+{630, 86, "Congo-Chine Telecom s.a.r.l."},
+{631, 2, "Unitel"},
+{632, 1, "Guintel S.A."},
+{632, 2, "Spacetel Guin-Bissau S.A."},
+{633, 10, "Telecom (Seychelles) Ltd."},
+{633, 1, "Cable & Wireless (Seychelles) Ltd."},
+{633, 2, "Mediatech International Ltd."},
+{634, 1, "SD Mobitel"},
+{634, 2, "Areeba-Sudan"},
+{635, 10, "MTN Rwandacell"},
+{636, 1, "ETH MTN"},
+{637, 30, "Golis Telecommunications Company"},
+{638, 1, "Evatis"},
+{639, 2, "Safaricom Ltd."},
+{639, 3, "Kencell Communications Ltd."},
+{640, 2, "MIC (T) Ltd."},
+{640, 3, "Zantel"},
+{640, 4, "Vodacom (T) Ltd."},
+{640, 5, "Celtel (T) Ltd."},
+{641, 10, "MTN Uganda Ltd."},
+{641, 11, "Uganda Telecom Ltd."},
+{641, 14, "House of Integrated Technology and Systems Uganda Ltd "},
+{641, 1, "Celtel Uganda"},
+{641, 22, "Warid Telecom Uganda Ltd."},
+{642, 1, "Spacetel Burundi"},
+{642, 2, "Safaris"},
+{642, 3, "Telecel Burundi Company"},
+{643, 1, "T.D.M. GSM"},
+{643, 4, "VM Sarl"},
+{645, 1, "Celtel Zambia Ltd."},
+{645, 2, "Telecel Zambia Ltd."},
+{645, 3, "Zamtel"},
+{646, 1, "MADACOM"},
+{646, 2, "Orange Madagascar"},
+{646, 4, "Telecom Malagasy Mobile"},
+{647, 0, "Orange La Runion"},
+{647, 10, "Socit Runionnaise du Radiotlphone"},
+{647, 2, "Outremer Telecom"},
+{648, 1, "Net One"},
+{648, 3, "Telecel"},
+{648, 4, "Econet"},
+{649, 1, "Mobile Telecommunications Ltd."},
+{649, 3, "Powercom Pty Ltd"},
+{650, 10, "Celtel ltd."},
+{650, 1, "Telekom Network Ltd."},
+{651, 1, "Vodacom Lesotho (pty) Ltd."},
+{651, 2, "Econet Ezin-cel"},
+{652, 1, "Mascom Wireless (Pty) Ltd."},
+{652, 2, "Orange Botswana (Pty) Ltd."},
+{653, 10, "Swazi MTN"},
+{654, 1, "HURI - SNPT"},
+{655, 10, "Mobile Telephone Networks"},
+{655, 11, "SAPS Gauteng"},
+{655, 1, "Vodacom (Pty) Ltd."},
+{655, 21, "Cape Town Metropolitan Council"},
+{655, 30, "Bokamoso Consortium"},
+{655, 31, "Karabo Telecoms (Pty) Ltd."},
+{655, 32, "Ilizwi Telecommunications"},
+{655, 33, "Thinta Thinta Telecommunications"},
+{655, 34, "Bokone Telecoms"},
+{655, 35, "Kingdom Communications"},
+{655, 36, "Amatole Telecommunication Services"},
+{655, 6, "Sentech (Pty) Ltd."},
+{655, 7, "Cell C (Pty) Ltd."},
+{702, 67, "Belize Telecommunications Ltd., GSM 1900"},
+{702, 68, "International Telecommunications Ltd. (INTELCO)"},
+{704, 1, "Servicios de Comunicaciones Personales Inalmbricas, S.A. "},
+{704, 2, "Comunicaciones Celulares S.A."},
+{704, 3, "Telefnica Centroamrica Guatemala S.A."},
+{706, 1, "CTE Telecom Personal, S.A. de C.V."},
+{706, 2, "Digicel, S.A. de C.V."},
+{706, 3, "Telemvil El Salvador, S.A."},
+{708, 1, "Megatel"},
+{708, 2, "Celtel"},
+{710, 21, "Empresa Nicaragense de Telecomunicaciones, S.A. (ENITEL)"},
+{710, 73, "Servicios de Comunicaciones, S.A. (SERCOM)"},
+{712, 1, "Instituto Costarricense de Electricidad - ICE"},
+{714, 1, "Cable & Wireless Panama S.A."},
+{714, 2, "BSC de Panama S.A."},
+{716, 10, "TIM Peru"},
+{722, 10, "Compaia de Radiocomunicaciones Moviles S.A."},
+{722, 20, "Nextel Argentina srl"},
+{722, 310, "CTI PCS S.A."},
+{722, 320, "Compaia de Telefonos del Interior Norte S.A."},
+{722, 330, "Compaia de Telefonos del Interior S.A."},
+{722, 341, "Telecom Personal S.A."},
+{722, 70, "Telefonica Comunicaciones Personales S.A."},
+{724, 0, "Telet"},
+{724, 10, "ATL Algar"},
+{724, 11, "Telems Cel"},
+{724, 12, "Americel"},
+{724, 13, "Telesp Cel"},
+{724, 14, "Maxitel BA"},
+{724, 15, "CTBC Cel"},
+{724, 16, "BSE"},
+{724, 17, "Ceterp Cel"},
+{724, 18, "Norte Brasil Tel"},
+{724, 19, "Telemig Cel"},
+{724, 1, "CRT Cellular"},
+{724, 21, "Telerj Cel"},
+{724, 23, "Telest Cel"},
+{724, 25, "Telebrasilia Cel"},
+{724, 27, "Telegoias Cel"},
+{724, 29, "Telemat Cel"},
+{724, 2, "Global Telecom"},
+{724, 31, "Teleacre Cel"},
+{724, 33, "Teleron Cel"},
+{724, 35, "Telebahia Cel"},
+{724, 37, "Telergipe Cel"},
+{724, 39, "Telasa Cel"},
+{724, 3, "CTMR Cel"},
+{724, 41, "Telpe Cel"},
+{724, 43, "Telepisa Cel"},
+{724, 45, "Telpa Cel"},
+{724, 47, "Telern Cel"},
+{724, 48, "Teleceara Cel"},
+{724, 4, "BCP"},
+{724, 51, "Telma Cel"},
+{724, 53, "Telepara Cel"},
+{724, 55, "Teleamazon Cel"},
+{724, 57, "Teleamapa Cel"},
+{724, 59, "Telaima Cel"},
+{724, 5, "Telesc Cel"},
+{724, 6, "Tess"},
+{724, 7, "Sercontel Cel"},
+{724, 8, "Maxitel MG"},
+{724, 9, "Telepar Cel"},
+{730, 10, "Entel"},
+{730, 1, "Entel Telefonica Movl"},
+{730, 2, "Telefnica Mvil"},
+{730, 3, "Smartcom"},
+{730, 4, "Centennial Cayman Corp. Chile S.A."},
+{730, 5, "Multikom S.A."},
+{732, 1, "Colombia Telecomunicaciones S.A. - Telecom"},
+{732, 2, "Edatel S.A."},
+{732, 101, "Comcel S.A. Occel S.A./Celcaribe"},
+{732, 102, "Bellsouth Colombia S.A."},
+{732, 103, "Colombia Mvil S.A."},
+{732, 111, "Colombia Mvil S.A."},
+{732, 123, "Telfnica Mviles Colombia S.A."},
+{732, 130, "Avantel"},
+{732, 20, "Emtelsa"},
+{732, 99, "Emcali"},
+{734, 1, "Infonet"},
+{734, 2, "Corporacin Digitel"},
+{734, 3, "Digicel"},
+{734, 4, "Telcel, C.A."},
+{734, 6, "Telecomunicaciones Movilnet, C.A."},
+{736, 1, "Nuevatel S.A."},
+{736, 2, "ENTEL S.A."},
+{736, 3, "Telecel S.A."},
+{738, 1, "Cel*Star (Guyana) Inc."},
+{740, 0, "Otecel S.A. - Bellsouth"},
+{740, 1, "Porta GSM"},
+{740, 2, "Telecsa S.A."},
+{744, 1, "Hola Paraguay S.A."},
+{744, 2, "Hutchison Telecom S.A."},
+{744, 3, "Compaia Privada de Comunicaciones S.A."},
+{746, 2, "Telesur"},
+{746, 3, "Digicel"},
+{746, 4, "Intelsur"},
+{748, 0, "Ancel - TDMA"},
+{748, 10, "CTI Mvil"},
+{748, 1, "Ancel - GSM"},
+{748, 3, "Ancel"},
+{748, 7, "Movistar"},
+{901, 10, "Asia Cellular Satellite (AceS)"},
+{901, 11, "Inmarsat Ltd."},
+{901, 12, "Maritime Communications Partner AS (MCP network)"},
+{901, 13, "Global Networks, Inc."},
+{901, 14, "Telenor GSM - services in aircraft"},
+{901, 15, "SITA GSM services in aircraft (On Air)"},
+{901, 16, "Jasper Systems, Inc."},
+{901, 17, "Jersey Telecom"},
+{901, 18, "Cingular Wireless"},
+{901, 19, "Vodaphone Malta"},
+{901, 1, "ICO Global Communications"},
+{901, 20, "Intermatica"},
+{901, 21, "Seanet Maritime Communications"},
+{901, 22, "Denver Consultants Ltd"},
+{901, 2, "Sense Communications International AS"},
+{901, 3, "Iridium Satellite, LLC (GMSS)"},
+{901, 4, "Globalstar"},
+{901, 5, "Thuraya RMSS Network"},
+{901, 6, "Thuraya Satellite Telecommunications Company"},
+{901, 7, "Ellipso"},
+{901, 88, "Telecommunications for Disaster Relief (TDR) (OCHA)"},
+{901, 9, "Tele1 Europe"},
+{-1, -1, NULL}
+};
+
+/*
+ * Return Mobile Country Code string by code.
+ * Return NULL if not exists.
+ */
+const char *
+mcc_get(int mcc)
+{
+ int i = 0;
+
+ for (i = 0; i < sizeof mcc_list / sizeof *mcc_list; i++)
+ {
+ if (mcc_list[i].mcc == mcc)
+ return mcc_list[i].data;
+ }
+
+ return NULL;
+}
+
+const char *
+mnc_get(int mcc, int mnc)
+{
+ int i = 0;
+
+ for (i = 0; i < sizeof mnc_list / sizeof *mnc_list; i++)
+ {
+ if (mnc_list[i].mcc != mcc)
+ continue;
+ for (; mnc_list[i].mcc == mcc; i++)
+ {
+ if (mnc_list[i].mnc == mnc)
+ return mnc_list[i].data;
+ }
+
+ break;
+ }
+
+ return NULL;
+}
+
diff --git a/gsmdecode/src/mcc_list.h b/gsmdecode/src/mcc_list.h
new file mode 100644
index 0000000..ad8c54f
--- /dev/null
+++ b/gsmdecode/src/mcc_list.h
@@ -0,0 +1,5 @@
+
+
+const char *mcc_get(int mcc);
+const char *mnc_get(int mcc, int mnc);
+
personal git repositories of Harald Welte. Your mileage may vary