diff options
Diffstat (limited to 'gsmdecode')
-rw-r--r-- | gsmdecode/INSTALL | 11 | ||||
-rw-r--r-- | gsmdecode/Makefile.am | 6 | ||||
-rwxr-xr-x | gsmdecode/bootstrap | 45 | ||||
-rw-r--r-- | gsmdecode/configure.in | 84 | ||||
-rw-r--r-- | gsmdecode/src/Makefile.am | 3 | ||||
-rw-r--r-- | gsmdecode/src/common.c | 86 | ||||
-rw-r--r-- | gsmdecode/src/common.h | 50 | ||||
-rw-r--r-- | gsmdecode/src/data_out.c | 3867 | ||||
-rw-r--r-- | gsmdecode/src/data_out.h | 5 | ||||
-rw-r--r-- | gsmdecode/src/gsm_desc.h | 262 | ||||
-rw-r--r-- | gsmdecode/src/gsmdecode.c | 289 | ||||
-rw-r--r-- | gsmdecode/src/id_list.c | 19 | ||||
-rw-r--r-- | gsmdecode/src/id_list.h | 15 | ||||
-rw-r--r-- | gsmdecode/src/mcc_list.c | 1433 | ||||
-rw-r--r-- | gsmdecode/src/mcc_list.h | 5 |
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); + |