From 956203ad8df7b68af83ae94f7793a028c74113ee Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 25 Nov 2008 11:11:49 +0530 Subject: Initial import of gsmsp-0.2a --- gsmsp/gsm/src/lib/data_out.c | 2289 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2289 insertions(+) create mode 100644 gsmsp/gsm/src/lib/data_out.c (limited to 'gsmsp/gsm/src/lib/data_out.c') diff --git a/gsmsp/gsm/src/lib/data_out.c b/gsmsp/gsm/src/lib/data_out.c new file mode 100644 index 0000000..b74b886 --- /dev/null +++ b/gsmsp/gsm/src/lib/data_out.c @@ -0,0 +1,2289 @@ +#include "common.h" +#include +#include +#include +#include "id_list.h" +#include "gsm_desc.h" + +#define OUTF(a...) do { \ + printf(" %3d: %02x ", (int)(data - start), data[0]); \ + printf(a); \ +} while (0) + +#define OUT(a...) do { \ + printf(a); \ +} while (0) + +#define RETTRUNK() do { \ + printf("%s:%d TRUNKATED (0x%p - 0x%p)\n", __func__, __LINE__, data, end); \ + return; \ +} while (0) + +static void l2_rrm(); +static void l2_sms(); +static void l2_cc(); +static void l2_RRsystemInfo1(); +static void l2_MccMncLac(); +static void l2_RRsystemInfo2(); +//static void l2_RRsystemInfo2ter(); +static void l2_RRsystemInfo3C(); +static void l2_RRsystemInfo4C(); +static void l2_RRsystemInfo6(); +static void l2_RRsystemInfo13C(); +static void l2_RRimmediateAssTBFC(); +static void l2_RRassignCommand(); +static void l2_RRassignComplete(); +static void l2_RRpagingrequest1(); +static void l2_RRpagingrequest2(); +static void l2_RRpagingrequest3(); +static void l2_RRimmediateAssignment(); +static void l2_RRimmAssTBFDirEncHoChaC(); +static void l2_MobId(); +static void l2_mmm(); +static void l2_HoppingChannel(); +static void l2_SingleChannel(); +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_ChannelNeeded(char *str, unsigned char ch); +static void l2_MNCC(const char *str, unsigned char a, unsigned char b, unsigned char c); + +static char *BitRow(unsigned char c, int pos); +static char *PageMode(unsigned char mode); +static char *BitRowFill(unsigned char c, unsigned char mask); + +static void dcch_address(); +static void dcch_control(); +static void ControlChannelDescription(); +static void CellOptionsBcch(); +static void CellSelectionParameters(); +static void RequestReference(); +static void TimingAdvance(); +static void StartingTime(); +static void l2_NeighbourCellDescription(); +static void CellIdentity(); +static void MSClassMarkTwo(); +static void cpData(); +static void Address(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 AuthenticationRequest(); +static void AuthenticationResponse(); + +static const unsigned char *start; +static const unsigned char *data; +static const unsigned char *end; + +/* + * B-format (and also A-Format) + */ +void +l2_data_out_B(int fn, const unsigned char *input_data, int len) +{ + data = input_data; + start = data; + end = data + len; + HEXDUMPF(data, 23 /*len*/, "Format B DATA\n"); + /* Need at least 3 octets */ + if (data + 2 >= end) + RETTRUNK(); + + 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'); + OUTF("%s Length: %u\n", BitRowFill(data[0], 0xfc), data[0] >> 2); + if (data + (data[0] >> 2) < end) + end = data + (data[0] >> 2) + 1; + data++; + if (data >= end) + return; + 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); + 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 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 achknowledgement)\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 */ + switch ((data[0] >> 2) & 0x07) + { + case 0x03: + 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: + 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; + + + if (len <= 0) + return; + + data = input_data; + start = data; + + 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() +{ + 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 messages [FIXME]\n"); + /* GSM 04.80 */ + break; + case 0x0c: + OUTF("----1100 Location services [FIXME]\n"); + break; + case 0x0d: + OUTF("----1101 RFU [FIXME]\n"); + break; + case 0x0e: + OUTF("----1110 Extension of the PD to one octet length [FIXME]\n"); + break; + case 0x0f: + OUTF("----1111 Tests procedures describe in TS GSM 11.10 [FIXME]\n"); + break; + default: + OUTF("%s 0x%02x UNKNOWN\n", BitRowFill(data[0], 0x0f), data[0] & 0x0f); + } + +} + +/* + * Broadcast Call Control (04.69) + */ +static void +l2_bcc() +{ + if (data >= end) + RETTRUNK(); + + /* Message type 04.69:9.3*/ + switch (data[0] & 0x3f) + { + case 0x06: /* 0-000110 */ + OUTF("--000110 ???\n"); + break; + default: + OUTF("--?????? UNKNOWN [FIXME]\n"); + return; + } + + /* Call reference 04.69:9.4.1*/ + + /* Orig indication 04.69:9.5.5*/ + /* Spare half octet 04.69:9.4.5*/ + +} + +/* + * ProtDisc3 + */ +static void +l2_cc() +{ + if (data >= end) + RETTRUNK(); + OUTF("%s Send Sequence Number: %u\n", BitRowFill(data[0], 0xc0), data[0] >> 6); + + if ((data[0] & 0x3f) == 0x01) + { + OUTF("--000001 Call Alerting\n"); + data++; + CCalerting(); + } else if ((data[0] & 0x3f) == 0x02) { + OUTF("--000010 Call Proceesing\n"); + if (++data >= end) + return; + OUTF("FIXME %s\n", __func__); + } else if ((data[0] & 0x3f) == 0x07) { + OUTF("--000111 Call Connect\n"); + if (++data >= end) + return; + OUTF("FIXME %s\n", __func__); + } else if ((data[0] & 0x3f) == 0x08) { + OUTF("--001000 Call Confirmed\n"); + if (++data >= end) + return; + if (data[0] != 0x04) + return; + OUTF("--000010 Bearer Capability\n"); + data++; + BearerCap(); + } else if ((data[0] & 0x3f) == 0x05) { + OUTF("--000101 Call Setup\n"); + data++; + CCsetup(); + } else if ((data[0] & 0x3f) == 0x03) { + OUTF("--000011 Call Progress\n"); + data++; + ProgressIndicator(); + } else if ((data[0] & 0x3f) == 0x0f) { + OUTF("--001111 Connect Acknowledge\n"); + } else if ((data[0] & 0x3f) == 0x25) { + OUTF("--100101 Disconnect\n"); + data++; + Cause(); + } else if ((data[0] & 0x3f) == 0x2d) { + OUTF("--101101 CC Release\n"); + if (++data >= end) + RETTRUNK(); + if (data[0] == 0x08) + { + data++; + Cause(); + } + } else if ((data[0] & 0x3f) == 0x2a) { + OUTF("--101010 CC Release Complete\n"); + if (++data >= end) + RETTRUNK(); + if (data[0] == 0x08) + { + data++; + Cause(); + } + if (data >= end) + RETTRUNK(); + if (data[0] == 0x1c) + { + /* facility */ + OUTF("FIXME\n"); + } + } else { + OUTF("%s FIXME %s\n", BitRowFill(data[0], 0xff), __func__); + } +} + +/* + * ----0101 + * ProtDisc5 - Mobile Management message (non GPRS) + */ +static void +l2_mmm() +{ + if (data >= end) + return; + OUTF("%s SendSequenceNumber: %d\n", BitRowFill(data[0], 0xc0), data[0] >> 6); + switch (data[0] & 0x3f) + { + case 1: + //l2_MMimsiDetIndication(data + 1, end); + OUTF("--000001 Imsi Det Indication\n"); /* FIXME */ + OUTF("FIXME: Possible IMSI in here\n"); + OUTF("FIXME: Possible cipher mode here\n"); + break; + case 2: + OUTF("--000010 Location Update Accept\n"); /* FIXME */ + break; + case 4: + OUTF("--000100 Message Type: Locatoin Updating Reject\n"); + break; + case 8: + OUTF("--001000 MM Location Update Request\n"); /* FIXME */ + OUTF("FIXME: Possible IMSI in here\n"); + OUTF("FIXME: Possible cipher mode here\n"); + break; + case 0x12: + OUTF("--010010 Authentication Request\n"); + data++; + AuthenticationRequest(); + break; + case 0x14: + OUTF("--010100 Authentication Response\n"); + data++; + AuthenticationResponse(); + break; + case 0x19: + OUTF("--011001 MMidentityResponse\n"); + OUTF("FIXME: Possible IMSI in here\n"); + break; + case 0x1a: + OUTF("--011010 TMSI Realloc Command\n"); + data++; + l2_TmsiReallocCommand(); + break; + case 0x24: /* --100100 */ + OUTF("--100100 MMcmServiceRequest\n"); + data++; + l2_MMcmServiceRequest(); + /* in multisupport2 and others! */ + break; + default: + OUTF("UNKNWON\n"); + } +} + +/* + * ProtDisc6 - Radio Resource Management Messages + */ +static void +l2_rrm() +{ + if (data >= end) + return; + + switch (data[0] & 0x3f) + { + case 0x00: + OUTF("00000000 System Information Type 13\n"); + data++; + l2_RRsystemInfo13C(); + break; + case 0x06: + OUTF("00000110 System Information Type 5ter\n"); + data++; + l2_BcchAllocation(); + break; + case 0x0d: + OUTF("00001101 Channel Release\n"); + data++; + l2_ChannelRelease(); + break; + case 0x15: + OUTF("00010101 RR Measurement Report C [FIXME]\n"); + break; + case 0x16: + OUTF("00010110 RRclassmarkChange\n"); + data++; + l2_RRclassmarkChange(); + break; + case 0x19: + OUTF("00011001 RRsystemInfo1\n"); + data++; + l2_RRsystemInfo1(); + break; + case 0x1a: + OUTF("00011010 RRsystemInfo2\n"); + data++; + l2_RRsystemInfo2(); + break; + case 0x1B: /* 0001 1011 */ + OUTF("00011011 RRsystemInfo3C\n"); + data++; + l2_RRsystemInfo3C(); + break; + case 0x1c: + OUTF("00011100 RRsystemInfo4-C\n"); + data++; + l2_RRsystemInfo4C(); + break; + case 0x1d: + /* From SDCCH */ + OUTF("00011101 Neighbour Cells Description\n"); + data++; + l2_NeighbourCellDescription(); + break; + case 0x1e: + /* From SDCCH */ + OUTF("00011110 System Information Type 6\n"); + data++; + l2_RRsystemInfo6(); + break; + case 0x21: + OUTF("00100001 Paging Request Type 1\n"); + data++; + l2_RRpagingrequest1(); + break; + case 0x22: + OUTF("00100010 Paging Request Type 2\n"); + data++; + l2_RRpagingrequest2(); + break; + case 0x24: + OUTF("00100100 Paging Request Type 3\n"); + data++; + l2_RRpagingrequest3(); + break; + case 0x27: + OUTF("0-100111 RRpagingResponse\n"); + OUTF("-x------ Send sequence number: %d\n", (data[0] >> 7) & 0x01); + data++; + l2_RRpagingresponse(); + break; + case 0x29: + OUTF("0-101001 RR Assign Complete\n"); + data++; + l2_RRassignComplete(); + break; + case 0x2e: + OUTF("00101110 RR Assign Command\n"); + data++; + l2_RRassignCommand(); + break; + case 0x32: + OUTF("00110010 RR Cipher Mode Complete\n"); + data++; + l2_RRciphModCompl(); + break; + case 0x35: + OUTF("00110101 RR Cipher Mode Command\n"); + data++; + l2_RRciphModCmd(); + break; + case 0x3f: + OUTF("0-111111 RRimmediateAssignment\n"); + OUTF("-x------ Send sequence number: %d\n", (data[0] >> 7) & 0x01); + data++; + l2_RRimmediateAssignment(); + break; + default: + OUTF("???????? UNKNOWN. FIXME\n"); + } +} +static void +l2_RRsystemInfo13C() +{ + if (data >= end); + return; + if (data[0] >> 7) + OUTF("1------- SI 13 Restoctet present\n"); + else + OUTF("0------- SI 13 Restoctet NOT present\n"); + OUTF("%s BCCH_CHANGE_MARK : %d\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07); + switch (data[0] & 0x0f) + { + case 0x00: + OUTF("----0000 SI_CHANGE_FIELD : Update of unspecified SI messages\n"); + break; + case 0x01: + OUTF("----00001 SI_CHANGE_FIELD : Update of unspecified SI1 messages\n"); + break; + case 0x02: + OUTF("----0010 SI_CHANGE_FIELD : Update of unspecified SI2 messages\n"); + break; + case 0x03: + OUTF("----0011 SI_CHANGE_FIELD : Update of unspecified SI3,4,7,8 messages\n"); + break; + case 0x04: + OUTF("----0100 SI_CHANGE_FIELD : Update of unspecified SI9 messages\n"); + break; + default: + OUTF("----???? Unknown %d\n", data[0] & 0x0f); + break; + } + OUTF("FIXME: implement me\n"); + +} + +static void +l2_RRimmediateAssignment() +{ + if (data >= end) + return; + + /* Octect 4, 0x79 */ + OUTF("%s\n", PageMode(data[0] & 0x03)); + + if ((data[0] >> 6) & 0x01) + OUTF("-1------ Two messages assign.: 1. message of..(continue)\n"); + else + OUTF("-0------ No meaning\n"); + if ((data[0] >> 5) & 0x01) + OUTF("--1----- Assigns a resource identified in the IA rest octets.\n"); + else + OUTF("--0----- Downlink assig to MS: No meaning\n"); + if ((data[0] >> 4) & 0x01) + { + OUTF("---1---- Temporary Block Flow (TBF)\n"); + data++; + l2_RRimmediateAssTBFC(); + return; + } + else + OUTF("---0---- This messages assigns a dedicated mode resource\n"); + data++; + if (data >= end) + return; + + /* Channel Description */ + ChannelDescriptionTwo(); + + if (data >= end) + return; + if (((data[0] >> 2) & 0x07) == 0) + l2_SingleChannel(); + else if (((data[0] >> 4) & 0x01) == 1) + { + l2_HoppingChannel(); + } else { + OUTF("xxx0??xxx UNKNOWN %d\n", (data[0] >> 3) & 0x3); + } +} + +static void +l2_SingleChannel() +{ + int freq; + OUTF("%s Training seq. code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5); + OUTF("---000-- Single channel\n"); + freq = (data[0] & 0x03) << 8; + data++; + if (data >= end) + RETTRUNK(); + freq |= data[0]; + OUTF("........ Absolute RF channel number: %u\n", freq); + data++; + RequestReference(); + TimingAdvance(); + l2_MobileAllocation(); + if (data >= end) + return; +} + +static void +l2_HoppingChannel() +{ + unsigned char maio = 0; + OUTF("%s Training seq. code : %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5); + OUTF("---1---- HoppingChannel\n"); + maio = (data[0] & 0x0f) << 2; + data++; + if (data >= end) + RETTRUNK(); + maio |= (data[0] >> 6); + OUTF("........ MAIO %d\n", maio); + OUTF("%s Hopping Seq. Number: %d\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f); + + data++; + RequestReference(); + TimingAdvance(); + l2_MobileAllocation(); + if (data >= end) + return; /* finished. not truncated! */ + + OUTF("FIXME, more data left here???\n"); +} + +static void +l2_MobileAllocation() +{ + int c = 64, pos; + char *str = "Mobile allocation RF chann."; + const unsigned char *thisend; + + if (data >= end) + RETTRUNK(); + OUTF("%s Length of Mobile Allocation: %d\n", BitRowFill(data[0], 0xff), data[0]); + thisend = data + data[0] + 1; + if (thisend > end) + { + OUTF("xxxxxxxx ERROR: Packet to short or length to long\n"); + thisend = end; + } + + data++; + /* If mobile allocation has length 0 */ + if (data >= thisend) + return; + + while (data < thisend) + { + pos = 7; + while (pos >= 0) + { + if ((data[0] >> pos) & 1) + OUTF("%s %s%d\n", BitRow(data[0], pos), str, c - (7 - pos)); + pos--; + + } + + c -= 8; + data++; + if (c <= 0) + break; + } +} + +/* + * From RRsystemInfo2 + */ +static void +l2_BcchAllocation() +{ + int c, pos; + char *str = "BCCH alloc. RF chan.: "; + +#if 0 + /* goeller script for Info2 outputs channels 128 + 127 + * but opengpa outputs bitmap format for info2. + * We do what opengpa does. (correct?) + */ + if ((data[0] >> 7)) + OUTF("1------- %s%d\n", str, 128); + if ((data[0] >> 6) & 1) + OUTF("-1------ %s%d\n", str, 127); +#endif + if ((data[0] >> 6) == 0x00) + OUTF("00------ Bitmap format: 0\n"); + else { + OUTF("%s Bitmap format: UNKNOWN [FIXME]\n", BitRowFill(data[0], 0xc0)); + RETTRUNK(); + } + + if ((data[0] & 0x8e) == 0x8e) + { + /* From System Information Type 5ter */ + OUTF("1---111- Variable Bitmap SI5ter [FIXME]\n"); + return; + } + + if ((data[0] >> 5) & 1) + OUTF("--1----- Extension Indicator: The IE carries only a part of the BA\n"); + else + OUTF("--0----- Extension Indicator: The IE carries the complete BA\n"); + OUTF("---x---- BCCH alloc. seq. num: %d\n", (data[0] >> 4) & 1); + if ((data[0] >> 3) & 1) + OUTF("----1--- %s%d\n", str, 124); + if ((data[0] >> 2) & 1) + OUTF("-----1-- %s%d\n", str, 123); + if ((data[0] >> 1) & 1) + OUTF("------1- %s%d\n", str, 122); + if (data[0] & 1) + OUTF("-------1 %s%d\n", str, 121); + + data++; + c = 120; + while (data < end) + { + pos = 7; + while (pos >= 0) + { + if ((data[0] >> pos) & 1) + OUTF("%s %s%d\n", BitRow(data[0], pos), str, c - (7 - pos)); + pos--; + + } + + c -= 8; + data++; + if (c <= 0) + break; + } +} + +static void +l2_RRimmediateAssTBFC() +{ + if (data >= end) + return; + + /* GPRS Packet Channel Description */ + OUTF("%s Channel Type : %d\n", BitRowFill(data[0], 0xf8), data[0] >> 3); + OUTF("%s Time Slot Number : %d\n", BitRowFill(data[0], 0x07), data[0] & 0x07); + data++; + if (data >= end) + return; + + OUTF("%s Tranining Sequence Code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5); + if ((data[0] >> 4) & 0x01) + { + OUTF("---1---- Direct Encoding of Hopping Channels\n"); + l2_RRimmAssTBFDirEncHoChaC(); + return; + } else { + OUTF("---0---- non-hopping RF channel config or indirect encoding of hopping RFCC\n"); + } + + if ((data[0] >> 3) & 0x01) + { + OUTF("----1--- indirect encoding of hopping RF channel config\n"); + } else { + OUTF("----0--- RRimmAssTBFaRFCN-C FIXME\n"); + return; + } + + data++; + if (data >= end) + RETTRUNK(); + OUTF("xxxxxxxx MAIO [FIXME]\n"); + + data++; + RequestReference(); + TimingAdvance(); + l2_MobileAllocation(); + if (data >= end) + RETTRUNK(); + OUTF("FIXME: implenet\n"); +} + +static void +l2_RRsystemInfo1() +{ + int ca; + + if (data + 1 >= end) + return; + switch (data[0] >> 6) + { + case 0x00: + OUTF("00------ Bitmap 0 format\n"); + break; + case 0x01: + OUTF("10------ Bitmap format: (FIXME)\n"); + break; + default: + OUTF("%s Bitmap %d format (FIXME)\n", BitRowFill(data[0], 0xc0), data[0] >> 6); + } + if ((data[0] >> 3) & 1) + OUTF("----1--- Cell Allocation : ARFCN 124\n"); + if ((data[0] >> 2) & 1) + OUTF("-----1-- Cell Allocation : ARFCN 123\n"); + if ((data[0] >> 1) & 1) + OUTF("------1- Cell Allocation : ARFCN 122\n"); + if (data[0] & 1) + OUTF("-------1 Cell Allocation : ARFCN 121\n"); + + ca = 120; + while (ca > 0) + { + data++; + if (data >= end) + return; + if ((data[0] >> 7) & 1) + OUTF("1------- Cell Allocation : ARFCN %d\n", ca); + if ((data[0] >> 6) & 1) + OUTF("-1------ Cell Allocation : ARFCN %d\n", ca - 1); + if ((data[0] >> 5) & 1) + OUTF("--1----- Cell Allocation : ARFCN %d\n", ca - 2); + if ((data[0] >> 4) & 1) + OUTF("---1---- Cell Allocation : ARFCN %d\n", ca - 3); + if ((data[0] >> 3) & 1) + OUTF("----1--- Cell Allocation : ARFCN %d\n", ca - 4); + if ((data[0] >> 2) & 1) + OUTF("-----1-- Cell Allocation : ARFCN %d\n", ca - 5); + if ((data[0] >> 1) & 1) + OUTF("------1- Cell Allocation : ARFCN %d\n", ca - 6); + if (data[0] & 1) + OUTF("-------1 Cell Allocation : ARFCN %d\n", ca - 7); + + ca -= 8; + } + + data++; + + l2_RachControlParameters(); + OUTF("FIXME: NCH Position\n"); + if (data >= end) + return; +} + +static void +l2_RachControlParameters() +{ + int ca = -1; + + if (data >= end) + return; + + if (((data[0] >> 6) & 0x03) == 0) + ca = 1; + else if (((data[0] >> 6) & 0x03) == 0x01) + ca = 2; + else if (((data[0] >> 6) & 0x03) == 0x02) + ca = 4; + else if (((data[0] >> 6) & 0x03) == 0x03) + ca = 7; + OUTF("%s Max. of retransmiss : %u\n", BitRowFill(data[0], 0xc0), ca); + if (((data[0] >> 2) & 0x0f) <= 9) + { + ca = ((data[0] >> 2) & 0x0f) + 3; + } else { + switch ((data[0] >> 2) & 0x0f) + { + case 10: /* --1010-- */ + ca = 14; + break; + case 11: + ca = 16; + break; + case 12: + ca = 20; + break; + case 13: + ca = 25; + break; + case 14: + ca = 32; + break; + case 15: + ca = 50; + break; + default: + ca = -1; + break; + } + } + OUTF("%s slots to spread TX : %u\n", BitRowFill(data[0], 0x3c), ca); + switch ((data[0] >> 1) & 0x01) + { + case 0: + OUTF("------0- The cell is barred : no\n"); + break; + case 1: + OUTF("------1- The cell is barred : yes\n"); + break; + } + + switch (data[0] & 0x01) + { + case 0: + OUTF("-------0 Call reestabl.i.cell: allowed\n"); + break; + case 1: + OUTF("-------1 Cell reestabl.i.cell: not allowed\n"); + } + + data++; + if (data >= end) + return; + switch ((data[0] >> 2) & 0x01) + { + case 0: + OUTF("-----0-- Emergency call EC 10: allowed\n"); + break; + case 1: + OUTF("-----1-- Emergency call EC 10: not allowed\n"); + break; + } + OUTF("%s Acc ctrl cl 11-15: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0xf8)); + OUTF("%s Acc ctrl cl 8- 9: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0x03)); + OUTF("%s Ordinary subscribers (8)\n", BitRowFill(data[0], 0x01)); + OUTF("%s Ordinary subscribers (9)\n", BitRowFill(data[0], 0x02)); + OUTF("%s Emergency call (10): %s\n", BitRowFill(data[0], 0x04), ((data[0] >> 4) & 1)?"Class 11-15 only":"Everyone"); + OUTF("%s Operator Specific (11)\n", BitRowFill(data[0], 0x08)); + OUTF("%s Security service (12)\n", BitRowFill(data[0], 0x10)); + OUTF("%s Public service (13)\n", BitRowFill(data[0], 0x20)); + OUTF("%s Emergency service (14)\n", BitRowFill(data[0], 0x40)); + OUTF("%s Network Operator (15)\n", BitRowFill(data[0], 0x80)); + data++; + if (data >= end) + RETTRUNK(); + OUTF("%s Acc ctrl cl 0- 7: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0xff)); + OUTF("%s Ordinary subscribers (0-7)\n", BitRowFill(data[0], 0xff)); + data++; +} + +static char * +BitRow(unsigned char c, int pos) +{ + unsigned char bit = 0; + static char buf[9]; + + if ((c >> pos) & 1) + bit = 1; + + if (pos == 0) + snprintf(buf, sizeof buf, "-------%d", bit); + else if (pos == 1) + snprintf(buf, sizeof buf, "------%d-", bit); + else if (pos == 2) + snprintf(buf, sizeof buf, "-----%d--", bit); + else if (pos == 3) + snprintf(buf, sizeof buf, "----%d---", bit); + else if (pos == 4) + snprintf(buf, sizeof buf, "---%d----", bit); + else if (pos == 5) + snprintf(buf, sizeof buf, "--%d-----", bit); + else if (pos == 6) + snprintf(buf, sizeof buf, "-%d------", bit); + else if (pos == 7) + snprintf(buf, sizeof buf, "%d-------", bit); + + return buf; +} + +static char * +BitRowFill(unsigned char c, unsigned char mask) +{ + static char buf[9]; + + memset(buf, '-', sizeof buf); + buf[sizeof buf - 1] = '\0'; + int i = 0; + while (i < 8) + { + if ((mask >> i) & 1) + { + if ((c >> i) & 1) + buf[7 - i] = '1'; + else + buf[7 - i] = '0'; + } + i++; + } + + return buf; +} + +static void +l2_RRsystemInfo2() +{ + if (data >= end) + RETTRUNK(); + + l2_BcchAllocation(); + if (data >= end) + RETTRUNK(); + + int c = 7; + while (c >= 0) + { + if ((data[0] >> c) & 1) + OUTF("%s BCCH carrier with NCC = %d is permitted for monitoring\n", BitRow(data[0], c), c); + c--; + } + data++; + if (data >= end) + RETTRUNK(); + + l2_RachControlParameters(); + + if (data > end) /* Note: not >= */ + RETTRUNK(); +} + +#if 0 +static void +l2_RRsystemInfo2ter() +{ + if (data >= end) + return; + if ((data[0] >> 7) == 0) + OUTF("%s Bitmap 0 format\n", BitRowFill(data[0], 0x8e)); + else { + /* 0x8e = 10001110 */ + if (((data[0] >> 1) & 0x07) == 0x04) + OUTF("1---100- 1024 range\nFIXME\n"); + else if (((data[0] >> 1) & 0x07) == 0x05) + OUTF("1---101- 512 range\nFIXME\n"); + else if (((data[0] >> 1) & 0x07) == 0x06) + OUTF("1---110- 128 range\nFIXME\n"); + else if (((data[0] >> 1) & 0x07) == 0x07) + OUTF("1---111- variable Bitmap\nFIXME\n"); + else + OUTF("1---xxx- UNKNOWN 0x%08x\n", data[0]); + } + OUTF("FIXME\n"); +} +#endif + + +/* + * RRsystemInfo4-C + */ +static void +l2_RRsystemInfo4C() +{ + if (data + 2 >= end) + RETTRUNK(); + l2_MccMncLac(); + CellSelectionParameters(); + l2_RachControlParameters(); + if (data >= end) + RETTRUNK(); + OUTF("FIXME\n"); +} + +/* + * Output MCC, MNC and LAC. consume 5 bytes. + */ +static void +l2_MccMncLac() +{ + if (data + 2 >= end) + return; + unsigned short lac; + + l2_MNCC("Mobile Country Code", data[0] & 0x0f, (data[0] >> 4) & 0x0f, data[1] & 0x0f); + data++; + l2_MNCC("Mobile Network Code", data[1] & 0x0f, (data[1] >> 4) & 0x0f, (data[0] >> 4) & 0x0f); + data += 2; + + if (data + 1 >= end) + return; + + lac = data[0]; + lac = (lac << 8) | data[1]; + OUTF("%-8u [0x%02x%02x] Local Area Code\n", lac, data[0], data[1]); + data += 2; +} +/* + * RRsystemINfo3-C + */ +static void +l2_RRsystemInfo3C() +{ + CellIdentity(); + l2_MccMncLac(); + + ControlChannelDescription(); + CellOptionsBcch(); + CellSelectionParameters(); + l2_RachControlParameters(); + + /* FIXME: complete here */ +} + +static void +l2_RRsystemInfo6() +{ + CellIdentity(); + l2_MccMncLac(); + CellOptionsBcch(); + if (data >= end) + RETTRUNK(); + OUTF("%s Network Colour Code: %u\n", BitRowFill(data[0], 0xff), data[0]); +} + +static void +CellIdentity() +{ + unsigned short id; + + if (data + 1 >= end) + return; + + id = data[0]; + id = (id << 8) | data[1]; + OUTF("%-8u [0x%02x%02x] Cell identity\n", id, data[0], data[1]); + data += 2; +} + +static void +ControlChannelDescription() +{ + if (data >= end) + RETTRUNK(); + OUTF("%s Spare bit (should be 0)\n", BitRow(data[0], 7)); + if ((data[0] >> 6) & 1) + OUTF("-1------ MSs in the cell shall apply IMSI attach/detach procedure\n"); + else + OUTF("-0------ MSs in cell are not allowed attach/detach procedure\n"); + OUTF("%s Number of blocks: %u\n", BitRowFill(data[0], 0x38), (data[0] >> 3) & 0x07); + + switch (data[0] & 0x07) + { + case 0x00: + OUTF("-----000 1 basic physical channel for CCCH, not combined with SDCCHs\n"); + break; + case 0x01: + OUTF("-----001 1 basic physical channel for CCCH, combined with SDCCHs\n"); + break; + case 0x02: + OUTF("-----010 2 basic physical channel for CCCH, not combined with SDCCHs\n"); + break; + case 0x04: + OUTF("-----100 3 basic physical channel for CCCH, not combined with SDCCHs\n"); + break; + case 0x06: + OUTF("-----110 4 basic physical channel for CCCH, not combined with SDCCHs\n"); + break; + default: + OUTF("%s Unknown CCCH config (ERROR)\n", BitRowFill(data[0], 0x07)); + break; + } + + data++; + if (data >= end) + RETTRUNK(); + + OUTF("%s spare bits (should be 0)\n", BitRowFill(data[0], 0xf8)); + OUTF("%s %u multi frames period for paging request\n", BitRowFill(data[0], 0x07), (data[0] & 0x07) + 2); + + data++; + if (data >= end) + RETTRUNK(); + OUTF("%s T3212 TimeOut value: %u\n", BitRowFill(data[0], 0xff), data[0]); + data++; +} + +static void +CellOptionsBcch() +{ + if (data >= end) + RETTRUNK(); + OUTF("%s spare bit (should be 0)\n", BitRowFill(data[0], 0x80)); + if ((data[0] >> 6) & 1) + OUTF("-1------ Power control indicator is set\n"); + else + OUTF("-0------ Power control indicator is not set\n"); + + if (((data[0] >> 4) & 0x03) == 0x00) + OUTF("--00---- MSs may use uplink DTX\n"); + else if (((data[0] >> 4) & 0x03) == 0x01) + OUTF("--01---- MSs shall use uplink DTX\n"); + else if (((data[0] >> 4) & 0x03) == 0x02) + OUTF("--10---- MSs shall not use uplink DTX\n"); + else + OUTF("%s DTX UNKNOWN [ERROR]\n", BitRowFill(data[0], 0x30)); + + OUTF("%s Radio Link Timeout: %u\n", BitRowFill(data[0], 0x0f), ((data[0] & 0x0f) + 1 ) * 4); + data++; +} + +static void +l2_MNCC(const char *str, unsigned char a, unsigned char b, unsigned char c) +{ + char buf[128]; + char f[12]; + + snprintf(f, sizeof f, "%x%x%x", a, b, c); + /* Nokia netmonitor shows NC's like '30F' and '10F' */ + snprintf(buf, sizeof buf, "%-8s %s\n", f, str); + +#if 0 + buf[0] = '\0'; + if (a != 0x0f) + { + snprintf(buf, sizeof buf, "%x", a); + if (b != 0x0f) + { + snprintf(buf + 1, sizeof buf - 1, "%x", b); + if (c != 0x0f) + snprintf(buf + 2, sizeof buf - 2, "%x", c); + } + } + snprintf(buf + strlen(buf), sizeof buf - strlen(buf), " - %s\n", str); +#endif + + OUTF(buf); +} + +static char * +PageMode(unsigned char mode) +{ + switch (mode) + { + case 0: + return "------00 Page Mode: Normal paging"; + case 1: + return "------01 Page Mode: Extended paging"; + case 2: + return "------10 Page Mode: Paging reorganisation"; + case 3: + return "------11 Page Mode: reserved / same as before"; + } + + return "------?? UNKNOWN\n"; +} + +static void +l2_RRpagingrequest1() +{ + if (data >= end) + return; + + OUTF("%s\n", PageMode(data[0] & 0x3)); + + /* FIXME complete here */ + + data++; + if (data >= end) + return; + + l2_MobId(); + if (data >= end) + return; /* sometimes it's end here */ + if (data[0] == 0x17) + { + data++; + l2_MobId(); + return; + } + OUTF("ERR: wrong data\n"); +} + +static void +l2_ChannelNeeded(char *str, unsigned char ch) +{ + switch (ch) + { + case 0x00: + OUTF("%s Channel Needed: Any channel\n", str); + break; + case 0x01: + OUTF("%s Channel Needed: SDCCH\n", str); + break; + case 0x02: + OUTF("%s Channel Needed: TCH/F (Full rate)\n", str); + break; + case 0x03: + OUTF("%s Channel Needed: TCH/H or TCH/F (Dual rate)\n", str); + break; + } + +} + +static void +l2_RRpagingrequest2() +{ + if (data >= end) + return; + OUTF("%s\n", PageMode(data[0] & 0x03)); + + l2_ChannelNeeded("--xx---- (first)", (data[0] >> 4) & 0x03); + l2_ChannelNeeded("xx------ (second)", data[0] >> 6); + + data++; + if (data + 3 >= end) + RETTRUNK(); + OUTF("........ Mob. Ident 1 (P)TMSI: %02X%02X%02X%02X\n", data[0], data[1], data[2], data[3]); + data += 4; + if (data + 3 >= end) + RETTRUNK(); + OUTF("........ Mob. Ident 2 (P)TMSI: %02X%02X%02X%02X\n", data[0], data[1], data[2], data[3]); + data += 4; + if (data >= end) + RETTRUNK(); + + if (data[0] == 0x17) + { + data++; + l2_MobId(); + return; + } + + OUTF("FIXME, unknown\n"); +} + +static void +l2_RRpagingrequest3() +{ + if (data >= end) + RETTRUNK(); + OUTF("%s\n", PageMode(data[0] & 0x03)); + l2_ChannelNeeded("--xx---- (first)", (data[0] >> 4) & 0x03); + l2_ChannelNeeded("xx------ (second)", data[0] >> 6); + data++; + + int c = 0; + while (c++ < 4) + { + if (data + 3 >= end) + RETTRUNK(); + OUTF("........ Mob. Ident %u (P)TMSI: %02X%02X%02X%02X\n", c, data[0], data[1], data[2], data[3]); + data += 4; + } +} + +static void +l2_MobId() +{ + const unsigned char *thisend = end; + unsigned char len = data[0]; + char odd = 0; + int bcd = 0; + + data++; + if (data >= end) + return; + + if ((data[0] >> 3) & 1) + odd = 1; + + switch (data[0] & 0x07) + { + case 0: + OUTF("-----000 Type of identity: No Identity\n"); + break; + case 1: + OUTF("-----001 Type of identity: IMSI\n"); + bcd = 1; + break; + case 2: + OUTF("-----010 Type of identity: IMEI\n"); + bcd = 1; + break; + case 3: + OUTF("-----011 Type of identity: IMEISV\n"); + bcd = 1; + break; + case 4: + OUTF("-----100 Type of identity: TMSI/P-TMSI\n"); + break; + default: + OUTF("-----000 Type of identity: UNKNOWN\n"); + return; + } + if (len <= 0) + return; + + /* Nokia Netmonitor never outputs the first value */ + //OUTF("%x", data[0] >> 4); + unsigned char c; + c = data[0] >> 4; + len--; + data++; + if (len <= 0) + return; + + OUTF("-------- ID(%d/%s): ", len, odd?"odd":"even"); + + if (data + len < thisend) + thisend = data + len; + if (bcd) + { + OUT("%X", c); + while (data < thisend) + { + if ((data + 1 == thisend) && (!odd)) + OUT("%X", data[0] & 0x0f); + else + OUT("%X%X", data[0] & 0x0f, (data[0] >> 4) & 0x0f); + data++; + } + } else { + while (data < thisend) + { + if ((data + 1 == thisend) && (odd)) + OUT("%X", (data[0] >> 4 ) & 0x0f); + else + OUT("%X%X", (data[0] >> 4) & 0x0f, data[0] & 0x0f); + data++; + } + } + OUT("\n"); +} + + +static void CellSelectionParameters() +{ + if (data >= end) + RETTRUNK(); + + switch (data[0] >> 5) + { + case 0: + OUTF("000----- Cell Reselect Hyst. : 0 db RXLEV\n"); + break; + case 1: + OUTF("001----- Cell Reselect Hyst. : 2 db RXLEV\n"); + break; + case 2: + OUTF("010----- Cell Reselect Hyst. : 4 db RXLEV\n"); + break; + case 3: + OUTF("011----- Cell Reselect Hyst. : 6 db RXLEV\n"); + break; + case 4: + OUTF("100----- Cell Reselect Hyst. : 8 db RXLEV\n"); + break; + case 5: + OUTF("101----- Cell Reselect Hyst. : 10 db RXLEV\n"); + break; + case 6: + OUTF("110----- Cell Reselect Hyst. : 12 db RXLEV\n"); + break; + case 7: + OUTF("111----- Cell Reselect Hyst. : 14 db RXLEV\n"); + break; + } + OUTF("---xxxxx Max Tx power level: %d\n", data[0] & 0x1f); + data++; + if (data >= end) + RETTRUNK(); + + if (data[0] >> 7) + OUTF("1------- Additional cells in SysInfo 16,17\n"); + else + OUTF("0------- No additional cells in SysInfo 7-8\n"); + if ((data[0] >> 6) & 1) + OUTF("-1------ New establishm cause: supported\n"); + else + OUTF("-0------ New establishm cause: not supported\n"); + OUTF("--xxxxxx RXLEV Access Min permitted = -110 + %ddB\n", data[0] & 0x3f); + data++; +} + +static void +l2_RRimmAssTBFDirEncHoChaC() +{ + unsigned char maio = (data[0] & 0x0f) << 4; + + data++; + if (data >= end) + RETTRUNK(); + maio |= (data[0] >> 6); + OUTF("xxxxxxxx MAIO: %u\n", maio); + OUTF("%s HSN: %u\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f); + data++; + + RequestReference(); + + TimingAdvance(); + l2_MobileAllocation(); + + if (data >= end) + RETTRUNK(); + if (data[0] == 0x7c) + { + StartingTime(); + return; + } + OUTF("FIXME: implement me\n"); +} + +static void +RequestReference() +{ + if (data >= end) + RETTRUNK(); + + /* Request Reference */ + if ((data[0] >> 5) == 0) + OUTF("000----- Establishing Cause : All other cases\n"); + else if ((data[0] >> 5) == 0x01) + OUTF("001----- Establishing Cause : All other cases\n"); + else if ((data[0] >> 5) == 0x02) + OUTF("010----- Establishing Cause : All other cases\n"); + else if ((data[0] >> 5) == 0x03) + OUTF("011----- Establishing Cause : All other cases\n"); + else if ((data[0] >> 5) == 0x04) + OUTF("100----- Establishing Cause: Answer to paging\n"); + else if ((data[0] >> 5) == 0x05) + OUTF("101----- Establishing Cause: Emergency call\n"); + else if ((data[0] >> 5) == 0x07) + OUTF("111----- Establishing Cause: Other services req. by user\n"); +/* Random refernce must be 5 bit long ?! */ +// else if ((data[0] >> 4) == 0x05) +// OUTF("0101---- Establishing Cause: Originating data call from dual rate mobile station\n"); +// else if ((data[0] >> 4) == 0x02) +// OUTF("0010---- Establishing Cause: Answer to paging\n"); + else + OUTF("%s Establishing Cause: UNKNOWN [FIXME}\n", BitRowFill(data[0], 0xe0)); + + OUTF("---xxxxx Random Reference : %d\n", data[0] & 0x1f); + + data++; + if (data + 1>= end) + RETTRUNK(); + + OUTF("xxxxxxxx T1/T2/T3\n"); + data++; + OUTF("xxxxxxxx T1/T2/T3\n"); + data++; + /* END Request Reference */ +} + +static void +TimingAdvance() +{ + if (data >= end) + RETTRUNK(); + OUTF("--xxxxxx Timing advance value: %d\n", data[0] & 0x3f); + data++; +} + +static void +StartingTime() +{ + if (data >= end) + RETTRUNK(); + OUTF("01111100 Starting Time block\n"); + data++; + if (data >= end) + RETTRUNK(); + unsigned char t3; + OUTF("%s T1 Frame Number: %u\n", BitRowFill(data[0], 0xf8), data[0] >> 3); + t3 = (data[0] & 0x07) << 5; + data++; + if (data >= end) + RETTRUNK(); + t3 |= (data[0] >> 5); + OUTF("%s T2 Frame Number: %u\n", BitRowFill(data[0], 0x1f), data[0] & 0x1f); + OUTF("........ T3 Frame Number: %u\n", t3); +} + +/* + * RRsystemInfo5 + */ +static void +l2_NeighbourCellDescription() +{ + if (data >= end) + RETTRUNK(); + l2_BcchAllocation(); +} + + +static void +l2_ChannelRelease() +{ + if (data >= end) + RETTRUNK(); + OUTF("%s\n", id_list_get(list_ChannelRelease, data[0])); + data++; +} + +static void +l2_MMcmServiceRequest() +{ + if (data >= end) + RETTRUNK(); + + OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07); + OUTF("%s\n", id_list_get(list_RequestServiceType, data[0] & 0x0f)); + data++; + MSClassMarkTwo(); + if (data >= end) + RETTRUNK(); + + if (data[0] == 0x20) + { + OUTF("FIXME: classmark3\n"); + return; + } + + l2_MobId(); +} + +static void +MSClassMarkTwo() +{ + if (data >= end) + RETTRUNK(); + + OUTF("%s MS Classmark 2 length: %u\n", BitRowFill(data[0], 0xff), data[0]); + data++; + 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++; + + if ((data[0] >> 6) & 1) + OUTF("-1------ Pseudo Sync Capability: present\n"); + else + OUTF("-1------ Pseudo Sync Capability: not present\n"); + + if (((data[0] >> 4) & 0x03) == 0) + OUTF("--00---- SS Screening: Phase 1 default value\n"); + else if (((data[0] >> 4) & 0x03) == 1) + OUTF("--01---- SS Screening: Phase 2 error handling\n"); + else + OUTF("--xx---- SS Screening: UNKNOWN\n"); + + if ((data[0] >> 3) & 1) + OUTF("----1--- Mobile Terminated Point to Point SMS: supported\n"); + else + OUTF("----0--- Mobile Terminated Point to Point SMS: not supported\n"); + + if ((data[0] >> 2) & 1) + OUTF("-----1-- VoiceBroadcastService: supported\n"); + else + OUTF("-----0-- VoiceBroadcastService: not supported\n"); + + if ((data[0] >> 1) & 1) + OUTF("------1- VoiceGroupCallService: supported\n"); + else + OUTF("------0- VoiceGroupCallService: not supported\n"); + + if (data[0] & 1) + OUTF("-------1 MS supports E-GSM or R-GSM: supported\n"); + else + OUTF("-------0 MS supports E-GSM or R-GSM: not supported\n"); + + data++; + if (data >= end) + RETTRUNK(); + + + if ((data[0] >> 7) & 1) + OUTF("1------- CM3 option: supported\n"); + else + OUTF("0------- CM3 option: not supported\n"); + + if ((data[0] >> 5) & 1) + OUTF("--1----- LocationServiceValueAdded Capability: supported\n"); + else + OUTF("--0----- LocationServiceValueAdded Capability: not supported\n"); + + if ((data[0] >> 3) & 1) + OUTF("----1--- SoLSA Capability: supported\n"); + else + OUTF("----0--- SoLSA Capability: not supported\n"); + + if ((data[0] >> 1) & 1) + OUTF("------1- A5/3 available\n"); + else + OUTF("------0- A5/3 not available\n"); + + if (data[0] & 1) + OUTF("-------1 A5/2: available\n"); + else + OUTF("-------0 A5/2: not available\n"); + data++; +} + +static void +l2_RRciphModCmd() +{ + if (data >= end) + RETTRUNK(); + if (((data[0] >> 1) & 0x07) == 0x07) + OUTF("----111- Cipher: reserved [UNKNOWN]\n"); + else + OUTF("%s Cipher: A5/%u\n", BitRowFill(data[0], 0x0e), ((data[0] >> 1) & 0x07) + 1); + + + if (data[0] & 1) + OUTF("-------1 Start ciphering\n"); + else + OUTF("-------0 No ciphering\n"); + + if ((data[0] >> 4) & 1) + OUTF("---1---- Cipher Response: IMEISV shall be included\n"); + else + OUTF("---0---- Cipher Response: IMEISV shall not be included\n"); + data++; +} + +static void +l2_RRciphModCompl() +{ + if (data >= end) + RETTRUNK(); + + if (data[0] != 0x17) + return; + if (++data >= end) + RETTRUNK(); + l2_MobId(); +} + +static void +l2_TmsiReallocCommand() +{ + if (data >= end) + RETTRUNK(); + + l2_MccMncLac(); + l2_MobId(); +} + +static void +l2_sms() +{ + if (data >= end) + RETTRUNK(); + + if ((data[0] == 0x04)) + OUTF("00000100 Type: CP-ACK\n"); + else if (data[0] == 0x10) + OUTF("00010000 Type: CP-ERROR\n"); + else if (data[0] == 1) { + OUTF("00000001 Type: CP-DATA\n"); + data++; + cpData(); + } else + OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff)); +} + +static void +cpDataUp() +{ + if (data >= end) + RETTRUNK(); + OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]); + if (++data >= end) + RETTRUNK(); + OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]); + if (++data >= end) + RETTRUNK(); + OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]); + data++; + Address("SMSC"); + if (data >= end) + RETTRUNK(); + + /* FIXME: Be more detailed here about message flags */ + OUTF("%s Message Flags: %u\n", BitRowFill(data[0], 0xff), data[0]); + if (++data + 1 >= end) + RETTRUNK(); + int num = data[0] << 8; + OUTF("%s Reference Number [continue]\n", BitRowFill(data[0], 0xff)); + data++; + num |= data[0]; + OUTF("%s Reference Number: %u\n", BitRowFill(data[0], 0xff), num); + data++; + + /* Destination address */ + Address("Destination"); + SmsProtocolDataValidity(); + if (data >= end) + RETTRUNK(); +} + +static void +cpData() +{ + 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 Parameter\n", BitRowFill(data[0], 0xff)); + if (++data >= end) + RETTRUNK(); + OUTF("%s Parameter\n", BitRowFill(data[0], 0xff)); + if (++data >= end) + return; /* Can happen that msg terminated here... */ + + Address("SMSC"); + if (data >= end) + RETTRUNK(); + + 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++; + + Address("Destination"); + SmsProtocolDataValidity(); + + int c = 0; + while (c++ < 7) + { + OUTF("%s Parameter%u\n", BitRowFill(data[0], 0xff), c); + if (++data >= end) + RETTRUNK(); + } + OUTF("FIXME %p < %p\n", data, end); +} + +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) + return; + if (data >= end) + RETTRUNK(); + if (data[0] >> 7) + OUTF("1------- Extension\n"); + + OUTF("%s\n", id_list_get(list_SMSCAddressType, (data[0] >> 4) & 0x07)); + OUTF("%s\n", id_list_get(list_SMSCAddressNumberingPlan, data[0] & 0x0f)); + len--; + data++; + if (len <= 0) + return; + const unsigned char *thisend = data + len; + if (thisend > end) + thisend = end; + + OUTF("-------- Number(%d): ", len); + while (data < thisend) + { + if ((data[0] >> 4) == 0x0f) + OUT("%X", data[0] & 0x0f); + else + OUT("%X%X", data[0] & 0x0f, data[0] >> 4); + data++; + } + OUT("\n"); +} + + +static void +l2_RRpagingresponse() +{ + if (data >= end) + RETTRUNK(); + + if ((data[0] & 0x07) == 0x07) + OUTF("-----111 Cipher key sequence: Key not available!\n"); + else + OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x07), data[0] & 0x07); + + OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07); + + data++; + MSClassMarkTwo(); + if (data >= end) + RETTRUNK(); + l2_MobId(); +} + +static void +l2_RRassignCommand() +{ + ChannelDescriptionTwo(); + if (data >= end) + RETTRUNK(); + + OUTF("%s Training seq. code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5); + if (((data[0] >> 2) & 0x07) == 0x00) + l2_SingleChannelAssCom(); + else if (((data[0] >> 4) & 1) == 0x01) + l2_HoppingChannelAssCom(); + else + OUTF("xxx0??xxx UNKNOWN %d\n", (data[0] >> 3) & 0x3); +} + +static void +l2_RRassignComplete() +{ + if (data >= end) + RETTRUNK(); + + OUTF("%s\n", id_list_get(list_ChannelRelease, data[0])); + data++; +} + +static void +ChannelDescriptionTwo() +{ + if (data >= end) + RETTRUNK(); + OUTF("%s Timeslot number: %d\n", BitRowFill(data[0], 0x07), data[0] & 0x07); + OUTF("%s Channel Description: %s\n", BitRowFill(data[0], 0xf8), id_list_get(list_ChannelDescriptionTwo, data[0] >> 3)); + + data++; +} + +static void +l2_SingleChannelAssCom() +{ + int freq = (data[0] & 0x03) << 8; + + data++; + if (data >= end) + RETTRUNK(); + freq |= data[0]; + OUTF("........ Absolute RF channel number: %u\n", freq); + if (++data >= end) + RETTRUNK(); + OUTF("%s Power Level: %u\n", BitRowFill(data[0], 0x1f), data[0] & 0x1f); + if (++data >= end) + RETTRUNK(); + if (data[0] != 0x63) + return; + if (++data >= end) + RETTRUNK(); + OUTF("%s\n", id_list_get(list_ChannelMode, data[0])); +} + +static void +l2_HoppingChannelAssCom() +{ + OUTF("FIXME %s\n", __func__); +} + +static void +CCalerting() +{ + if (data >= end) + RETTRUNK(); + if (data[0] != 0x1e) + return; + + data++; + ProgressIndicator(); +} + +static void +ProgressIndicator() +{ + if (data >= end) + RETTRUNK(); + + OUTF("%s Length of IE Progress Indicator: %u\n", BitRowFill(data[0], 0xff), data[0]); + if (++data >= end) + RETTRUNK(); + OUTF("%s Coding: %s\n", BitRowFill(data[0], 0x60), id_list_get(list_CodingStandard, (data[0] >> 5) & 0x03)); + OUTF("%s Location: %s\n", BitRowFill(data[0], 0x0f), id_list_get(list_Location, data[0] & 0x0f)); + if (++data >= end) + RETTRUNK(); + OUTF("%s\n", id_list_get(list_Progress, data[0] & 0x7f)); + data++; +} + +static void +CCsetup() +{ + if (data >= end) + RETTRUNK(); + + if (data[0] == 0x04) + { + OUTF("00000100 Bearer Capability\n"); + data++; + BearerCap(); + } else if (data[0] == 0x1e) { + OUTF("00011110 Progress Indicator\n"); + ProgressIndicator(); + return; + } else { + OUTF("%s FIXME\n", BitRowFill(data[0], 0xff)); + } + + 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 [FIXME]\n"); + data++; + } +} + +static void +SmsProtocolDataValidity() +{ + if (data >= end) + RETTRUNK(); + OUTF("%s Protocol Identifier: %u\n", BitRowFill(data[0], 0xff), data[0]); + if (++data >= end) + RETTRUNK(); + OUTF("%s Data Coding Sheme: %u\n", BitRowFill(data[0], 0xff), data[0]); + data++; +} + +static void +BearerCap() +{ + int len; + + 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(); + + 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)); + //len--; + OUTF("FIXME: Stuff missing here\n"); +#if 0 + if (++data >= end) + RETTRUNK(); + if ((data[0] >> 6) & 1) + OUTF("-1------ Coding: octet 3 extended [FIXME]\n"); + else + OUTF("-0------ Coding: octet 3 extended for inf. trans. cap\n"); + + /* FIXME: Stuff missing here */ +#endif +} + +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 +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; +} + -- cgit v1.2.3