From ab1255b34f56c222202eedc42ac6e54cdf2cb4c4 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 13 Jan 2011 18:09:44 +0800 Subject: debian: Switch to the 3.0 git format, update version, fix depends Switch to the git format as this can generate the source directly from the git checkout. Increase the version number to 0.1.27 as this is the latest tag, depend on autoconf, automake and libtool and use autoreconf when building to be able to directly build from a git clone. --- debian/changelog | 6 ++++++ debian/control | 2 +- debian/rules | 2 +- debian/source/format | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 5783127f..4c103cb9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +libosmocore (0.1.27) natty; urgency=low + + * New upstream version of libosmocore. + + -- Holger Hans Peter Freyther Thu, 13 Jan 2011 18:07:36 +0800 + libosmocore (0.1.17-1) unstable; urgency=low * Initial release (Closes: #nnnn) diff --git a/debian/control b/debian/control index 1348ec30..164fc386 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: libosmocore Section: libs Priority: optional Maintainer: Harald Welte -Build-Depends: debhelper (>= 7.0.50~), autotools-dev +Build-Depends: debhelper (>= 7.0.50~), autotools-dev, autoconf, automake, libtool, dh-autoreconf Standards-Version: 3.8.4 Homepage: http://bb.osmocom.org/trac/wiki/libosmocore Vcs-Git: git://git.osmocom.org/libosmocore.git diff --git a/debian/rules b/debian/rules index a81850a2..15f78f2c 100755 --- a/debian/rules +++ b/debian/rules @@ -12,7 +12,7 @@ CFLAGS = -Wall -g %: - dh $@ + dh --with autoreconf $@ #override_dh_strip: # dh_strip --dbg-package=libosmocore-dbg diff --git a/debian/source/format b/debian/source/format index 163aaf8d..af745b31 100644 --- a/debian/source/format +++ b/debian/source/format @@ -1 +1 @@ -3.0 (quilt) +3.0 (git) -- cgit v1.2.3 From 16f80a0e7a8f3d5ea74229920aea1e5e6693c951 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 13 Jan 2011 12:31:25 +0100 Subject: debian: Make the -dev package depend on the normal one Make libosmocore-dev depend on libosmocore. Otherwise we only end up with the libosmocore.a files installed and then have various issues with the link order when linking OpenBSC and such. --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 164fc386..3f92875c 100644 --- a/debian/control +++ b/debian/control @@ -17,7 +17,7 @@ Description: Open Source MObile COMmunications CORE library Package: libosmocore-dev Section: libdevel Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} +Depends: ${shlibs:Depends}, ${misc:Depends}, libosmocore Description: Development headers for Open Source MObile COMmunications CORE library #Package: libosmocore-dbg -- cgit v1.2.3 From d126ab988b4f63c31e803dccbb2a08ac6f16e9ce Mon Sep 17 00:00:00 2001 From: Alex Badea Date: Sat, 15 Jan 2011 19:43:42 +0200 Subject: gsm 03.41: fix GSM341_MSG_CODE macro argument One usage of the "ms" argument is typoed as "msg". Fix it to prevent subtle future failures. Also paranthesize the macro argument for good measure. Signed-off-by: Alex Badea --- include/osmocore/protocol/gsm_03_41.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osmocore/protocol/gsm_03_41.h b/include/osmocore/protocol/gsm_03_41.h index 3b1b7c9f..54365cbc 100644 --- a/include/osmocore/protocol/gsm_03_41.h +++ b/include/osmocore/protocol/gsm_03_41.h @@ -40,7 +40,7 @@ struct gsm341_etws_message { uint8_t data[0]; } __attribute__((packed)); -#define GSM341_MSG_CODE(ms) (ms->serial.code_lo | (msg->serial.code_hi << 4)) +#define GSM341_MSG_CODE(ms) ((ms)->serial.code_lo | ((ms)->serial.code_hi << 4)) /* Section 9.3.2.1 - Geographical Scope */ #define GSM341_GS_CELL_WIDE_IMMED 0 -- cgit v1.2.3 From 52c07ca6c5708e4b20d8a6b6f40d09f74fef43ba Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 16 Jan 2011 17:37:27 +0100 Subject: misc: Move the static_assert from logging to the utils This is just an ordinary macro, no specific reason to have it in logging.h. This was compile tested with code from our osmo family. --- include/osmocore/logging.h | 1 - include/osmocore/utils.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/osmocore/logging.h b/include/osmocore/logging.h index 7f33155a..27e77341 100644 --- a/include/osmocore/logging.h +++ b/include/osmocore/logging.h @@ -19,7 +19,6 @@ #define DEBUGPC(ss, fmt, args...) #endif -#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; void logp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); diff --git a/include/osmocore/utils.h b/include/osmocore/utils.h index 3574f7f8..93cefbe6 100644 --- a/include/osmocore/utils.h +++ b/include/osmocore/utils.h @@ -21,4 +21,6 @@ int hexparse(const char *str, uint8_t *b, int max_len); char *hexdump(const unsigned char *buf, int len); char *hexdump_nospc(const unsigned char *buf, int len); +#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; + #endif -- cgit v1.2.3 From 5853f084a0212b7f50cbdd18cfbc15f90de240ff Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sun, 16 Jan 2011 17:38:22 +0100 Subject: msgb: Make sure at compile time that headroom is smaller than size All current code is using constants to allocate the msgb with headroom. Use a static_assert to make sure that the headroom is smaller than the size. This makes API misusage unlikely to happen. --- include/osmocore/msgb.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/osmocore/msgb.h b/include/osmocore/msgb.h index 6fd24c7f..c4f44305 100644 --- a/include/osmocore/msgb.h +++ b/include/osmocore/msgb.h @@ -22,6 +22,7 @@ #include #include "linuxlist.h" +#include "utils.h" #define MSGB_DEBUG @@ -180,6 +181,8 @@ static inline void msgb_reserve(struct msgb *msg, int len) static inline struct msgb *msgb_alloc_headroom(int size, int headroom, const char *name) { + static_assert(size > headroom, headroom_bigger); + struct msgb *msg = msgb_alloc(size, name); if (msg) msgb_reserve(msg, headroom); -- cgit v1.2.3 From dba847822266ac144a519c1752f8941072f3897b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 18 Jan 2011 21:38:12 +0100 Subject: gsmtap.h: Add some more comments --- include/osmocore/gsmtap.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/osmocore/gsmtap.h b/include/osmocore/gsmtap.h index 3f384a4f..c5dba794 100644 --- a/include/osmocore/gsmtap.h +++ b/include/osmocore/gsmtap.h @@ -21,6 +21,7 @@ #define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */ #define GSMTAP_TYPE_SIM 0x04 +/* sub-types for TYPE_UM_BURST */ #define GSMTAP_BURST_UNKNOWN 0x00 #define GSMTAP_BURST_FCCH 0x01 #define GSMTAP_BURST_PARTIAL_SCH 0x02 @@ -32,6 +33,7 @@ #define GSMTAP_BURST_ACCESS 0x08 #define GSMTAP_BURST_NONE 0x09 +/* sub-types for TYPE_UM */ #define GSMTAP_CHANNEL_UNKNOWN 0x00 #define GSMTAP_CHANNEL_BCCH 0x01 #define GSMTAP_CHANNEL_CCCH 0x02 @@ -45,10 +47,12 @@ #define GSMTAP_CHANNEL_TCH_H 0x0a #define GSMTAP_CHANNEL_ACCH 0x80 +/* flags for the ARFCN */ #define GSMTAP_ARFCN_F_PCS 0x8000 #define GSMTAP_ARFCN_F_UPLINK 0x4000 #define GSMTAP_ARFCN_MASK 0x3fff +/* IANA-assigned well-known UDP port for GSMTAP messages */ #define GSMTAP_UDP_PORT 4729 struct gsmtap_hdr { -- cgit v1.2.3 From c035ec63f509573408069340b4d40a906a40b8f7 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 19 Jan 2011 09:40:59 +0100 Subject: [gsmtap] extend GSMTAP for TETRA --- include/osmocore/gsmtap.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/osmocore/gsmtap.h b/include/osmocore/gsmtap.h index c5dba794..3f911e6d 100644 --- a/include/osmocore/gsmtap.h +++ b/include/osmocore/gsmtap.h @@ -20,6 +20,8 @@ #define GSMTAP_TYPE_ABIS 0x02 #define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */ #define GSMTAP_TYPE_SIM 0x04 +#define GSMTAP_TYPE_TETRA_I1 0x05 /* tetra air interface */ +#define GSMTAP_TYPE_TETRA_I1_BURST 0x06 /* tetra air interface */ /* sub-types for TYPE_UM_BURST */ #define GSMTAP_BURST_UNKNOWN 0x00 @@ -47,6 +49,17 @@ #define GSMTAP_CHANNEL_TCH_H 0x0a #define GSMTAP_CHANNEL_ACCH 0x80 +/* sub-types for TYPE_TETRA_AIR */ +#define GSMTAP_TETRA_BSCH 0x01 +#define GSMTAP_TETRA_AACH 0x02 +#define GSMTAP_TETRA_AACH 0x03 +#define GSMTAP_TETRA_SCH_HU 0x04 +#define GSMTAP_TETRA_SCH_HD 0x05 +#define GSMTAP_TETRA_SCH_F 0x06 +#define GSMTAP_TETRA_BNCH 0x07 +#define GSMTAP_TETRA_STCH 0x08 +#define GSMTAP_TETRA_TCH_F 0x09 + /* flags for the ARFCN */ #define GSMTAP_ARFCN_F_PCS 0x8000 #define GSMTAP_ARFCN_F_UPLINK 0x4000 -- cgit v1.2.3 From 2230c133a69e8f9660051aff61626996deba4ed8 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 19 Jan 2011 10:10:16 +0100 Subject: [BITS] introduce new packed/unpacked bit conversion routines --- include/osmocore/Makefile.am | 2 +- include/osmocore/bits.h | 27 ++++++++++++++++++ src/Makefile.am | 2 +- src/bits.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 include/osmocore/bits.h create mode 100644 src/bits.c diff --git a/include/osmocore/Makefile.am b/include/osmocore/Makefile.am index 2efaa96b..a3b12ef4 100644 --- a/include/osmocore/Makefile.am +++ b/include/osmocore/Makefile.am @@ -1,4 +1,4 @@ -osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h \ +osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \ tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \ gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \ gsm48_ie.h logging.h gsm0808.h rate_ctr.h gsmtap_util.h \ diff --git a/include/osmocore/bits.h b/include/osmocore/bits.h new file mode 100644 index 00000000..662c4a9d --- /dev/null +++ b/include/osmocore/bits.h @@ -0,0 +1,27 @@ +#ifndef _OSMO_BITS_H +#define _OSMO_BITS_H + +#include + +typedef uint8_t sbit_t; /* soft bit (-127...127) */ +typedef uint8_t ubit_t; /* unpacked bit (0 or 1) */ +typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */ + +/* determine how many bytes we would need for 'num_bits' packed bits */ +static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits) +{ + unsigned int pbit_bytesize = num_bits / 8; + + if (num_bits % 8) + pbit_bytesize++; + + return pbit_bytesize; +} + +/* convert unpacked bits to packed bits, return length in bytes */ +int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits); + +/* convert packed bits to unpacked bits, return length in bytes */ +int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits); + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index 64310e0f..d4c6e127 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,7 @@ AM_CFLAGS = -fPIC -Wall lib_LTLIBRARIES = libosmocore.la -libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \ +libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c bits.c \ tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ logging.c gsm0808.c rate_ctr.c gsmtap_util.c \ diff --git a/src/bits.c b/src/bits.c new file mode 100644 index 00000000..fb3c7224 --- /dev/null +++ b/src/bits.c @@ -0,0 +1,65 @@ + +#include + +#include + +/* convert unpacked bits to packed bits, return length in bytes */ +int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits) +{ + unsigned int i; + uint8_t curbyte = 0; + pbit_t *outptr = out; + + for (i = 0; i < num_bits; i++) { + uint8_t bitnum = 7 - (i % 8); + + curbyte |= (in[i] << bitnum); + + if (i > 0 && i % 8 == 0) { + *outptr++ = curbyte; + curbyte = 0; + } + } + /* we have a non-modulo-8 bitcount */ + if (i % 8) + *outptr++ = curbyte; + + return outptr - out; +} + +/* convert packed bits to unpacked bits, return length in bytes */ +int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits) +{ + unsigned int i; + ubit_t *cur = out; + ubit_t *limit = out + num_bits; + + for (i = 0; i < (num_bits/8)+1; i++) { + pbit_t byte = in[i]; + *cur++ = (byte >> 7) & 1; + if (cur >= limit) + break; + *cur++ = (byte >> 6) & 1; + if (cur >= limit) + break; + *cur++ = (byte >> 5) & 1; + if (cur >= limit) + break; + *cur++ = (byte >> 4) & 1; + if (cur >= limit) + break; + *cur++ = (byte >> 3) & 1; + if (cur >= limit) + break; + *cur++ = (byte >> 2) & 1; + if (cur >= limit) + break; + *cur++ = (byte >> 1) & 1; + if (cur >= limit) + break; + *cur++ = (byte >> 0) & 1; + if (cur >= limit) + break; + } + return cur - out; +} -- cgit v1.2.3 From aeb10770510decf85797c8768285641639be9026 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 21 Jan 2011 12:22:30 +0100 Subject: bits: Add extended options version of pbit2ubit and ubit2pbit Signed-off-by: Sylvain Munaut --- include/osmocore/bits.h | 12 ++++++++++++ src/bits.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/include/osmocore/bits.h b/include/osmocore/bits.h index 662c4a9d..eb2cbcba 100644 --- a/include/osmocore/bits.h +++ b/include/osmocore/bits.h @@ -24,4 +24,16 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits); /* convert packed bits to unpacked bits, return length in bytes */ int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits); +/* convert unpacked bits to packed bits (extended options but slower), + * return length in bytes (max written ofs of output buffer + 1) */ +int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs, + const ubit_t *in, unsigned int in_ofs, + unsigned int num_bits, int lsb_mode); + +/* convert packed bits to unpacked bits (extended options but slower), + * return length in bytes (max written ofs of output buffer + 1) */ +int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs, + const pbit_t *in, unsigned int in_ofs, + unsigned int num_bits, int lsb_mode); + #endif diff --git a/src/bits.c b/src/bits.c index fb3c7224..029cfe55 100644 --- a/src/bits.c +++ b/src/bits.c @@ -63,3 +63,36 @@ int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits) } return cur - out; } + +/* convert unpacked bits to packed bits (extended options but slower), + * return length in bytes (max written ofs of output buffer + 1) */ +int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs, + const ubit_t *in, unsigned int in_ofs, + unsigned int num_bits, int lsb_mode) +{ + int i, op, bn; + for (i=0; i>3] |= 1 << bn; + else + out[op>>3] &= ~(1 << bn); + } + return ((out_ofs + num_bits - 1) >> 3) + 1; +} + +/* convert packed bits to unpacked bits (extended options but slower), + * return length in bytes (max written ofs of output buffer + 1) */ +int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs, + const pbit_t *in, unsigned int in_ofs, + unsigned int num_bits, int lsb_mode) +{ + int i, ip, bn; + for (i=0; i>3] & (1< Date: Sat, 22 Jan 2011 22:48:37 +0100 Subject: ubit2pbit flushes at the wrong moment, added one note to bits.h (e.g. input2[] test sequence from testra/crc_test decodes incorrectly to packed bits: 90 b0 3e 80 03 87 53 bd 6f 08, this patch fixes it) --- include/osmocore/bits.h | 6 ++++++ src/bits.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/osmocore/bits.h b/include/osmocore/bits.h index eb2cbcba..8d4a0789 100644 --- a/include/osmocore/bits.h +++ b/include/osmocore/bits.h @@ -7,6 +7,12 @@ typedef uint8_t sbit_t; /* soft bit (-127...127) */ typedef uint8_t ubit_t; /* unpacked bit (0 or 1) */ typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */ +/* + NOTE on the endianess of pbit_t: + Bits in a pbit_t are ordered MSB first, i.e. 0x80 is the first bit. + Bit i in a pbit_t array is array[i/8] & (1<<(7-i%8)) +*/ + /* determine how many bytes we would need for 'num_bits' packed bits */ static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits) { diff --git a/src/bits.c b/src/bits.c index 029cfe55..fcdf5cc3 100644 --- a/src/bits.c +++ b/src/bits.c @@ -15,7 +15,7 @@ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits) curbyte |= (in[i] << bitnum); - if (i > 0 && i % 8 == 0) { + if(i % 8 == 7){ *outptr++ = curbyte; curbyte = 0; } -- cgit v1.2.3 From 549fbb8232aedc86acc3abae814b41d8555f8e5b Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 22 Jan 2011 23:17:21 +0100 Subject: logging: Add isup,m2ua,pcap from the cellmgr. This is something that we should generate dynamically from the log_info as well. This is adding bits from the cellmgr_ng. --- src/vty/logging_vty.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 896d79a9..ea58887a 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -138,7 +138,7 @@ DEFUN(logging_prnt_timestamp, } /* FIXME: those have to be kept in sync with the log levels and categories */ -#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|gprs|ns|bssgp|llc|sndcp|all)" +#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|gprs|ns|bssgp|llc|sndcp|isup|m2ua|pcap|all)" #define CATEGORIES_HELP \ "A-bis Radio Link Layer (RLL)\n" \ "Layer3 Call Control (CC)\n" \ @@ -165,6 +165,9 @@ DEFUN(logging_prnt_timestamp, "GPRS BSS Gateway Protocol (BSSGP)\n" \ "GPRS Logical Link Control Protocol (LLC)\n" \ "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \ + "ISDN User Part (ISUP)\n" \ + "SCTP M2UA\n" \ + "Trace message IO\n" \ "Global setting for all subsytems\n" #define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)" -- cgit v1.2.3 From e7509083673381f5be0e66bf6d9d76195b5fad82 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 28 Jan 2011 10:13:41 +0100 Subject: gsmtap: The TETRA_AACH was defined twice, remove one, renumber The GSMTAP_TETRA_AACH was defined twice. On the tetra list we decided to remove the second entry and renumber the list as no one is using this yet. --- include/osmocore/gsmtap.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/osmocore/gsmtap.h b/include/osmocore/gsmtap.h index 3f911e6d..236b25ac 100644 --- a/include/osmocore/gsmtap.h +++ b/include/osmocore/gsmtap.h @@ -52,13 +52,12 @@ /* sub-types for TYPE_TETRA_AIR */ #define GSMTAP_TETRA_BSCH 0x01 #define GSMTAP_TETRA_AACH 0x02 -#define GSMTAP_TETRA_AACH 0x03 -#define GSMTAP_TETRA_SCH_HU 0x04 -#define GSMTAP_TETRA_SCH_HD 0x05 -#define GSMTAP_TETRA_SCH_F 0x06 -#define GSMTAP_TETRA_BNCH 0x07 -#define GSMTAP_TETRA_STCH 0x08 -#define GSMTAP_TETRA_TCH_F 0x09 +#define GSMTAP_TETRA_SCH_HU 0x03 +#define GSMTAP_TETRA_SCH_HD 0x04 +#define GSMTAP_TETRA_SCH_F 0x05 +#define GSMTAP_TETRA_BNCH 0x06 +#define GSMTAP_TETRA_STCH 0x07 +#define GSMTAP_TETRA_TCH_F 0x08 /* flags for the ARFCN */ #define GSMTAP_ARFCN_F_PCS 0x8000 -- cgit v1.2.3 From 3d0ac5e446314c08f3e590bb4dd976b551bff618 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 8 Feb 2011 16:55:03 +0100 Subject: [utils] add 'bitdump' function for bitfields --- include/osmocore/utils.h | 1 + src/utils.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/osmocore/utils.h b/include/osmocore/utils.h index 93cefbe6..da4eb959 100644 --- a/include/osmocore/utils.h +++ b/include/osmocore/utils.h @@ -20,6 +20,7 @@ uint8_t char2bcd(char c); int hexparse(const char *str, uint8_t *b, int max_len); char *hexdump(const unsigned char *buf, int len); char *hexdump_nospc(const unsigned char *buf, int len); +char *bitdump(const uint8_t *bits, unsigned int len); #define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; diff --git a/src/utils.c b/src/utils.c index 405039f6..52007931 100644 --- a/src/utils.c +++ b/src/utils.c @@ -95,6 +95,36 @@ static char *_hexdump(const unsigned char *buf, int len, char *delim) return hexd_buff; } +char *bitdump(const uint8_t *bits, unsigned int len) +{ + int i; + + if (len > sizeof(hexd_buff)-1) + len = sizeof(hexd_buff)-1; + memset(hexd_buff, 0, sizeof(hexd_buff)); + + for (i = 0; i < len; i++) { + char outch; + switch (bits[i]) { + case 0: + outch = '0'; + break; + case 0xff: + outch = '?'; + break; + case 1: + outch = '1'; + break; + default: + outch = 'E'; + break; + } + hexd_buff[i] = outch; + } + hexd_buff[sizeof(hexd_buff)-1] = 0; + return hexd_buff; +} + char *hexdump(const unsigned char *buf, int len) { return _hexdump(buf, len, " "); -- cgit v1.2.3 From b05552b14c8ac5918c9d88a568bdfc85cfe45755 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 8 Feb 2011 16:56:23 +0100 Subject: [utils] introduce ubit_dump to dump buffers of unpacked bits --- include/osmocore/utils.h | 2 +- src/utils.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/osmocore/utils.h b/include/osmocore/utils.h index da4eb959..6fe1b388 100644 --- a/include/osmocore/utils.h +++ b/include/osmocore/utils.h @@ -20,7 +20,7 @@ uint8_t char2bcd(char c); int hexparse(const char *str, uint8_t *b, int max_len); char *hexdump(const unsigned char *buf, int len); char *hexdump_nospc(const unsigned char *buf, int len); -char *bitdump(const uint8_t *bits, unsigned int len); +char *ubit_dump(const uint8_t *bits, unsigned int len); #define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; diff --git a/src/utils.c b/src/utils.c index 52007931..49c210e0 100644 --- a/src/utils.c +++ b/src/utils.c @@ -95,7 +95,7 @@ static char *_hexdump(const unsigned char *buf, int len, char *delim) return hexd_buff; } -char *bitdump(const uint8_t *bits, unsigned int len) +char *ubit_dump(const uint8_t *bits, unsigned int len) { int i; -- cgit v1.2.3 From 76681bafa8013f3dac2a6b66841720e8fc78d76d Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 15 Feb 2011 00:42:19 +0100 Subject: write_queue: Only pop the queue if it is not empty It is possible that the queue is cleared after the select and before the callback for writable is called. Check if the list is not empty brefore taking an item out of it. --- src/write_queue.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/write_queue.c b/src/write_queue.c index 618a8c0b..7295569a 100644 --- a/src/write_queue.c +++ b/src/write_queue.c @@ -39,16 +39,18 @@ int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what) struct msgb *msg; fd->when &= ~BSC_FD_WRITE; - msg = msgb_dequeue(&queue->msg_queue); - if (!msg) - return -1; - --queue->current_length; - queue->write_cb(fd, msg); - msgb_free(msg); + /* the queue might have been emptied */ + if (!llist_empty(&queue->msg_queue)) { + --queue->current_length; + + msg = msgb_dequeue(&queue->msg_queue); + queue->write_cb(fd, msg); + msgb_free(msg); - if (!llist_empty(&queue->msg_queue)) - fd->when |= BSC_FD_WRITE; + if (!llist_empty(&queue->msg_queue)) + fd->when |= BSC_FD_WRITE; + } } return 0; -- cgit v1.2.3 From 76e72abe329e7b36b88a8f939593d84b2ba00152 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 17 Feb 2011 15:52:39 +0100 Subject: LOGGING: Pass the log level down to the log target output function This will be required for mapping osmocore log levels to syslog priorities. --- include/osmocore/logging.h | 3 ++- src/logging.c | 11 ++++++----- src/vty/logging_vty.c | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/include/osmocore/logging.h b/include/osmocore/logging.h index 27e77341..5b780a34 100644 --- a/include/osmocore/logging.h +++ b/include/osmocore/logging.h @@ -95,7 +95,8 @@ struct log_target { } tgt_vty; }; - void (*output) (struct log_target *target, const char *string); + void (*output) (struct log_target *target, unsigned int level, + const char *string); }; /* use the above macros */ diff --git a/src/logging.c b/src/logging.c index b3b5cb69..44528620 100644 --- a/src/logging.c +++ b/src/logging.c @@ -124,8 +124,8 @@ static const char* color(int subsys) } static void _output(struct log_target *target, unsigned int subsys, - char *file, int line, int cont, const char *format, - va_list ap) + unsigned int level, char *file, int line, int cont, + const char *format, va_list ap) { char col[30]; char sub[30]; @@ -167,7 +167,7 @@ static void _output(struct log_target *target, unsigned int subsys, snprintf(final, sizeof(final), "%s%s%s%s%s", col, tim, sub, buf, target->use_color ? "\033[0;m" : ""); final[sizeof(final)-1] = '\0'; - target->output(target, final); + target->output(target, level, final); } @@ -212,7 +212,7 @@ static void _logp(unsigned int subsys, int level, char *file, int line, * with the same va_list will segfault */ va_list bp; va_copy(bp, ap); - _output(tar, subsys, file, line, cont, format, bp); + _output(tar, subsys, level, file, line, cont, format, bp); va_end(bp); } } @@ -294,7 +294,8 @@ void log_set_category_filter(struct log_target *target, int category, target->categories[category].loglevel = level; } -static void _file_output(struct log_target *target, const char *log) +static void _file_output(struct log_target *target, unsigned int level, + const char *log) { fprintf(target->tgt_file.out, "%s", log); fflush(target->tgt_file.out); diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index ea58887a..55882a77 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -35,7 +35,8 @@ extern const struct log_info *osmo_log_info; -static void _vty_output(struct log_target *tgt, const char *line) +static void _vty_output(struct log_target *tgt, + unsigned int level, const char *line) { struct vty *vty = tgt->tgt_vty.vty; vty_out(vty, "%s", line); -- cgit v1.2.3 From 46cfd77f7521ad53934e1e42057723b4cd52d241 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 17 Feb 2011 15:56:56 +0100 Subject: LOGGING: Add syslog log target --- include/osmocore/logging.h | 2 ++ src/Makefile.am | 5 ++-- src/logging_syslog.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/logging_syslog.c diff --git a/include/osmocore/logging.h b/include/osmocore/logging.h index 5b780a34..d4d632d8 100644 --- a/include/osmocore/logging.h +++ b/include/osmocore/logging.h @@ -127,6 +127,8 @@ struct log_target *log_target_create(void); void log_target_destroy(struct log_target *target); struct log_target *log_target_create_stderr(void); struct log_target *log_target_create_file(const char *fname); +struct log_target *log_target_create_syslog(const char *ident, int option, + int facility); int log_target_file_reopen(struct log_target *tgt); void log_add_target(struct log_target *target); diff --git a/src/Makefile.am b/src/Makefile.am index d4c6e127..94492c53 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,8 +12,9 @@ lib_LTLIBRARIES = libosmocore.la libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c bits.c \ tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ - logging.c gsm0808.c rate_ctr.c gsmtap_util.c \ - gprs_cipher_core.c crc16.c panic.c process.c gsm0480.c + logging.c logging_syslog.c gsm0808.c rate_ctr.c \ + gsmtap_util.c gprs_cipher_core.c crc16.c panic.c \ + process.c gsm0480.c if ENABLE_PLUGIN libosmocore_la_SOURCES += plugin.c diff --git a/src/logging_syslog.c b/src/logging_syslog.c new file mode 100644 index 00000000..b65e8196 --- /dev/null +++ b/src/logging_syslog.c @@ -0,0 +1,72 @@ +/* Syslog logging support code */ + +/* (C) 2011 by Harald Welte + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "../config.h" + +#include +#include +#include +#include +#include + +#ifdef HAVE_STRINGS_H +#include +#endif + +#include +#include +#include + +static const int logp2syslog_level(unsigned int level) +{ + if (level >= LOGL_FATAL) + return LOG_CRIT; + else if (level >= LOGL_ERROR) + return LOG_ERR; + else if (level >= LOGL_NOTICE) + return LOG_NOTICE; + else if (level >= LOGL_INFO) + return LOG_INFO; + else + return LOG_DEBUG; +} + +static void _syslog_output(struct log_target *target, + unsigned int level, const char *log) +{ + syslog(logp2syslog_level(level), "%s", log); +} + +struct log_target *log_target_create_syslog(const char *ident, int option, + int facility) +{ + struct log_target *target; + + target = log_target_create(); + if (!target) + return NULL; + + target->output = _syslog_output; + + openlog(ident, option, facility); + + return target; +} -- cgit v1.2.3 From 2822296ddb22389c5b4e9b8fb6ef7c906ff99314 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 18 Feb 2011 20:37:04 +0100 Subject: LOGGING: configure logging from the vty We can now configure logging to (multiple) files, stderr and syslog from the vty command line in a persistent way (config file) --- configure.in | 2 +- include/osmocom/vty/command.h | 1 + include/osmocore/logging.h | 13 ++ include/osmocore/utils.h | 3 + src/logging.c | 24 ++- src/logging_syslog.c | 6 + src/utils.c | 22 +++ src/vty/Makefile.am | 2 +- src/vty/command.c | 4 + src/vty/logging_vty.c | 377 +++++++++++++++++++++++++++++++++++++++--- src/vty/vty.c | 6 + 11 files changed, 433 insertions(+), 27 deletions(-) diff --git a/configure.in b/configure.in index 309aa034..165cecb7 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ AC_CONFIG_MACRO_DIR([m4]) dnl checks for header files AC_HEADER_STDC -AC_CHECK_HEADERS(execinfo.h sys/select.h) +AC_CHECK_HEADERS(execinfo.h sys/select.h syslog.h ctype.h) # The following test is taken from WebKit's webkit.m4 saved_CFLAGS="$CFLAGS" diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h index 69e9e772..caf04142 100644 --- a/include/osmocom/vty/command.h +++ b/include/osmocom/vty/command.h @@ -70,6 +70,7 @@ enum node_type { CONFIG_NODE, /* Config node. Default mode of config file. */ SERVICE_NODE, /* Service node. */ DEBUG_NODE, /* Debug node. */ + CFG_LOG_NODE, /* Configure the logging */ VTY_NODE, /* Vty node. */ diff --git a/include/osmocore/logging.h b/include/osmocore/logging.h index d4d632d8..a2c63e9a 100644 --- a/include/osmocore/logging.h +++ b/include/osmocore/logging.h @@ -69,6 +69,13 @@ struct log_info { unsigned int num_cat; }; +enum log_target_type { + LOG_TGT_TYPE_VTY, + LOG_TGT_TYPE_SYSLOG, + LOG_TGT_TYPE_FILE, + LOG_TGT_TYPE_STDERR, +}; + struct log_target { struct llist_head entry; @@ -80,6 +87,8 @@ struct log_target { int use_color:1; int print_timestamp:1; + enum log_target_type type; + union { struct { FILE *out; @@ -88,6 +97,7 @@ struct log_target { struct { int priority; + int facility; } tgt_syslog; struct { @@ -138,4 +148,7 @@ void log_del_target(struct log_target *target); const char *log_vty_category_string(struct log_info *info); const char *log_vty_level_string(struct log_info *info); +struct log_target *log_target_find(int type, const char *fname); +extern struct llist_head osmo_log_target_list; + #endif /* _OSMOCORE_LOGGING_H */ diff --git a/include/osmocore/utils.h b/include/osmocore/utils.h index 6fe1b388..0cdf03b8 100644 --- a/include/osmocore/utils.h +++ b/include/osmocore/utils.h @@ -24,4 +24,7 @@ char *ubit_dump(const uint8_t *bits, unsigned int len); #define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; +void osmo_str2lower(char *out, const char *in); +void osmo_str2upper(char *out, const char *in); + #endif diff --git a/src/logging.c b/src/logging.c index 44528620..876a3526 100644 --- a/src/logging.c +++ b/src/logging.c @@ -41,7 +41,7 @@ const struct log_info *osmo_log_info; static struct log_context log_context; static void *tall_log_ctx = NULL; -static LLIST_HEAD(target_list); +LLIST_HEAD(osmo_log_target_list); static const struct value_string loglevel_strs[] = { { 0, "EVERYTHING" }, @@ -176,7 +176,7 @@ static void _logp(unsigned int subsys, int level, char *file, int line, { struct log_target *tar; - llist_for_each_entry(tar, &target_list, entry) { + llist_for_each_entry(tar, &osmo_log_target_list, entry) { struct log_category *category; int output = 0; @@ -239,7 +239,7 @@ void logp2(unsigned int subsys, unsigned int level, char *file, int line, int co void log_add_target(struct log_target *target) { - llist_add_tail(&target->entry, &target_list); + llist_add_tail(&target->entry, &osmo_log_target_list); } void log_del_target(struct log_target *target) @@ -338,6 +338,7 @@ struct log_target *log_target_create_stderr(void) if (!target) return NULL; + target->type = LOG_TGT_TYPE_STDERR; target->tgt_file.out = stderr; target->output = _file_output; return target; @@ -354,6 +355,7 @@ struct log_target *log_target_create_file(const char *fname) if (!target) return NULL; + target->type = LOG_TGT_TYPE_FILE; target->tgt_file.out = fopen(fname, "a"); if (!target->tgt_file.out) return NULL; @@ -365,6 +367,22 @@ struct log_target *log_target_create_file(const char *fname) return target; } +struct log_target *log_target_find(int type, const char *fname) +{ + struct log_target *tgt; + + llist_for_each_entry(tgt, &osmo_log_target_list, entry) { + if (tgt->type != type) + continue; + if (tgt->type == LOG_TGT_TYPE_FILE) { + if (!strcmp(fname, tgt->tgt_file.fname)) + return tgt; + } else + return tgt; + } + return NULL; +} + void log_target_destroy(struct log_target *target) { diff --git a/src/logging_syslog.c b/src/logging_syslog.c index b65e8196..b558fc0b 100644 --- a/src/logging_syslog.c +++ b/src/logging_syslog.c @@ -21,6 +21,8 @@ #include "../config.h" +#ifdef HAVE_SYSLOG_H + #include #include #include @@ -64,9 +66,13 @@ struct log_target *log_target_create_syslog(const char *ident, int option, if (!target) return NULL; + target->tgt_syslog.facility = facility; + target->type = LOG_TGT_TYPE_SYSLOG; target->output = _syslog_output; openlog(ident, option, facility); return target; } + +#endif /* HAVE_SYSLOG_H */ diff --git a/src/utils.c b/src/utils.c index 49c210e0..354fce57 100644 --- a/src/utils.c +++ b/src/utils.c @@ -134,3 +134,25 @@ char *hexdump_nospc(const unsigned char *buf, int len) { return _hexdump(buf, len, ""); } + +#include "../config.h" +#ifdef HAVE_CTYPE_H +#include +void osmo_str2lower(char *out, const char *in) +{ + unsigned int i; + + for (i = 0; i < strlen(in); i++) + out[i] = tolower(in[i]); + out[strlen(in)] = '\0'; +} + +void osmo_str2upper(char *out, const char *in) +{ + unsigned int i; + + for (i = 0; i < strlen(in); i++) + out[i] = toupper(in[i]); + out[strlen(in)] = '\0'; +} +#endif /* HAVE_CTYPE_H */ diff --git a/src/vty/Makefile.am b/src/vty/Makefile.am index 7353ab84..8d730c3c 100644 --- a/src/vty/Makefile.am +++ b/src/vty/Makefile.am @@ -10,5 +10,5 @@ lib_LTLIBRARIES = libosmovty.la libosmovty_la_SOURCES = buffer.c command.c vty.c vector.c utils.c \ telnet_interface.c logging_vty.c -libosmovty_la_LIBADD = $(top_builddir)/src/libosmocore.la +libosmovty_la_LIBADD = -losmocore $(top_builddir)/src/libosmocore.la endif diff --git a/src/vty/command.c b/src/vty/command.c index 7525df65..0f65224f 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -2180,6 +2180,9 @@ gDEFUN(config_exit, case VTY_NODE: vty->node = CONFIG_NODE; break; + case CFG_LOG_NODE: + vty->node = CONFIG_NODE; + break; default: break; } @@ -2195,6 +2198,7 @@ gDEFUN(config_exit, case ENABLE_NODE: /* Nothing to do. */ break; + case CFG_LOG_NODE: case CONFIG_NODE: case VTY_NODE: vty_config_unlock(vty); diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 55882a77..b51be7d6 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -22,8 +22,11 @@ #include #include +#include "../../config.h" + #include #include +#include //#include @@ -33,6 +36,8 @@ #include #include +#define LOG_STR "Configure logging sub-system\n" + extern const struct log_info *osmo_log_info; static void _vty_output(struct log_target *tgt, @@ -179,46 +184,54 @@ DEFUN(logging_prnt_timestamp, "Log noticable messages and higher levels\n" \ "Log error messages and higher levels\n" \ "Log only fatal messages\n" -DEFUN(logging_level, - logging_level_cmd, - "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, - LOGGING_STR - "Set the log level for a specified category\n" - CATEGORIES_HELP - LEVELS_HELP) -{ - struct telnet_connection *conn; - int category = log_parse_category(argv[0]); - int level = log_parse_level(argv[1]); - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } +static int _logging_level(struct vty *vty, struct log_target *dbg, + const char *cat_str, const char *lvl_str) +{ + int category = log_parse_category(cat_str); + int level = log_parse_level(lvl_str); if (level < 0) { - vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE); + vty_out(vty, "Invalid level `%s'%s", lvl_str, VTY_NEWLINE); return CMD_WARNING; } /* Check for special case where we want to set global log level */ - if (!strcmp(argv[0], "all")) { - log_set_log_level(conn->dbg, level); + if (!strcmp(cat_str, "all")) { + log_set_log_level(dbg, level); return CMD_SUCCESS; } if (category < 0) { - vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE); + vty_out(vty, "Invalid category `%s'%s", cat_str, VTY_NEWLINE); return CMD_WARNING; } - conn->dbg->categories[category].enabled = 1; - conn->dbg->categories[category].loglevel = level; + dbg->categories[category].enabled = 1; + dbg->categories[category].loglevel = level; return CMD_SUCCESS; } +DEFUN(logging_level, + logging_level_cmd, + "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, + LOGGING_STR + "Set the log level for a specified category\n" + CATEGORIES_HELP + LEVELS_HELP) +{ + struct telnet_connection *conn; + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) { + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return _logging_level(vty, conn->dbg, argv[0], argv[1]); +} + DEFUN(logging_set_category_mask, logging_set_category_mask_cmd, "logging set log mask MASK", @@ -338,6 +351,310 @@ gDEFUN(cfg_no_description, cfg_no_description_cmd, return CMD_SUCCESS; } +/* Support for configuration of log targets != the current vty */ + +struct cmd_node cfg_log_node = { + CFG_LOG_NODE, + "%s(config-log)# ", + 1 +}; + +DEFUN(cfg_log_fltr_all, + cfg_log_fltr_all_cmd, + "logging filter all (0|1)", + LOGGING_STR FILTER_STR + "Do you want to log all messages?\n" + "Only print messages matched by other filters\n" + "Bypass filter and print all messages\n") +{ + struct log_target *dbg = vty->index; + + log_set_all_filter(dbg, atoi(argv[0])); + return CMD_SUCCESS; +} + +DEFUN(cfg_log_use_clr, + cfg_log_use_clr_cmd, + "logging color (0|1)", + LOGGING_STR "Configure color-printing for log messages\n" + "Don't use color for printing messages\n" + "Use color for printing messages\n") +{ + struct log_target *dbg = vty->index; + + log_set_use_color(dbg, atoi(argv[0])); + return CMD_SUCCESS; +} + +DEFUN(cfg_log_timestamp, + cfg_log_timestamp_cmd, + "logging timestamp (0|1)", + LOGGING_STR "Configure log message timestamping\n" + "Don't prefix each log message\n" + "Prefix each log message with current timestamp\n") +{ + struct log_target *dbg = vty->index; + + log_set_print_timestamp(dbg, atoi(argv[0])); + return CMD_SUCCESS; +} + +DEFUN(cfg_log_level, + cfg_log_level_cmd, + "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, + LOGGING_STR + "Set the log level for a specified category\n" + CATEGORIES_HELP + LEVELS_HELP) +{ + struct log_target *dbg = vty->index; + + return _logging_level(vty, dbg, argv[0], argv[1]); +} + +#ifdef HAVE_SYSLOG_H + +#include + +static const int local_sysl_map[] = { + [0] = LOG_LOCAL0, + [1] = LOG_LOCAL1, + [2] = LOG_LOCAL2, + [3] = LOG_LOCAL3, + [4] = LOG_LOCAL4, + [5] = LOG_LOCAL5, + [6] = LOG_LOCAL6, + [7] = LOG_LOCAL7 +}; + +static int _cfg_log_syslog(struct vty *vty, int facility) +{ + struct log_target *tgt; + + /* First delete the old syslog target, if any */ + tgt = log_target_find(LOG_TGT_TYPE_SYSLOG, NULL); + if (tgt) + log_target_destroy(tgt); + + tgt = log_target_create_syslog("FIXME", 0, facility); + if (!tgt) { + vty_out(vty, "%% Unable to open syslog%s", VTY_NEWLINE); + return CMD_WARNING; + } + log_add_target(tgt); + + vty->index = tgt; + vty->node = CFG_LOG_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_log_syslog_local, cfg_log_syslog_local_cmd, + "log syslog local <0-7>", + LOG_STR "Logging via syslog\n" "Syslog LOCAL facility\n" + "Local facility number\n") +{ + int local = atoi(argv[0]); + int facility = local_sysl_map[local]; + + return _cfg_log_syslog(vty, facility); +} + +static struct value_string sysl_level_names[] = { + { LOG_AUTHPRIV, "authpriv" }, + { LOG_CRON, "cron" }, + { LOG_DAEMON, "daemon" }, + { LOG_FTP, "ftp" }, + { LOG_LPR, "lpr" }, + { LOG_MAIL, "mail" }, + { LOG_NEWS, "news" }, + { LOG_USER, "user" }, + { LOG_UUCP, "uucp" }, + /* only for value -> string conversion */ + { LOG_LOCAL0, "local 0" }, + { LOG_LOCAL1, "local 1" }, + { LOG_LOCAL2, "local 2" }, + { LOG_LOCAL3, "local 3" }, + { LOG_LOCAL4, "local 4" }, + { LOG_LOCAL5, "local 5" }, + { LOG_LOCAL6, "local 6" }, + { LOG_LOCAL7, "local 7" }, + { 0, NULL } +}; + +DEFUN(cfg_log_syslog, cfg_log_syslog_cmd, + "log syslog (authpriv|cron|daemon|ftp|lpr|mail|news|user|uucp)", + LOG_STR "Logging via syslog\n") +{ + int facility = get_string_value(sysl_level_names, argv[0]); + + return _cfg_log_syslog(vty, facility); +} + +DEFUN(cfg_no_log_syslog, cfg_no_log_syslog_cmd, + "no log syslog", + NO_STR LOG_STR "Logging via syslog\n") +{ + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_SYSLOG, NULL); + if (!tgt) { + vty_out(vty, "%% No syslog target found%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + log_target_destroy(tgt); + + return CMD_SUCCESS; +} +#endif /* HAVE_SYSLOG_H */ + +DEFUN(cfg_log_stderr, cfg_log_stderr_cmd, + "log stderr", + LOG_STR "Logging via STDERR of the process\n") +{ + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_STDERR, NULL); + if (!tgt) { + tgt = log_target_create_stderr(); + if (!tgt) { + vty_out(vty, "%% Unable to create stderr log%s", + VTY_NEWLINE); + return CMD_WARNING; + } + log_add_target(tgt); + } + + vty->index = tgt; + vty->node = CFG_LOG_NODE; + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_log_stderr, cfg_no_log_stderr_cmd, + "no log stderr", + NO_STR LOG_STR "Logging via STDERR of the process\n") +{ + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_STDERR, NULL); + if (!tgt) { + vty_out(vty, "%% No stderr logging active%s", VTY_NEWLINE); + return CMD_WARNING; + } + + log_target_destroy(tgt); + + return CMD_SUCCESS; +} + +DEFUN(cfg_log_file, cfg_log_file_cmd, + "log file .FILENAME", + LOG_STR "Logging to text file\n" "Filename\n") +{ + const char *fname = argv[0]; + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_FILE, fname); + if (!tgt) { + tgt = log_target_create_file(fname); + if (!tgt) { + vty_out(vty, "%% Unable to create file `%s'%s", + fname, VTY_NEWLINE); + return CMD_WARNING; + } + log_add_target(tgt); + } + + vty->index = tgt; + vty->node = CFG_LOG_NODE; + + return CMD_SUCCESS; +} + + +DEFUN(cfg_no_log_file, cfg_no_log_file_cmd, + "no log file .FILENAME", + NO_STR LOG_STR "Logging to text file\n" "Filename\n") +{ + const char *fname = argv[0]; + struct log_target *tgt; + + tgt = log_target_find(LOG_TGT_TYPE_FILE, fname); + if (!tgt) { + vty_out(vty, "%% No such log file `%s'%s", + fname, VTY_NEWLINE); + return CMD_WARNING; + } + + log_target_destroy(tgt); + + return CMD_SUCCESS; +} + +static int config_write_log_single(struct vty *vty, struct log_target *tgt) +{ + int i; + char level_lower[32]; + + switch (tgt->type) { + case LOG_TGT_TYPE_VTY: + return 1; + break; + case LOG_TGT_TYPE_STDERR: + vty_out(vty, "log stderr%s", VTY_NEWLINE); + break; + case LOG_TGT_TYPE_SYSLOG: +#ifdef HAVE_SYSLOG_H + vty_out(vty, "log syslog %s%s", + get_value_string(sysl_level_names, + tgt->tgt_syslog.facility), + VTY_NEWLINE); +#endif + break; + case LOG_TGT_TYPE_FILE: + vty_out(vty, "log file %s%s", tgt->tgt_file.fname, VTY_NEWLINE); + break; + } + + vty_out(vty, " logging color %u%s", tgt->use_color ? 1 : 0, + VTY_NEWLINE); + vty_out(vty, " logging timestamp %u%s", tgt->print_timestamp ? 1 : 0, + VTY_NEWLINE); + + /* stupid old osmo logging API uses uppercase strings... */ + osmo_str2lower(level_lower, log_level_str(tgt->loglevel)); + vty_out(vty, " logging level all %s%s", level_lower, VTY_NEWLINE); + + for (i = 0; i < osmo_log_info->num_cat; i++) { + const struct log_category *cat = &tgt->categories[i]; + char cat_lower[32]; + + /* stupid old osmo logging API uses uppercase strings... */ + osmo_str2lower(cat_lower, osmo_log_info->cat[i].name+1); + osmo_str2lower(level_lower, log_level_str(cat->loglevel)); + + vty_out(vty, " logging level %s %s%s", cat_lower, level_lower, + VTY_NEWLINE); + } + + /* FIXME: levels */ + + return 1; +} + +static int config_write_log(struct vty *vty) +{ + struct log_target *dbg = vty->index; + + llist_for_each_entry(dbg, &osmo_log_target_list, entry) + config_write_log_single(vty, dbg); + + return 1; +} + void logging_vty_add_cmds() { install_element_ve(&enable_logging_cmd); @@ -348,4 +665,20 @@ void logging_vty_add_cmds() install_element_ve(&logging_set_category_mask_cmd); install_element_ve(&logging_level_cmd); install_element_ve(&show_logging_vty_cmd); + + install_node(&cfg_log_node, config_write_log); + install_element(CFG_LOG_NODE, &cfg_log_fltr_all_cmd); + install_element(CFG_LOG_NODE, &cfg_log_use_clr_cmd); + install_element(CFG_LOG_NODE, &cfg_log_timestamp_cmd); + install_element(CFG_LOG_NODE, &cfg_log_level_cmd); + + install_element(CONFIG_NODE, &cfg_log_stderr_cmd); + install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd); + install_element(CONFIG_NODE, &cfg_log_file_cmd); + install_element(CONFIG_NODE, &cfg_no_log_file_cmd); +#ifdef HAVE_SYSLOG_H + install_element(CONFIG_NODE, &cfg_log_syslog_cmd); + install_element(CONFIG_NODE, &cfg_log_syslog_local_cmd); + install_element(CONFIG_NODE, &cfg_no_log_syslog_cmd); +#endif } diff --git a/src/vty/vty.c b/src/vty/vty.c index a5b16dce..c1a9b3af 100644 --- a/src/vty/vty.c +++ b/src/vty/vty.c @@ -765,6 +765,9 @@ static void vty_end_config(struct vty *vty) vty_config_unlock(vty); vty->node = ENABLE_NODE; break; + case CFG_LOG_NODE: + vty->node = CONFIG_NODE; + break; default: /* Unknown node, we have to ignore it. */ break; @@ -1129,6 +1132,9 @@ static void vty_stop_input(struct vty *vty) vty_config_unlock(vty); vty->node = ENABLE_NODE; break; + case CFG_LOG_NODE: + vty->node = CONFIG_NODE; + break; default: /* Unknown node, we have to ignore it. */ break; -- cgit v1.2.3 From 6b431033b3118b1893a94735292143f6c67cfd20 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 18 Feb 2011 20:39:36 +0100 Subject: LOGGING: Add missing 'nat' subsystem --- src/vty/logging_vty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index b51be7d6..b6eb0c6d 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -144,7 +144,7 @@ DEFUN(logging_prnt_timestamp, } /* FIXME: those have to be kept in sync with the log levels and categories */ -#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|gprs|ns|bssgp|llc|sndcp|isup|m2ua|pcap|all)" +#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|gprs|ns|bssgp|llc|sndcp|isup|m2ua|pcap|nat|all)" #define CATEGORIES_HELP \ "A-bis Radio Link Layer (RLL)\n" \ "Layer3 Call Control (CC)\n" \ @@ -174,6 +174,7 @@ DEFUN(logging_prnt_timestamp, "ISDN User Part (ISUP)\n" \ "SCTP M2UA\n" \ "Trace message IO\n" \ + "BSC NAT\n" \ "Global setting for all subsytems\n" #define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)" -- cgit v1.2.3 From a62648b0b05f80c97ac470f114024c7c8eee7e9a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 18 Feb 2011 21:03:27 +0100 Subject: LOGGING: remove duplicated code between vty-logging and cfg-logging --- include/osmocom/vty/logging.h | 2 + src/vty/logging_vty.c | 183 ++++++++++++++---------------------------- 2 files changed, 62 insertions(+), 123 deletions(-) diff --git a/include/osmocom/vty/logging.h b/include/osmocom/vty/logging.h index 45d74fdf..f4e28f88 100644 --- a/include/osmocom/vty/logging.h +++ b/include/osmocom/vty/logging.h @@ -6,4 +6,6 @@ void logging_vty_add_cmds(void); +struct log_target *osmo_log_vty2tgt(struct vty *vty); + #endif /* _VTY_LOGGING_H */ diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index b6eb0c6d..4c46c68e 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -85,6 +85,21 @@ DEFUN(enable_logging, return CMD_SUCCESS; } +struct log_target *osmo_log_vty2tgt(struct vty *vty) +{ + struct telnet_connection *conn; + + if (vty->node == CFG_LOG_NODE) + return vty->index; + + + conn = (struct telnet_connection *) vty->priv; + if (!conn->dbg) + vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + + return conn->dbg; +} + DEFUN(logging_fltr_all, logging_fltr_all_cmd, "logging filter all (0|1)", @@ -93,15 +108,12 @@ DEFUN(logging_fltr_all, "Only print messages matched by other filters\n" "Bypass filter and print all messages\n") { - struct telnet_connection *conn; + struct log_target *tgt = osmo_log_vty2tgt(vty); - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + if (!tgt) return CMD_WARNING; - } - log_set_all_filter(conn->dbg, atoi(argv[0])); + log_set_all_filter(tgt, atoi(argv[0])); return CMD_SUCCESS; } @@ -112,15 +124,12 @@ DEFUN(logging_use_clr, "Don't use color for printing messages\n" "Use color for printing messages\n") { - struct telnet_connection *conn; + struct log_target *tgt = osmo_log_vty2tgt(vty); - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + if (!tgt) return CMD_WARNING; - } - log_set_use_color(conn->dbg, atoi(argv[0])); + log_set_use_color(tgt, atoi(argv[0])); return CMD_SUCCESS; } @@ -131,15 +140,12 @@ DEFUN(logging_prnt_timestamp, "Don't prefix each log message\n" "Prefix each log message with current timestamp\n") { - struct telnet_connection *conn; + struct log_target *tgt = osmo_log_vty2tgt(vty); - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + if (!tgt) return CMD_WARNING; - } - log_set_print_timestamp(conn->dbg, atoi(argv[0])); + log_set_print_timestamp(tgt, atoi(argv[0])); return CMD_SUCCESS; } @@ -186,68 +192,55 @@ DEFUN(logging_prnt_timestamp, "Log error messages and higher levels\n" \ "Log only fatal messages\n" -static int _logging_level(struct vty *vty, struct log_target *dbg, - const char *cat_str, const char *lvl_str) +DEFUN(logging_level, + logging_level_cmd, + "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, + LOGGING_STR + "Set the log level for a specified category\n" + CATEGORIES_HELP + LEVELS_HELP) { - int category = log_parse_category(cat_str); - int level = log_parse_level(lvl_str); + int category = log_parse_category(argv[0]); + int level = log_parse_level(argv[1]); + struct log_target *tgt = osmo_log_vty2tgt(vty); + + if (!tgt) + return CMD_WARNING; if (level < 0) { - vty_out(vty, "Invalid level `%s'%s", lvl_str, VTY_NEWLINE); + vty_out(vty, "Invalid level `%s'%s", argv[1], VTY_NEWLINE); return CMD_WARNING; } /* Check for special case where we want to set global log level */ - if (!strcmp(cat_str, "all")) { - log_set_log_level(dbg, level); + if (!strcmp(argv[0], "all")) { + log_set_log_level(tgt, level); return CMD_SUCCESS; } if (category < 0) { - vty_out(vty, "Invalid category `%s'%s", cat_str, VTY_NEWLINE); + vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } - dbg->categories[category].enabled = 1; - dbg->categories[category].loglevel = level; + tgt->categories[category].enabled = 1; + tgt->categories[category].loglevel = level; return CMD_SUCCESS; } -DEFUN(logging_level, - logging_level_cmd, - "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, - LOGGING_STR - "Set the log level for a specified category\n" - CATEGORIES_HELP - LEVELS_HELP) -{ - struct telnet_connection *conn; - - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); - return CMD_WARNING; - } - - return _logging_level(vty, conn->dbg, argv[0], argv[1]); -} - DEFUN(logging_set_category_mask, logging_set_category_mask_cmd, "logging set log mask MASK", LOGGING_STR "Decide which categories to output.\n") { - struct telnet_connection *conn; + struct log_target *tgt = osmo_log_vty2tgt(vty); - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + if (!tgt) return CMD_WARNING; - } - log_parse_category_mask(conn->dbg, argv[0]); + log_parse_category_mask(tgt, argv[0]); return CMD_SUCCESS; } @@ -257,17 +250,16 @@ DEFUN(diable_logging, LOGGING_STR "Disables logging to this vty\n") { - struct telnet_connection *conn; + struct log_target *tgt = osmo_log_vty2tgt(vty); + struct telnet_connection *conn = (struct telnet_connection *) vty->priv; - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + if (!tgt) return CMD_WARNING; - } - log_del_target(conn->dbg); - talloc_free(conn->dbg); + log_del_target(tgt); + talloc_free(tgt); conn->dbg = NULL; + return CMD_SUCCESS; } @@ -302,14 +294,12 @@ DEFUN(show_logging_vty, SHOW_STR SHOW_LOG_STR "Show current logging configuration for this vty\n") { - struct telnet_connection *conn; + struct log_target *tgt = osmo_log_vty2tgt(vty); - conn = (struct telnet_connection *) vty->priv; - if (!conn->dbg) { - vty_out(vty, "Logging was not enabled.%s", VTY_NEWLINE); + if (!tgt) return CMD_WARNING; - } - vty_print_logtarget(vty, osmo_log_info, conn->dbg); + + vty_print_logtarget(vty, osmo_log_info, tgt); return CMD_SUCCESS; } @@ -360,59 +350,6 @@ struct cmd_node cfg_log_node = { 1 }; -DEFUN(cfg_log_fltr_all, - cfg_log_fltr_all_cmd, - "logging filter all (0|1)", - LOGGING_STR FILTER_STR - "Do you want to log all messages?\n" - "Only print messages matched by other filters\n" - "Bypass filter and print all messages\n") -{ - struct log_target *dbg = vty->index; - - log_set_all_filter(dbg, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(cfg_log_use_clr, - cfg_log_use_clr_cmd, - "logging color (0|1)", - LOGGING_STR "Configure color-printing for log messages\n" - "Don't use color for printing messages\n" - "Use color for printing messages\n") -{ - struct log_target *dbg = vty->index; - - log_set_use_color(dbg, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(cfg_log_timestamp, - cfg_log_timestamp_cmd, - "logging timestamp (0|1)", - LOGGING_STR "Configure log message timestamping\n" - "Don't prefix each log message\n" - "Prefix each log message with current timestamp\n") -{ - struct log_target *dbg = vty->index; - - log_set_print_timestamp(dbg, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(cfg_log_level, - cfg_log_level_cmd, - "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, - LOGGING_STR - "Set the log level for a specified category\n" - CATEGORIES_HELP - LEVELS_HELP) -{ - struct log_target *dbg = vty->index; - - return _logging_level(vty, dbg, argv[0], argv[1]); -} - #ifdef HAVE_SYSLOG_H #include @@ -668,10 +605,10 @@ void logging_vty_add_cmds() install_element_ve(&show_logging_vty_cmd); install_node(&cfg_log_node, config_write_log); - install_element(CFG_LOG_NODE, &cfg_log_fltr_all_cmd); - install_element(CFG_LOG_NODE, &cfg_log_use_clr_cmd); - install_element(CFG_LOG_NODE, &cfg_log_timestamp_cmd); - install_element(CFG_LOG_NODE, &cfg_log_level_cmd); + install_element(CFG_LOG_NODE, &logging_fltr_all_cmd); + install_element(CFG_LOG_NODE, &logging_use_clr_cmd); + install_element(CFG_LOG_NODE, &logging_prnt_timestamp_cmd); + install_element(CFG_LOG_NODE, &logging_level_cmd); install_element(CONFIG_NODE, &cfg_log_stderr_cmd); install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd); -- cgit v1.2.3 From 49cc32b0a3ceee4dad17d2910b7e9de29ac65db7 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 19 Feb 2011 16:10:51 +0900 Subject: vty: Revert Makefile.am change for libosmocore dependency --- src/vty/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vty/Makefile.am b/src/vty/Makefile.am index 8d730c3c..7353ab84 100644 --- a/src/vty/Makefile.am +++ b/src/vty/Makefile.am @@ -10,5 +10,5 @@ lib_LTLIBRARIES = libosmovty.la libosmovty_la_SOURCES = buffer.c command.c vty.c vector.c utils.c \ telnet_interface.c logging_vty.c -libosmovty_la_LIBADD = -losmocore $(top_builddir)/src/libosmocore.la +libosmovty_la_LIBADD = $(top_builddir)/src/libosmocore.la endif -- cgit v1.2.3 From 7c3b8fb441943a47a4fb57ee67251c24c84e41ee Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 19 Feb 2011 16:35:47 +0100 Subject: rxlev_stat: Fix compiler warning --- src/rxlev_stat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rxlev_stat.c b/src/rxlev_stat.c index 1bfd6795..b474aaa8 100644 --- a/src/rxlev_stat.c +++ b/src/rxlev_stat.c @@ -68,7 +68,7 @@ int16_t rxlev_stat_get_next(const struct rxlev_stats *st, uint8_t rxlev, int16_t if (arfcn < 0) arfcn = -1; - bv.data = st->rxlev_buckets[rxlev]; + bv.data = (uint8_t *) st->rxlev_buckets[rxlev]; return bitvec_find_bit_pos(&bv, arfcn+1, ONE); } -- cgit v1.2.3 From de79cee5a60e91b7fdc266f59dc8e43acd366ce6 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 24 Feb 2011 23:47:57 +0100 Subject: LOGGING: Use host.app_info->name instead of FIXME This should put a useful syslog identity in place. --- src/vty/logging_vty.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 4c46c68e..904f8fec 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -365,6 +365,9 @@ static const int local_sysl_map[] = { [7] = LOG_LOCAL7 }; +/* From VTY core code */ +extern struct host host; + static int _cfg_log_syslog(struct vty *vty, int facility) { struct log_target *tgt; @@ -374,7 +377,7 @@ static int _cfg_log_syslog(struct vty *vty, int facility) if (tgt) log_target_destroy(tgt); - tgt = log_target_create_syslog("FIXME", 0, facility); + tgt = log_target_create_syslog(host.app_info->name, 0, facility); if (!tgt) { vty_out(vty, "%% Unable to open syslog%s", VTY_NEWLINE); return CMD_WARNING; -- cgit v1.2.3 From 63196de6d899d01c4e1899e3aab2e700a47a196d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 5 Mar 2011 14:32:50 +0100 Subject: TLV: Add tv_fixed_put() and msgb_tv_fixed_put() This is for a Tag-Value type with fixed-length value (len > 1) --- include/osmocore/tlv.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/osmocore/tlv.h b/include/osmocore/tlv.h index 4cfce872..7bda9f92 100644 --- a/include/osmocore/tlv.h +++ b/include/osmocore/tlv.h @@ -132,6 +132,14 @@ static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag, return buf; } +static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag, + unsigned int len, const uint8_t *val) +{ + *buf++ = tag; + memcpy(buf, val, len); + return buf + len; +} + /* 'val' is still in host byte order! */ static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag, uint16_t val) @@ -160,6 +168,13 @@ static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val) return tv_put(buf, tag, val); } +static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag, + unsigned int len, const uint8_t *val) +{ + uint8_t *buf = msgb_put(msg, 1+len); + return tv_fixed_put(buf, tag, len, val); +} + static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val) { uint8_t *buf = msgb_put(msg, 1); -- cgit v1.2.3 From 04139f14b6197e3ec996133a945af3fa8a68fb7a Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 9 Mar 2011 13:05:08 +0100 Subject: vty: integration with logging framework The logging categories are registered by the applications, like osmo-nitb, during startup. Thus, the VTY have to provide the logging commands according to the logging categories that the application has registered. Before this patch, the VTY contained the logging categories hardcoded. Thus, any change in the logging categories by the application would not be shown by the VTY. So far, this was not a problem because all applications used the same logging categories. However, according to what Harald told me, this may be a problem in the future. This patch resolve the lack of integration between the logging framework and the VTY by generating the VTY logging commands from the logging categories registered. Since this patch changes one function of the libosmocore API, it follows another patch for the openbsc application to get in sync with the new function layout. I have reworked and renamed the functions: * log_vty_category_string() * log_vty_level_string() to provide the new ones that generate the exact output that VTY requires. This patch does not release the memory allocated by talloc_zero_size() to store the VTY strings for the commands and the description. I found no exit function that can clean up resources that were allocated. --- include/osmocom/vty/logging.h | 5 +- include/osmocore/logging.h | 6 +- src/logging.c | 138 +++++++++++++++++++++++++++++++++++------- src/vty/logging_vty.c | 56 +++-------------- 4 files changed, 128 insertions(+), 77 deletions(-) diff --git a/include/osmocom/vty/logging.h b/include/osmocom/vty/logging.h index f4e28f88..e0011bf9 100644 --- a/include/osmocom/vty/logging.h +++ b/include/osmocom/vty/logging.h @@ -4,8 +4,9 @@ #define LOGGING_STR "Configure log message to this terminal\n" #define FILTER_STR "Filter log messages\n" -void logging_vty_add_cmds(void); - +struct log_info; +void logging_vty_add_cmds(const struct log_info *cat); +struct vty; struct log_target *osmo_log_vty2tgt(struct vty *vty); #endif /* _VTY_LOGGING_H */ diff --git a/include/osmocore/logging.h b/include/osmocore/logging.h index a2c63e9a..fd458440 100644 --- a/include/osmocore/logging.h +++ b/include/osmocore/logging.h @@ -144,9 +144,9 @@ int log_target_file_reopen(struct log_target *tgt); void log_add_target(struct log_target *target); void log_del_target(struct log_target *target); -/* Gernerate command argument strings for VTY use */ -const char *log_vty_category_string(struct log_info *info); -const char *log_vty_level_string(struct log_info *info); +/* Generate command string for VTY use */ +const char *log_vty_command_string(const struct log_info *info); +const char *log_vty_command_description(const struct log_info *info); struct log_target *log_target_find(int type, const char *fname); extern struct llist_head osmo_log_target_list; diff --git a/src/logging.c b/src/logging.c index 876a3526..89ca6ced 100644 --- a/src/logging.c +++ b/src/logging.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef HAVE_STRINGS_H #include @@ -37,13 +38,17 @@ #include #include +#include /* for LOGGING_STR. */ + const struct log_info *osmo_log_info; static struct log_context log_context; static void *tall_log_ctx = NULL; LLIST_HEAD(osmo_log_target_list); -static const struct value_string loglevel_strs[] = { +#define LOGLEVEL_DEFS 6 /* Number of loglevels.*/ + +static const struct value_string loglevel_strs[LOGLEVEL_DEFS+1] = { { 0, "EVERYTHING" }, { LOGL_DEBUG, "DEBUG" }, { LOGL_INFO, "INFO" }, @@ -53,6 +58,17 @@ static const struct value_string loglevel_strs[] = { { 0, NULL }, }; +/* You have to keep this in sync with the structure loglevel_strs. */ +const char *loglevel_descriptions[LOGLEVEL_DEFS+1] = { + "Log simply everything", + "Log debug messages and higher levels", + "Log informational messages and higher levels", + "Log noticable messages and higher levels", + "Log error messages and higher levels", + "Log only fatal messages", + NULL, +}; + int log_parse_level(const char *lvl) { return get_string_value(loglevel_strs, lvl); @@ -418,49 +434,125 @@ int log_target_file_reopen(struct log_target *target) return 0; } -const char *log_vty_level_string(struct log_info *info) +/* This can go into some header file so others can benefit from it. */ +#define SNPRINTF_FAILURE(ret, rem, offset, len) \ +do { \ + len += ret; \ + if (ret > rem) \ + ret = rem; \ + offset += ret; \ + rem -= ret; \ +} while (0) + +/* This generates the logging command string for VTY. */ +const char *log_vty_command_string(const struct log_info *info) { - const struct value_string *vs; - unsigned int len = 3; /* ()\0 */ + int len = 0, offset = 0, ret, i, rem; + int size = strlen("logging level () ()") + 1; char *str; - for (vs = loglevel_strs; vs->value || vs->str; vs++) - len += strlen(vs->str) + 1; + for (i = 0; i < info->num_cat; i++) + size += strlen(info->cat[i].name) + 1; - str = talloc_zero_size(NULL, len); + for (i = 0; i < LOGLEVEL_DEFS; i++) + size += strlen(loglevel_strs[i].str) + 1; + + rem = size; + str = talloc_zero_size(NULL, size); if (!str) return NULL; - str[0] = '('; - for (vs = loglevel_strs; vs->value || vs->str; vs++) { - strcat(str, vs->str); - strcat(str, "|"); - } - str[strlen(str)-1] = ')'; + ret = snprintf(str + offset, rem, "logging level ("); + if (ret < 0) + goto err; + SNPRINTF_FAILURE(ret, rem, offset, len); + + for (i = 0; i < info->num_cat; i++) { + int j, name_len = strlen(info->cat[i].name)+1; + char name[name_len]; + for (j = 0; j < name_len; j++) + name[j] = tolower(info->cat[i].name[j]); + + name[name_len-1] = '\0'; + ret = snprintf(str + offset, rem, "%s|", name+1); + if (ret < 0) + goto err; + SNPRINTF_FAILURE(ret, rem, offset, len); + } + offset--; /* to remove the trailing | */ + rem++; + + ret = snprintf(str + offset, rem, ") ("); + if (ret < 0) + goto err; + SNPRINTF_FAILURE(ret, rem, offset, len); + + for (i = 0; i < LOGLEVEL_DEFS; i++) { + int j, loglevel_str_len = strlen(loglevel_strs[i].str)+1; + char loglevel_str[loglevel_str_len]; + + for (j = 0; j < loglevel_str_len; j++) + loglevel_str[j] = tolower(loglevel_strs[i].str[j]); + + loglevel_str[loglevel_str_len-1] = '\0'; + ret = snprintf(str + offset, rem, "%s|", loglevel_str); + if (ret < 0) + goto err; + SNPRINTF_FAILURE(ret, rem, offset, len); + } + offset--; /* to remove the trailing | */ + rem++; + + ret = snprintf(str + offset, rem, ")"); + if (ret < 0) + goto err; + SNPRINTF_FAILURE(ret, rem, offset, len); +err: return str; } -const char *log_vty_category_string(struct log_info *info) +/* This generates the logging command description for VTY. */ +const char *log_vty_command_description(const struct log_info *info) { - unsigned int len = 3; /* "()\0" */ - unsigned int i; char *str; + int i, ret, len = 0, offset = 0, rem; + unsigned int size = + strlen(LOGGING_STR + "Set the log level for a specified category\n") + 1; for (i = 0; i < info->num_cat; i++) - len += strlen(info->cat[i].name) + 1; + size += strlen(info->cat[i].description) + 1; - str = talloc_zero_size(NULL, len); + for (i = 0; i < LOGLEVEL_DEFS; i++) + size += strlen(loglevel_descriptions[i]) + 1; + + rem = size; + str = talloc_zero_size(NULL, size); if (!str) return NULL; - str[0] = '('; + ret = snprintf(str + offset, rem, LOGGING_STR + "Set the log level for a specified category\n"); + if (ret < 0) + goto err; + SNPRINTF_FAILURE(ret, rem, offset, len); + for (i = 0; i < info->num_cat; i++) { - strcat(str, info->cat[i].name+1); - strcat(str, "|"); + ret = snprintf(str + offset, rem, "%s\n", + info->cat[i].description); + if (ret < 0) + goto err; + SNPRINTF_FAILURE(ret, rem, offset, len); } - str[strlen(str)-1] = ')'; - + for (i = 0; i < LOGLEVEL_DEFS; i++) { + ret = snprintf(str + offset, rem, "%s\n", + loglevel_descriptions[i]); + if (ret < 0) + goto err; + SNPRINTF_FAILURE(ret, rem, offset, len); + } +err: return str; } diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 904f8fec..1b356c9f 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -149,56 +149,10 @@ DEFUN(logging_prnt_timestamp, return CMD_SUCCESS; } -/* FIXME: those have to be kept in sync with the log levels and categories */ -#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|gprs|ns|bssgp|llc|sndcp|isup|m2ua|pcap|nat|all)" -#define CATEGORIES_HELP \ - "A-bis Radio Link Layer (RLL)\n" \ - "Layer3 Call Control (CC)\n" \ - "Layer3 Mobility Management (MM)\n" \ - "Layer3 Radio Resource (RR)\n" \ - "A-bis Radio Signalling Link (RSL)\n" \ - "A-bis Network Management / O&M (NM/OML)\n" \ - "Layer3 Short Messagaging Service (SMS)\n" \ - "Paging Subsystem\n" \ - "MNCC API for Call Control application\n" \ - "A-bis Input Subsystem\n" \ - "A-bis Input Driver for Signalling\n" \ - "A-bis Input Driver for B-Channel (voice data)\n" \ - "A-bis B-Channel / Sub-channel Multiplexer\n" \ - "Radio Measurements\n" \ - "SCCP\n" \ - "Mobile Switching Center\n" \ - "Media Gateway Control Protocol\n" \ - "Hand-over\n" \ - "Database Layer\n" \ - "Reference Counting\n" \ - "GPRS Core\n" \ - "GPRS Network Service (NS)\n" \ - "GPRS BSS Gateway Protocol (BSSGP)\n" \ - "GPRS Logical Link Control Protocol (LLC)\n" \ - "GPRS Sub-Network Dependent Control Protocol (SNDCP)\n" \ - "ISDN User Part (ISUP)\n" \ - "SCTP M2UA\n" \ - "Trace message IO\n" \ - "BSC NAT\n" \ - "Global setting for all subsytems\n" - -#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)" -#define LEVELS_HELP \ - "Log simply everything\n" \ - "Log debug messages and higher levels\n" \ - "Log informational messages and higher levels\n" \ - "Log noticable messages and higher levels\n" \ - "Log error messages and higher levels\n" \ - "Log only fatal messages\n" - DEFUN(logging_level, logging_level_cmd, - "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, - LOGGING_STR - "Set the log level for a specified category\n" - CATEGORIES_HELP - LEVELS_HELP) + NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */ + NULL) /* same thing for helpstr. */ { int category = log_parse_category(argv[0]); int level = log_parse_level(argv[1]); @@ -596,7 +550,7 @@ static int config_write_log(struct vty *vty) return 1; } -void logging_vty_add_cmds() +void logging_vty_add_cmds(const struct log_info *cat) { install_element_ve(&enable_logging_cmd); install_element_ve(&disable_logging_cmd); @@ -604,6 +558,10 @@ void logging_vty_add_cmds() install_element_ve(&logging_use_clr_cmd); install_element_ve(&logging_prnt_timestamp_cmd); install_element_ve(&logging_set_category_mask_cmd); + + /* Logging level strings are generated dynamically. */ + logging_level_cmd.string = log_vty_command_string(cat); + logging_level_cmd.doc = log_vty_command_description(cat); install_element_ve(&logging_level_cmd); install_element_ve(&show_logging_vty_cmd); -- cgit v1.2.3 From fba495e5f6084800c076e0ecae990ed9e6483530 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 23 Mar 2011 18:08:08 +0100 Subject: This patch moves the GSM-specific functions to the new library libosmogsm which is provided by libosmocore. I have also moved generate_backtrace() to backtrace.c instead of gsm_utils.c, otherwise the timer and msgfile tests depend on libosmogsm. Signed-off-by: Pablo Neira Ayuso --- Makefile.am | 2 +- configure.in | 2 + include/osmocore/Makefile.am | 3 +- include/osmocore/backtrace.h | 6 + include/osmocore/gsm_utils.h | 1 - libosmogsm.pc.in | 11 + src/Makefile.am | 14 +- src/backtrace.c | 50 ++ src/comp128.c | 230 --------- src/gprs_cipher_core.c | 99 ---- src/gsm/Makefile.am | 13 + src/gsm/comp128.c | 230 +++++++++ src/gsm/gprs_cipher_core.c | 99 ++++ src/gsm/gsm0480.c | 461 ++++++++++++++++++ src/gsm/gsm0808.c | 369 ++++++++++++++ src/gsm/gsm48.c | 415 ++++++++++++++++ src/gsm/gsm48_ie.c | 1095 ++++++++++++++++++++++++++++++++++++++++++ src/gsm/gsm_utils.c | 465 ++++++++++++++++++ src/gsm/rsl.c | 371 ++++++++++++++ src/gsm/rxlev_stat.c | 94 ++++ src/gsm/tlv_parser.c | 179 +++++++ src/gsm0480.c | 461 ------------------ src/gsm0808.c | 369 -------------- src/gsm48.c | 415 ---------------- src/gsm48_ie.c | 1095 ------------------------------------------ src/gsm_utils.c | 488 ------------------- src/panic.c | 1 + src/rsl.c | 371 -------------- src/rxlev_stat.c | 94 ---- src/tlv_parser.c | 179 ------- tests/sms/Makefile.am | 2 +- tests/smscb/Makefile.am | 2 +- tests/ussd/Makefile.am | 2 +- 33 files changed, 3874 insertions(+), 3814 deletions(-) create mode 100644 include/osmocore/backtrace.h create mode 100644 libosmogsm.pc.in create mode 100644 src/backtrace.c delete mode 100644 src/comp128.c delete mode 100644 src/gprs_cipher_core.c create mode 100644 src/gsm/Makefile.am create mode 100644 src/gsm/comp128.c create mode 100644 src/gsm/gprs_cipher_core.c create mode 100644 src/gsm/gsm0480.c create mode 100644 src/gsm/gsm0808.c create mode 100644 src/gsm/gsm48.c create mode 100644 src/gsm/gsm48_ie.c create mode 100644 src/gsm/gsm_utils.c create mode 100644 src/gsm/rsl.c create mode 100644 src/gsm/rxlev_stat.c create mode 100644 src/gsm/tlv_parser.c delete mode 100644 src/gsm0480.c delete mode 100644 src/gsm0808.c delete mode 100644 src/gsm48.c delete mode 100644 src/gsm48_ie.c delete mode 100644 src/gsm_utils.c delete mode 100644 src/rsl.c delete mode 100644 src/rxlev_stat.c delete mode 100644 src/tlv_parser.c diff --git a/Makefile.am b/Makefile.am index 93254e81..e391de89 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include SUBDIRS = include src tests pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libosmocore.pc libosmocodec.pc libosmovty.pc +pkgconfig_DATA = libosmocore.pc libosmocodec.pc libosmovty.pc libosmogsm.pc BUILT_SOURCES = $(top_srcdir)/.version $(top_srcdir)/.version: diff --git a/configure.in b/configure.in index 165cecb7..b572bf4c 100644 --- a/configure.in +++ b/configure.in @@ -101,6 +101,7 @@ AC_OUTPUT( libosmocore.pc libosmocodec.pc libosmovty.pc + libosmogsm.pc include/osmocom/Makefile include/osmocom/vty/Makefile include/osmocom/codec/Makefile @@ -111,6 +112,7 @@ AC_OUTPUT( src/Makefile src/vty/Makefile src/codec/Makefile + src/gsm/Makefile tests/Makefile tests/timer/Makefile tests/sms/Makefile diff --git a/include/osmocore/Makefile.am b/include/osmocore/Makefile.am index a3b12ef4..b65589a6 100644 --- a/include/osmocore/Makefile.am +++ b/include/osmocore/Makefile.am @@ -2,7 +2,8 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \ tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \ gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \ gsm48_ie.h logging.h gsm0808.h rate_ctr.h gsmtap_util.h \ - plugin.h crc16.h panic.h process.h gsm0480.h msgfile.h + plugin.h crc16.h panic.h process.h gsm0480.h msgfile.h \ + backtrace.h if ENABLE_TALLOC osmocore_HEADERS += talloc.h diff --git a/include/osmocore/backtrace.h b/include/osmocore/backtrace.h new file mode 100644 index 00000000..bbbb2c28 --- /dev/null +++ b/include/osmocore/backtrace.h @@ -0,0 +1,6 @@ +#ifndef _OSMO_BACKTRACE_H_ +#define _OSMO_BACKTRACE_H_ + +void generate_backtrace(); + +#endif diff --git a/include/osmocore/gsm_utils.h b/include/osmocore/gsm_utils.h index 0aadd2e4..19adb70a 100644 --- a/include/osmocore/gsm_utils.h +++ b/include/osmocore/gsm_utils.h @@ -114,5 +114,4 @@ int gprs_tlli_type(uint32_t tlli); uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type); -void generate_backtrace(); #endif diff --git a/libosmogsm.pc.in b/libosmogsm.pc.in new file mode 100644 index 00000000..753bb3a1 --- /dev/null +++ b/libosmogsm.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Osmocom GSM Core Library +Description: GSM Core Library +Version: @VERSION@ +Libs: -L${libdir} -losmogsm +Cflags: -I${includedir}/ + diff --git a/src/Makefile.am b/src/Makefile.am index 94492c53..c5c8a21d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=. vty codec +SUBDIRS=. vty codec gsm # This is _NOT_ the library release version, it's an API version. # Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification @@ -9,12 +9,12 @@ AM_CFLAGS = -fPIC -Wall lib_LTLIBRARIES = libosmocore.la -libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c bits.c \ - tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ - write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ - logging.c logging_syslog.c gsm0808.c rate_ctr.c \ - gsmtap_util.c gprs_cipher_core.c crc16.c panic.c \ - process.c gsm0480.c +libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \ + bitvec.c statistics.c \ + write_queue.c utils.c \ + logging.c logging_syslog.c rate_ctr.c \ + gsmtap_util.c crc16.c panic.c backtrace.c \ + process.c if ENABLE_PLUGIN libosmocore_la_SOURCES += plugin.c diff --git a/src/backtrace.c b/src/backtrace.c new file mode 100644 index 00000000..42394453 --- /dev/null +++ b/src/backtrace.c @@ -0,0 +1,50 @@ +/* + * (C) 2008 by Daniel Willmann + * (C) 2009 by Holger Hans Peter Freyther + * (C) 2009-2010 by Harald Welte + * (C) 2010 by Nico Golde + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include "config.h" + +#ifdef HAVE_EXECINFO_H +#include +void generate_backtrace() +{ + int i, nptrs; + void *buffer[100]; + char **strings; + + nptrs = backtrace(buffer, ARRAY_SIZE(buffer)); + printf("backtrace() returned %d addresses\n", nptrs); + + strings = backtrace_symbols(buffer, nptrs); + if (!strings) + return; + + for (i = 1; i < nptrs; i++) + printf("%s\n", strings[i]); + + free(strings); +} +#endif diff --git a/src/comp128.c b/src/comp128.c deleted file mode 100644 index 5d5680c7..00000000 --- a/src/comp128.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * COMP128 implementation - * - * - * This code is inspired by original code from : - * Marc Briceno , Ian Goldberg , - * and David Wagner - * - * But it has been fully rewritten from various PDFs found online describing - * the algorithm because the licence of the code referenced above was unclear. - * A comment snippet from the original code is included below, it describes - * where the doc came from and how the algorithm was reverse engineered. - * - * - * (C) 2009 by Sylvain Munaut - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -/* - * --- SNIP --- - * - * This code derived from a leaked document from the GSM standards. - * Some missing pieces were filled in by reverse-engineering a working SIM. - * We have verified that this is the correct COMP128 algorithm. - * - * The first page of the document identifies it as - * _Technical Information: GSM System Security Study_. - * 10-1617-01, 10th June 1988. - * The bottom of the title page is marked - * Racal Research Ltd. - * Worton Drive, Worton Grange Industrial Estate, - * Reading, Berks. RG2 0SB, England. - * Telephone: Reading (0734) 868601 Telex: 847152 - * The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy! - * - * Note: There are three typos in the spec (discovered by - * reverse-engineering). - * First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read - * "z = (2 * x[m] + x[n]) mod 2^(9-j)". - * Second, the "k" loop in the "Form bits from bytes" section is severely - * botched: the k index should run only from 0 to 3, and clearly the range - * on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8, - * to be consistent with the subsequent section). - * Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as - * claimed in the document. (And the document doesn't specify how Kc is - * derived, but that was also easily discovered with reverse engineering.) - * All of these typos have been corrected in the following code. - * - * --- /SNIP --- - */ - -#include -#include - -/* The compression tables (just copied ...) */ -static const uint8_t table_0[512] = { - 102, 177, 186, 162, 2, 156, 112, 75, 55, 25, 8, 12, 251, 193, 246, 188, - 109, 213, 151, 53, 42, 79, 191, 115, 233, 242, 164, 223, 209, 148, 108, 161, - 252, 37, 244, 47, 64, 211, 6, 237, 185, 160, 139, 113, 76, 138, 59, 70, - 67, 26, 13, 157, 63, 179, 221, 30, 214, 36, 166, 69, 152, 124, 207, 116, - 247, 194, 41, 84, 71, 1, 49, 14, 95, 35, 169, 21, 96, 78, 215, 225, - 182, 243, 28, 92, 201, 118, 4, 74, 248, 128, 17, 11, 146, 132, 245, 48, - 149, 90, 120, 39, 87, 230, 106, 232, 175, 19, 126, 190, 202, 141, 137, 176, - 250, 27, 101, 40, 219, 227, 58, 20, 51, 178, 98, 216, 140, 22, 32, 121, - 61, 103, 203, 72, 29, 110, 85, 212, 180, 204, 150, 183, 15, 66, 172, 196, - 56, 197, 158, 0, 100, 45, 153, 7, 144, 222, 163, 167, 60, 135, 210, 231, - 174, 165, 38, 249, 224, 34, 220, 229, 217, 208, 241, 68, 206, 189, 125, 255, - 239, 54, 168, 89, 123, 122, 73, 145, 117, 234, 143, 99, 129, 200, 192, 82, - 104, 170, 136, 235, 93, 81, 205, 173, 236, 94, 105, 52, 46, 228, 198, 5, - 57, 254, 97, 155, 142, 133, 199, 171, 187, 50, 65, 181, 127, 107, 147, 226, - 184, 218, 131, 33, 77, 86, 31, 44, 88, 62, 238, 18, 24, 43, 154, 23, - 80, 159, 134, 111, 9, 114, 3, 91, 16, 130, 83, 10, 195, 240, 253, 119, - 177, 102, 162, 186, 156, 2, 75, 112, 25, 55, 12, 8, 193, 251, 188, 246, - 213, 109, 53, 151, 79, 42, 115, 191, 242, 233, 223, 164, 148, 209, 161, 108, - 37, 252, 47, 244, 211, 64, 237, 6, 160, 185, 113, 139, 138, 76, 70, 59, - 26, 67, 157, 13, 179, 63, 30, 221, 36, 214, 69, 166, 124, 152, 116, 207, - 194, 247, 84, 41, 1, 71, 14, 49, 35, 95, 21, 169, 78, 96, 225, 215, - 243, 182, 92, 28, 118, 201, 74, 4, 128, 248, 11, 17, 132, 146, 48, 245, - 90, 149, 39, 120, 230, 87, 232, 106, 19, 175, 190, 126, 141, 202, 176, 137, - 27, 250, 40, 101, 227, 219, 20, 58, 178, 51, 216, 98, 22, 140, 121, 32, - 103, 61, 72, 203, 110, 29, 212, 85, 204, 180, 183, 150, 66, 15, 196, 172, - 197, 56, 0, 158, 45, 100, 7, 153, 222, 144, 167, 163, 135, 60, 231, 210, - 165, 174, 249, 38, 34, 224, 229, 220, 208, 217, 68, 241, 189, 206, 255, 125, - 54, 239, 89, 168, 122, 123, 145, 73, 234, 117, 99, 143, 200, 129, 82, 192, - 170, 104, 235, 136, 81, 93, 173, 205, 94, 236, 52, 105, 228, 46, 5, 198, - 254, 57, 155, 97, 133, 142, 171, 199, 50, 187, 181, 65, 107, 127, 226, 147, - 218, 184, 33, 131, 86, 77, 44, 31, 62, 88, 18, 238, 43, 24, 23, 154, - 159, 80, 111, 134, 114, 9, 91, 3, 130, 16, 10, 83, 240, 195, 119, 253, -}, table_1[256] = { - 19, 11, 80, 114, 43, 1, 69, 94, 39, 18, 127, 117, 97, 3, 85, 43, - 27, 124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5, - 35, 107, 103, 68, 21, 86, 36, 91, 85, 126, 32, 50, 109, 94, 120, 6, - 53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55, 110, 125, 105, 20, - 90, 80, 76, 96, 23, 60, 89, 64, 121, 56, 14, 74, 101, 8, 19, 78, - 76, 66, 104, 46, 111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51, - 57, 65, 119, 116, 22, 109, 7, 86, 59, 93, 62, 110, 78, 99, 77, 67, - 12, 113, 87, 98, 102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75, - 95, 63, 28, 49, 123, 120, 20, 112, 44, 30, 15, 98, 106, 2, 103, 29, - 82, 107, 42, 124, 24, 30, 41, 16, 108, 100, 117, 40, 73, 40, 7, 114, - 82, 115, 36, 112, 12, 102, 100, 84, 92, 48, 72, 97, 9, 54, 55, 74, - 113, 123, 17, 26, 53, 58, 4, 9, 69, 122, 21, 118, 42, 60, 27, 73, - 118, 125, 34, 15, 65, 115, 84, 64, 62, 81, 70, 1, 24, 111, 121, 83, - 104, 81, 49, 127, 48, 105, 31, 10, 6, 91, 87, 37, 16, 54, 116, 126, - 31, 38, 13, 0, 72, 106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52, - 101, 17, 44, 108, 71, 52, 66, 57, 33, 51, 25, 90, 2, 119, 122, 35, -}, table_2[128] = { - 52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43, - 37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18, - 55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59, - 62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56, - 48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61, - 29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0, - 20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27, - 31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7, -}, table_3[64] = { - 1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31, - 28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9, - 20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10, - 17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19, -}, table_4[32] = { - 15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8, - 10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12, -}; - -static const uint8_t *_comp128_table[5] = { table_0, table_1, table_2, table_3, table_4 }; - - -static inline void -_comp128_compression_round(uint8_t *x, int n, const uint8_t *tbl) -{ - int i, j, m, a, b, y, z; - m = 4 - n; - for (i=0; i<(1<>2] & (1<<(3-(i&3)))) - bits[i] = 1; -} - -static inline void -_comp128_permutation(uint8_t *x, uint8_t *bits) -{ - int i; - memset(&x[16], 0x00, 16); - for (i=0; i<128; i++) - x[(i>>3)+16] |= bits[(i*17) & 127] << (7-(i&7)); -} - -void -comp128(uint8_t *ki, uint8_t *rand, uint8_t *sres, uint8_t *kc) -{ - int i; - uint8_t x[32], bits[128]; - - /* x[16-31] = RAND */ - memcpy(&x[16], rand, 16); - - /* Round 1-7 */ - for (i=0; i<7; i++) { - /* x[0-15] = Ki */ - memcpy(x, ki, 16); - - /* Compression */ - _comp128_compression(x); - - /* FormBitFromBytes */ - _comp128_bitsfrombytes(x, bits); - - /* Permutation */ - _comp128_permutation(x, bits); - } - - /* Round 8 (final) */ - /* x[0-15] = Ki */ - memcpy(x, ki, 16); - - /* Compression */ - _comp128_compression(x); - - /* Output stage */ - for (i=0; i<8; i+=2) - sres[i>>1] = x[i]<<4 | x[i+1]; - - for (i=0; i<12; i+=2) - kc[i>>1] = (x[i + 18] << 6) | - (x[i + 19] << 2) | - (x[i + 20] >> 2); - - kc[6] = (x[30]<<6) | (x[31]<<2); - kc[7] = 0; -} - diff --git a/src/gprs_cipher_core.c b/src/gprs_cipher_core.c deleted file mode 100644 index 6174bd72..00000000 --- a/src/gprs_cipher_core.c +++ /dev/null @@ -1,99 +0,0 @@ -/* GPRS LLC cipher core infrastructure */ - -/* (C) 2010 by Harald Welte - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include - -#include -#include -#include - -#include - -static LLIST_HEAD(gprs_ciphers); - -static struct gprs_cipher_impl *selected_ciphers[_GPRS_ALGO_NUM]; - -/* register a cipher with the core */ -int gprs_cipher_register(struct gprs_cipher_impl *ciph) -{ - if (ciph->algo > ARRAY_SIZE(selected_ciphers)) - return -ERANGE; - - llist_add_tail(&ciph->list, &gprs_ciphers); - - /* check if we want to select this implementation over others */ - if (!selected_ciphers[ciph->algo] || - (selected_ciphers[ciph->algo]->priority > ciph->priority)) - selected_ciphers[ciph->algo] = ciph; - - return 0; -} - -/* load all available GPRS cipher plugins */ -int gprs_cipher_load(const char *path) -{ - /* load all plugins available from path */ - return plugin_load_all(path); -} - -/* function to be called by core code */ -int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo, - uint64_t kc, uint32_t iv, enum gprs_cipher_direction dir) -{ - if (algo > ARRAY_SIZE(selected_ciphers)) - return -ERANGE; - - if (!selected_ciphers[algo]) - return -EINVAL; - - if (len > GSM0464_CIPH_MAX_BLOCK) - return -ERANGE; - - /* run the actual cipher from the plugin */ - return selected_ciphers[algo]->run(out, len, kc, iv, dir); -} - -int gprs_cipher_supported(enum gprs_ciph_algo algo) -{ - if (algo > ARRAY_SIZE(selected_ciphers)) - return -ERANGE; - - if (selected_ciphers[algo]) - return 1; - - return 0; -} - -/* GSM TS 04.64 / Section A.2.1 : Generation of 'input' */ -uint32_t gprs_cipher_gen_input_ui(uint32_t iov_ui, uint8_t sapi, uint32_t lfn, uint32_t oc) -{ - uint32_t sx = ((1<<27) * sapi) + (1<<31); - - return (iov_ui ^ sx) + lfn + oc; -} - -/* GSM TS 04.64 / Section A.2.1 : Generation of 'input' */ -uint32_t gprs_cipher_gen_input_i(uint32_t iov_i, uint32_t lfn, uint32_t oc) -{ - return iov_i + lfn + oc; -} diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am new file mode 100644 index 00000000..a8c2e569 --- /dev/null +++ b/src/gsm/Makefile.am @@ -0,0 +1,13 @@ +# This is _NOT_ the library release version, it's an API version. +# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification +LIBVERSION=0:0:0 + +INCLUDES = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS = -fPIC -Wall + +lib_LTLIBRARIES = libosmogsm.la + +libosmogsm_la_SOURCES = rxlev_stat.c tlv_parser.c comp128.c gsm_utils.c \ + rsl.c gsm48.c gsm48_ie.c gsm0808.c \ + gprs_cipher_core.c gsm0480.c +libosmogsm_la_LIBADD = $(top_builddir)/src/libosmocore.la diff --git a/src/gsm/comp128.c b/src/gsm/comp128.c new file mode 100644 index 00000000..5d5680c7 --- /dev/null +++ b/src/gsm/comp128.c @@ -0,0 +1,230 @@ +/* + * COMP128 implementation + * + * + * This code is inspired by original code from : + * Marc Briceno , Ian Goldberg , + * and David Wagner + * + * But it has been fully rewritten from various PDFs found online describing + * the algorithm because the licence of the code referenced above was unclear. + * A comment snippet from the original code is included below, it describes + * where the doc came from and how the algorithm was reverse engineered. + * + * + * (C) 2009 by Sylvain Munaut + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + * --- SNIP --- + * + * This code derived from a leaked document from the GSM standards. + * Some missing pieces were filled in by reverse-engineering a working SIM. + * We have verified that this is the correct COMP128 algorithm. + * + * The first page of the document identifies it as + * _Technical Information: GSM System Security Study_. + * 10-1617-01, 10th June 1988. + * The bottom of the title page is marked + * Racal Research Ltd. + * Worton Drive, Worton Grange Industrial Estate, + * Reading, Berks. RG2 0SB, England. + * Telephone: Reading (0734) 868601 Telex: 847152 + * The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy! + * + * Note: There are three typos in the spec (discovered by + * reverse-engineering). + * First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read + * "z = (2 * x[m] + x[n]) mod 2^(9-j)". + * Second, the "k" loop in the "Form bits from bytes" section is severely + * botched: the k index should run only from 0 to 3, and clearly the range + * on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8, + * to be consistent with the subsequent section). + * Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as + * claimed in the document. (And the document doesn't specify how Kc is + * derived, but that was also easily discovered with reverse engineering.) + * All of these typos have been corrected in the following code. + * + * --- /SNIP --- + */ + +#include +#include + +/* The compression tables (just copied ...) */ +static const uint8_t table_0[512] = { + 102, 177, 186, 162, 2, 156, 112, 75, 55, 25, 8, 12, 251, 193, 246, 188, + 109, 213, 151, 53, 42, 79, 191, 115, 233, 242, 164, 223, 209, 148, 108, 161, + 252, 37, 244, 47, 64, 211, 6, 237, 185, 160, 139, 113, 76, 138, 59, 70, + 67, 26, 13, 157, 63, 179, 221, 30, 214, 36, 166, 69, 152, 124, 207, 116, + 247, 194, 41, 84, 71, 1, 49, 14, 95, 35, 169, 21, 96, 78, 215, 225, + 182, 243, 28, 92, 201, 118, 4, 74, 248, 128, 17, 11, 146, 132, 245, 48, + 149, 90, 120, 39, 87, 230, 106, 232, 175, 19, 126, 190, 202, 141, 137, 176, + 250, 27, 101, 40, 219, 227, 58, 20, 51, 178, 98, 216, 140, 22, 32, 121, + 61, 103, 203, 72, 29, 110, 85, 212, 180, 204, 150, 183, 15, 66, 172, 196, + 56, 197, 158, 0, 100, 45, 153, 7, 144, 222, 163, 167, 60, 135, 210, 231, + 174, 165, 38, 249, 224, 34, 220, 229, 217, 208, 241, 68, 206, 189, 125, 255, + 239, 54, 168, 89, 123, 122, 73, 145, 117, 234, 143, 99, 129, 200, 192, 82, + 104, 170, 136, 235, 93, 81, 205, 173, 236, 94, 105, 52, 46, 228, 198, 5, + 57, 254, 97, 155, 142, 133, 199, 171, 187, 50, 65, 181, 127, 107, 147, 226, + 184, 218, 131, 33, 77, 86, 31, 44, 88, 62, 238, 18, 24, 43, 154, 23, + 80, 159, 134, 111, 9, 114, 3, 91, 16, 130, 83, 10, 195, 240, 253, 119, + 177, 102, 162, 186, 156, 2, 75, 112, 25, 55, 12, 8, 193, 251, 188, 246, + 213, 109, 53, 151, 79, 42, 115, 191, 242, 233, 223, 164, 148, 209, 161, 108, + 37, 252, 47, 244, 211, 64, 237, 6, 160, 185, 113, 139, 138, 76, 70, 59, + 26, 67, 157, 13, 179, 63, 30, 221, 36, 214, 69, 166, 124, 152, 116, 207, + 194, 247, 84, 41, 1, 71, 14, 49, 35, 95, 21, 169, 78, 96, 225, 215, + 243, 182, 92, 28, 118, 201, 74, 4, 128, 248, 11, 17, 132, 146, 48, 245, + 90, 149, 39, 120, 230, 87, 232, 106, 19, 175, 190, 126, 141, 202, 176, 137, + 27, 250, 40, 101, 227, 219, 20, 58, 178, 51, 216, 98, 22, 140, 121, 32, + 103, 61, 72, 203, 110, 29, 212, 85, 204, 180, 183, 150, 66, 15, 196, 172, + 197, 56, 0, 158, 45, 100, 7, 153, 222, 144, 167, 163, 135, 60, 231, 210, + 165, 174, 249, 38, 34, 224, 229, 220, 208, 217, 68, 241, 189, 206, 255, 125, + 54, 239, 89, 168, 122, 123, 145, 73, 234, 117, 99, 143, 200, 129, 82, 192, + 170, 104, 235, 136, 81, 93, 173, 205, 94, 236, 52, 105, 228, 46, 5, 198, + 254, 57, 155, 97, 133, 142, 171, 199, 50, 187, 181, 65, 107, 127, 226, 147, + 218, 184, 33, 131, 86, 77, 44, 31, 62, 88, 18, 238, 43, 24, 23, 154, + 159, 80, 111, 134, 114, 9, 91, 3, 130, 16, 10, 83, 240, 195, 119, 253, +}, table_1[256] = { + 19, 11, 80, 114, 43, 1, 69, 94, 39, 18, 127, 117, 97, 3, 85, 43, + 27, 124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5, + 35, 107, 103, 68, 21, 86, 36, 91, 85, 126, 32, 50, 109, 94, 120, 6, + 53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55, 110, 125, 105, 20, + 90, 80, 76, 96, 23, 60, 89, 64, 121, 56, 14, 74, 101, 8, 19, 78, + 76, 66, 104, 46, 111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51, + 57, 65, 119, 116, 22, 109, 7, 86, 59, 93, 62, 110, 78, 99, 77, 67, + 12, 113, 87, 98, 102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75, + 95, 63, 28, 49, 123, 120, 20, 112, 44, 30, 15, 98, 106, 2, 103, 29, + 82, 107, 42, 124, 24, 30, 41, 16, 108, 100, 117, 40, 73, 40, 7, 114, + 82, 115, 36, 112, 12, 102, 100, 84, 92, 48, 72, 97, 9, 54, 55, 74, + 113, 123, 17, 26, 53, 58, 4, 9, 69, 122, 21, 118, 42, 60, 27, 73, + 118, 125, 34, 15, 65, 115, 84, 64, 62, 81, 70, 1, 24, 111, 121, 83, + 104, 81, 49, 127, 48, 105, 31, 10, 6, 91, 87, 37, 16, 54, 116, 126, + 31, 38, 13, 0, 72, 106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52, + 101, 17, 44, 108, 71, 52, 66, 57, 33, 51, 25, 90, 2, 119, 122, 35, +}, table_2[128] = { + 52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43, + 37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18, + 55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59, + 62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56, + 48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61, + 29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0, + 20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27, + 31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7, +}, table_3[64] = { + 1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31, + 28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9, + 20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10, + 17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19, +}, table_4[32] = { + 15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8, + 10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12, +}; + +static const uint8_t *_comp128_table[5] = { table_0, table_1, table_2, table_3, table_4 }; + + +static inline void +_comp128_compression_round(uint8_t *x, int n, const uint8_t *tbl) +{ + int i, j, m, a, b, y, z; + m = 4 - n; + for (i=0; i<(1<>2] & (1<<(3-(i&3)))) + bits[i] = 1; +} + +static inline void +_comp128_permutation(uint8_t *x, uint8_t *bits) +{ + int i; + memset(&x[16], 0x00, 16); + for (i=0; i<128; i++) + x[(i>>3)+16] |= bits[(i*17) & 127] << (7-(i&7)); +} + +void +comp128(uint8_t *ki, uint8_t *rand, uint8_t *sres, uint8_t *kc) +{ + int i; + uint8_t x[32], bits[128]; + + /* x[16-31] = RAND */ + memcpy(&x[16], rand, 16); + + /* Round 1-7 */ + for (i=0; i<7; i++) { + /* x[0-15] = Ki */ + memcpy(x, ki, 16); + + /* Compression */ + _comp128_compression(x); + + /* FormBitFromBytes */ + _comp128_bitsfrombytes(x, bits); + + /* Permutation */ + _comp128_permutation(x, bits); + } + + /* Round 8 (final) */ + /* x[0-15] = Ki */ + memcpy(x, ki, 16); + + /* Compression */ + _comp128_compression(x); + + /* Output stage */ + for (i=0; i<8; i+=2) + sres[i>>1] = x[i]<<4 | x[i+1]; + + for (i=0; i<12; i+=2) + kc[i>>1] = (x[i + 18] << 6) | + (x[i + 19] << 2) | + (x[i + 20] >> 2); + + kc[6] = (x[30]<<6) | (x[31]<<2); + kc[7] = 0; +} + diff --git a/src/gsm/gprs_cipher_core.c b/src/gsm/gprs_cipher_core.c new file mode 100644 index 00000000..6174bd72 --- /dev/null +++ b/src/gsm/gprs_cipher_core.c @@ -0,0 +1,99 @@ +/* GPRS LLC cipher core infrastructure */ + +/* (C) 2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include +#include +#include + +#include + +static LLIST_HEAD(gprs_ciphers); + +static struct gprs_cipher_impl *selected_ciphers[_GPRS_ALGO_NUM]; + +/* register a cipher with the core */ +int gprs_cipher_register(struct gprs_cipher_impl *ciph) +{ + if (ciph->algo > ARRAY_SIZE(selected_ciphers)) + return -ERANGE; + + llist_add_tail(&ciph->list, &gprs_ciphers); + + /* check if we want to select this implementation over others */ + if (!selected_ciphers[ciph->algo] || + (selected_ciphers[ciph->algo]->priority > ciph->priority)) + selected_ciphers[ciph->algo] = ciph; + + return 0; +} + +/* load all available GPRS cipher plugins */ +int gprs_cipher_load(const char *path) +{ + /* load all plugins available from path */ + return plugin_load_all(path); +} + +/* function to be called by core code */ +int gprs_cipher_run(uint8_t *out, uint16_t len, enum gprs_ciph_algo algo, + uint64_t kc, uint32_t iv, enum gprs_cipher_direction dir) +{ + if (algo > ARRAY_SIZE(selected_ciphers)) + return -ERANGE; + + if (!selected_ciphers[algo]) + return -EINVAL; + + if (len > GSM0464_CIPH_MAX_BLOCK) + return -ERANGE; + + /* run the actual cipher from the plugin */ + return selected_ciphers[algo]->run(out, len, kc, iv, dir); +} + +int gprs_cipher_supported(enum gprs_ciph_algo algo) +{ + if (algo > ARRAY_SIZE(selected_ciphers)) + return -ERANGE; + + if (selected_ciphers[algo]) + return 1; + + return 0; +} + +/* GSM TS 04.64 / Section A.2.1 : Generation of 'input' */ +uint32_t gprs_cipher_gen_input_ui(uint32_t iov_ui, uint8_t sapi, uint32_t lfn, uint32_t oc) +{ + uint32_t sx = ((1<<27) * sapi) + (1<<31); + + return (iov_ui ^ sx) + lfn + oc; +} + +/* GSM TS 04.64 / Section A.2.1 : Generation of 'input' */ +uint32_t gprs_cipher_gen_input_i(uint32_t iov_i, uint32_t lfn, uint32_t oc) +{ + return iov_i + lfn + oc; +} diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c new file mode 100644 index 00000000..b6b345cb --- /dev/null +++ b/src/gsm/gsm0480.c @@ -0,0 +1,461 @@ +/* Format functions for GSM 04.80 */ + +/* + * (C) 2010 by Holger Hans Peter Freyther + * (C) 2009 by Mike Haben + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +#include + +#include +#include + +#include + +static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag) +{ + uint8_t *data = msgb_push(msgb, 2); + + data[0] = tag; + data[1] = msgb->len - 2; + return data; +} + +static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag, + uint8_t value) +{ + uint8_t *data = msgb_push(msgb, 3); + + data[0] = tag; + data[1] = 1; + data[2] = value; + return data; +} + +/* wrap an invoke around it... the other way around + * + * 1.) Invoke Component tag + * 2.) Invoke ID Tag + * 3.) Operation + * 4.) Data + */ +int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id) +{ + /* 3. operation */ + msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, op); + + /* 2. invoke id tag */ + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, link_id); + + /* 1. component tag */ + msgb_wrap_with_TL(msg, GSM0480_CTYPE_INVOKE); + + return 0; +} + +/* wrap the GSM 04.08 Facility IE around it */ +int gsm0480_wrap_facility(struct msgb *msg) +{ + msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); + + return 0; +} + +struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text) +{ + struct msgb *msg; + uint8_t *seq_len_ptr, *ussd_len_ptr, *data; + int len; + + msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); + if (!msg) + return NULL; + + /* SEQUENCE { */ + msgb_put_u8(msg, GSM_0480_SEQUENCE_TAG); + seq_len_ptr = msgb_put(msg, 1); + + /* DCS { */ + msgb_put_u8(msg, ASN1_OCTET_STRING_TAG); + msgb_put_u8(msg, 1); + msgb_put_u8(msg, 0x0F); + /* } DCS */ + + /* USSD-String { */ + msgb_put_u8(msg, ASN1_OCTET_STRING_TAG); + ussd_len_ptr = msgb_put(msg, 1); + data = msgb_put(msg, 0); + len = gsm_7bit_encode(data, text); + msgb_put(msg, len); + ussd_len_ptr[0] = len; + /* USSD-String } */ + + /* alertingPattern { */ + msgb_put_u8(msg, ASN1_OCTET_STRING_TAG); + msgb_put_u8(msg, 1); + msgb_put_u8(msg, alertPattern); + /* } alertingPattern */ + + seq_len_ptr[0] = 3 + 2 + ussd_len_ptr[0] + 3; + /* } SEQUENCE */ + + return msg; +} + +struct msgb *gsm0480_create_notifySS(const char *text) +{ + struct msgb *msg; + uint8_t *data, *tmp_len; + uint8_t *seq_len_ptr, *cal_len_ptr, *opt_len_ptr, *nam_len_ptr; + int len; + + len = strlen(text); + if (len < 1 || len > 160) + return NULL; + + msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); + if (!msg) + return NULL; + + msgb_put_u8(msg, GSM_0480_SEQUENCE_TAG); + seq_len_ptr = msgb_put(msg, 1); + + /* ss_code for CNAP { */ + msgb_put_u8(msg, 0x81); + msgb_put_u8(msg, 1); + msgb_put_u8(msg, 0x19); + /* } ss_code */ + + + /* nameIndicator { */ + msgb_put_u8(msg, 0xB4); + nam_len_ptr = msgb_put(msg, 1); + + /* callingName { */ + msgb_put_u8(msg, 0xA0); + opt_len_ptr = msgb_put(msg, 1); + msgb_put_u8(msg, 0xA0); + cal_len_ptr = msgb_put(msg, 1); + + /* namePresentationAllowed { */ + /* add the DCS value */ + msgb_put_u8(msg, 0x80); + msgb_put_u8(msg, 1); + msgb_put_u8(msg, 0x0F); + + /* add the lengthInCharacters */ + msgb_put_u8(msg, 0x81); + msgb_put_u8(msg, 1); + msgb_put_u8(msg, strlen(text)); + + /* add the actual string */ + msgb_put_u8(msg, 0x82); + tmp_len = msgb_put(msg, 1); + data = msgb_put(msg, 0); + len = gsm_7bit_encode(data, text); + tmp_len[0] = len; + msgb_put(msg, len); + + /* }; namePresentationAllowed */ + + cal_len_ptr[0] = 3 + 3 + 2 + len; + opt_len_ptr[0] = cal_len_ptr[0] + 2; + /* }; callingName */ + + nam_len_ptr[0] = opt_len_ptr[0] + 2; + /* ); nameIndicator */ + + /* write the lengths... */ + seq_len_ptr[0] = 3 + nam_len_ptr[0] + 2; + + return msg; +} + +/* Forward declarations */ +static int parse_ussd(const struct gsm48_hdr *hdr, + uint16_t len, struct ussd_request *req); +static int parse_ussd_info_elements(const uint8_t *ussd_ie, uint16_t len, + struct ussd_request *req); +static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, + struct ussd_request *req); +static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, + struct ussd_request *req); +static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length, + struct ussd_request *req); + +/* Decode a mobile-originated USSD-request message */ +int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len, + struct ussd_request *req) +{ + int rc = 0; + + if (len < sizeof(*hdr) + 2) { + LOGP(0, LOGL_DEBUG, "USSD Request is too short.\n"); + return 0; + } + + if ((hdr->proto_discr & 0x0f) == GSM48_PDISC_NC_SS) { + req->transaction_id = hdr->proto_discr & 0x70; + rc = parse_ussd(hdr, len, req); + } + + if (!rc) + LOGP(0, LOGL_DEBUG, "Error occurred while parsing received USSD!\n"); + + return rc; +} + +static int parse_ussd(const struct gsm48_hdr *hdr, uint16_t len, struct ussd_request *req) +{ + int rc = 1; + uint8_t msg_type = hdr->msg_type & 0xBF; /* message-type - section 3.4 */ + + switch (msg_type) { + case GSM0480_MTYPE_RELEASE_COMPLETE: + LOGP(0, LOGL_DEBUG, "USS Release Complete\n"); + /* could also parse out the optional Cause/Facility data */ + req->text[0] = 0xFF; + break; + case GSM0480_MTYPE_REGISTER: + case GSM0480_MTYPE_FACILITY: + rc &= parse_ussd_info_elements(&hdr->data[0], len - sizeof(*hdr), req); + break; + default: + LOGP(0, LOGL_DEBUG, "Unknown GSM 04.80 message-type field 0x%02x\n", + hdr->msg_type); + rc = 0; + break; + } + + return rc; +} + +static int parse_ussd_info_elements(const uint8_t *ussd_ie, uint16_t len, + struct ussd_request *req) +{ + int rc = -1; + /* Information Element Identifier - table 3.2 & GSM 04.08 section 10.5 */ + uint8_t iei; + uint8_t iei_length; + + iei = ussd_ie[0]; + iei_length = ussd_ie[1]; + + /* If the data does not fit, report an error */ + if (len - 2 < iei_length) + return 0; + + switch (iei) { + case GSM48_IE_CAUSE: + break; + case GSM0480_IE_FACILITY: + rc = parse_facility_ie(ussd_ie+2, iei_length, req); + break; + case GSM0480_IE_SS_VERSION: + break; + default: + LOGP(0, LOGL_DEBUG, "Unhandled GSM 04.08 or 04.80 IEI 0x%02x\n", + iei); + rc = 0; + break; + } + + return rc; +} + +static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, + struct ussd_request *req) +{ + int rc = 1; + uint8_t offset = 0; + + while (offset + 2 <= length) { + /* Component Type tag - table 3.7 */ + uint8_t component_type = facility_ie[offset]; + uint8_t component_length = facility_ie[offset+1]; + + /* size check */ + if (offset + 2 + component_length > length) { + LOGP(0, LOGL_ERROR, "Component does not fit.\n"); + return 0; + } + + switch (component_type) { + case GSM0480_CTYPE_INVOKE: + rc &= parse_ss_invoke(facility_ie+2, + component_length, + req); + break; + case GSM0480_CTYPE_RETURN_RESULT: + break; + case GSM0480_CTYPE_RETURN_ERROR: + break; + case GSM0480_CTYPE_REJECT: + break; + default: + LOGP(0, LOGL_DEBUG, "Unknown GSM 04.80 Facility " + "Component Type 0x%02x\n", component_type); + rc = 0; + break; + } + offset += (component_length+2); + }; + + return rc; +} + +/* Parse an Invoke component - see table 3.3 */ +static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, + struct ussd_request *req) +{ + int rc = 1; + uint8_t offset; + + if (length < 3) + return 0; + + /* mandatory part */ + if (invoke_data[0] != GSM0480_COMPIDTAG_INVOKE_ID) { + LOGP(0, LOGL_DEBUG, "Unexpected GSM 04.80 Component-ID tag " + "0x%02x (expecting Invoke ID tag)\n", invoke_data[0]); + } + + offset = invoke_data[1] + 2; + req->invoke_id = invoke_data[2]; + + /* look ahead once */ + if (offset + 1 > length) + return 0; + + /* optional part */ + if (invoke_data[offset] == GSM0480_COMPIDTAG_LINKED_ID) + offset += invoke_data[offset+1] + 2; /* skip over it */ + + /* mandatory part */ + if (invoke_data[offset] == GSM0480_OPERATION_CODE) { + if (offset + 2 > length) + return 0; + uint8_t operation_code = invoke_data[offset+2]; + switch (operation_code) { + case GSM0480_OP_CODE_PROCESS_USS_REQ: + rc = parse_process_uss_req(invoke_data + offset + 3, + length - offset - 3, + req); + break; + default: + LOGP(0, LOGL_DEBUG, "GSM 04.80 operation code 0x%02x " + "is not yet handled\n", operation_code); + rc = 0; + break; + } + } else { + LOGP(0, LOGL_DEBUG, "Unexpected GSM 04.80 Component-ID tag 0x%02x " + "(expecting Operation Code tag)\n", + invoke_data[0]); + rc = 0; + } + + return rc; +} + +/* Parse the parameters of a Process UnstructuredSS Request */ +static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length, + struct ussd_request *req) +{ + int rc = 0; + int num_chars; + uint8_t dcs; + + + /* we need at least that much */ + if (length < 8) + return 0; + + + if (uss_req_data[0] == GSM_0480_SEQUENCE_TAG) { + if (uss_req_data[2] == ASN1_OCTET_STRING_TAG) { + dcs = uss_req_data[4]; + if ((dcs == 0x0F) && + (uss_req_data[5] == ASN1_OCTET_STRING_TAG)) { + num_chars = (uss_req_data[6] * 8) / 7; + /* Prevent a mobile-originated buffer-overrun! */ + if (num_chars > MAX_LEN_USSD_STRING) + num_chars = MAX_LEN_USSD_STRING; + gsm_7bit_decode(req->text, + &(uss_req_data[7]), num_chars); + rc = 1; + } + } + } + return rc; +} + +struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text) +{ + struct msgb *msg; + struct gsm48_hdr *gh; + uint8_t *ptr8; + int response_len; + + msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); + if (!msg) + return NULL; + + /* First put the payload text into the message */ + ptr8 = msgb_put(msg, 0); + response_len = gsm_7bit_encode(ptr8, text); + msgb_put(msg, response_len); + + /* Then wrap it as an Octet String */ + msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG); + + /* Pre-pend the DCS octet string */ + msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F); + + /* Then wrap these as a Sequence */ + msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); + + /* Pre-pend the operation code */ + msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, + GSM0480_OP_CODE_PROCESS_USS_REQ); + + /* Wrap the operation code and IA5 string as a sequence */ + msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); + + /* Pre-pend the invoke ID */ + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); + + /* Wrap this up as a Return Result component */ + msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT); + + /* Wrap the component in a Facility message */ + msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); + + /* And finally pre-pend the L3 header */ + gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); + gh->proto_discr = GSM48_PDISC_NC_SS | trans_id + | (1<<7); /* TI direction = 1 */ + gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE; + + return msg; +} diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c new file mode 100644 index 00000000..dc450cc4 --- /dev/null +++ b/src/gsm/gsm0808.c @@ -0,0 +1,369 @@ +/* (C) 2009,2010 by Holger Hans Peter Freyther + * (C) 2009,2010 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include + +#include + +#define BSSMAP_MSG_SIZE 512 +#define BSSMAP_MSG_HEADROOM 128 + +static void put_data_16(uint8_t *data, const uint16_t val) +{ + memcpy(data, &val, sizeof(val)); +} + +struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, uint16_t _ci) +{ + uint8_t *data; + uint8_t *ci; + struct msgb* msg; + struct gsm48_loc_area_id *lai; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap cmpl l3"); + if (!msg) + return NULL; + + /* create the bssmap header */ + msg->l3h = msgb_put(msg, 2); + msg->l3h[0] = 0x0; + + /* create layer 3 header */ + data = msgb_put(msg, 1); + data[0] = BSS_MAP_MSG_COMPLETE_LAYER_3; + + /* create the cell header */ + data = msgb_put(msg, 3); + data[0] = GSM0808_IE_CELL_IDENTIFIER; + data[1] = 1 + sizeof(*lai) + 2; + data[2] = CELL_IDENT_WHOLE_GLOBAL; + + lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai)); + gsm48_generate_lai(lai, cc, nc, lac); + + ci = msgb_put(msg, 2); + put_data_16(ci, htons(_ci)); + + /* copy the layer3 data */ + data = msgb_put(msg, msgb_l3len(msg_l3) + 2); + data[0] = GSM0808_IE_LAYER_3_INFORMATION; + data[1] = msgb_l3len(msg_l3); + memcpy(&data[2], msg_l3->l3h, data[1]); + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + + return msg; +} + +struct msgb *gsm0808_create_reset(void) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: reset"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 6); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0x04; + msg->l3h[2] = 0x30; + msg->l3h[3] = 0x04; + msg->l3h[4] = 0x01; + msg->l3h[5] = 0x20; + return msg; +} + +struct msgb *gsm0808_create_clear_complete(void) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: clear complete"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 1; + msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE; + + return msg; +} + +struct msgb *gsm0808_create_clear_command(uint8_t reason) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: clear command"); + if (!msg) + return NULL; + + msg->l3h = msgb_tv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 4); + msgb_v_put(msg, BSS_MAP_MSG_CLEAR_CMD); + msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &reason); + return msg; +} + +struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "cipher-complete"); + if (!msg) + return NULL; + + /* send response with BSS override for A5/1... cheating */ + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0xff; + msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_COMPLETE; + + /* include layer3 in case we have at least two octets */ + if (layer3 && msgb_l3len(layer3) > 2) { + msg->l4h = msgb_put(msg, msgb_l3len(layer3) + 2); + msg->l4h[0] = GSM0808_IE_LAYER_3_MESSAGE_CONTENTS; + msg->l4h[1] = msgb_l3len(layer3); + memcpy(&msg->l4h[2], layer3->l3h, msgb_l3len(layer3)); + } + + /* and the optional BSS message */ + msg->l4h = msgb_put(msg, 2); + msg->l4h[0] = GSM0808_IE_CHOSEN_ENCR_ALG; + msg->l4h[1] = alg_id; + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + return msg; +} + +struct msgb *gsm0808_create_cipher_reject(uint8_t cause) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: clear complete"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 2; + msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_REJECT; + msg->l3h[3] = cause; + + return msg; +} + +struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark_data, uint8_t length) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "classmark-update"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0xff; + msg->l3h[2] = BSS_MAP_MSG_CLASSMARK_UPDATE; + + msg->l4h = msgb_put(msg, length); + memcpy(msg->l4h, classmark_data, length); + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + return msg; +} + +struct msgb *gsm0808_create_sapi_reject(uint8_t link_id) +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: sapi 'n' reject"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 5); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 3; + msg->l3h[2] = BSS_MAP_MSG_SAPI_N_REJECT; + msg->l3h[3] = link_id; + msg->l3h[4] = GSM0808_CAUSE_BSS_NOT_EQUIPPED; + + return msg; +} + +struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause, + uint8_t chosen_channel, uint8_t encr_alg_id, + uint8_t speech_mode) +{ + uint8_t *data; + + struct msgb *msg = msgb_alloc(35, "bssmap: ass compl"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 3); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0xff; + msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_COMPLETE; + + /* write 3.2.2.22 */ + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_RR_CAUSE; + data[1] = rr_cause; + + /* write cirtcuit identity code 3.2.2.2 */ + /* write cell identifier 3.2.2.17 */ + /* write chosen channel 3.2.2.33 when BTS picked it */ + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_CHOSEN_CHANNEL; + data[1] = chosen_channel; + + /* write chosen encryption algorithm 3.2.2.44 */ + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_CHOSEN_ENCR_ALG; + data[1] = encr_alg_id; + + /* write circuit pool 3.2.2.45 */ + /* write speech version chosen: 3.2.2.51 when BTS picked it */ + if (speech_mode != 0) { + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_SPEECH_VERSION; + data[1] = speech_mode; + } + + /* write LSA identifier 3.2.2.15 */ + + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + return msg; +} + +struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause) +{ + uint8_t *data; + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: ass fail"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 6); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 0xff; + msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE; + msg->l3h[3] = GSM0808_IE_CAUSE; + msg->l3h[4] = 1; + msg->l3h[5] = cause; + + /* RR cause 3.2.2.22 */ + if (rr_cause) { + data = msgb_put(msg, 2); + data[0] = GSM0808_IE_RR_CAUSE; + data[1] = *rr_cause; + } + + /* Circuit pool 3.22.45 */ + /* Circuit pool list 3.2.2.46 */ + + /* update the size */ + msg->l3h[1] = msgb_l3len(msg) - 2; + return msg; +} + +struct msgb *gsm0808_create_clear_rqst(uint8_t cause) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: clear rqst"); + if (!msg) + return NULL; + + msg->l3h = msgb_put(msg, 2 + 4); + msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; + msg->l3h[1] = 4; + + msg->l3h[2] = BSS_MAP_MSG_CLEAR_RQST; + msg->l3h[3] = GSM0808_IE_CAUSE; + msg->l3h[4] = 1; + msg->l3h[5] = cause; + return msg; +} + +void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id) +{ + uint8_t *hh = msgb_push(msg, 3); + hh[0] = BSSAP_MSG_DTAP; + hh[1] = link_id; + hh[2] = msg->len - 3; +} + +struct msgb *gsm0808_create_dtap(struct msgb *msg_l3, uint8_t link_id) +{ + struct dtap_header *header; + uint8_t *data; + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "dtap"); + if (!msg) + return NULL; + + /* DTAP header */ + msg->l3h = msgb_put(msg, sizeof(*header)); + header = (struct dtap_header *) &msg->l3h[0]; + header->type = BSSAP_MSG_DTAP; + header->link_id = link_id; + header->length = msgb_l3len(msg_l3); + + /* Payload */ + data = msgb_put(msg, header->length); + memcpy(data, msg_l3->l3h, header->length); + + return msg; +} + +static const struct tlv_definition bss_att_tlvdef = { + .def = { + [GSM0808_IE_IMSI] = { TLV_TYPE_TLV }, + [GSM0808_IE_TMSI] = { TLV_TYPE_TLV }, + [GSM0808_IE_CELL_IDENTIFIER_LIST] = { TLV_TYPE_TLV }, + [GSM0808_IE_CHANNEL_NEEDED] = { TLV_TYPE_TV }, + [GSM0808_IE_EMLPP_PRIORITY] = { TLV_TYPE_TV }, + [GSM0808_IE_CHANNEL_TYPE] = { TLV_TYPE_TLV }, + [GSM0808_IE_PRIORITY] = { TLV_TYPE_TLV }, + [GSM0808_IE_CIRCUIT_IDENTITY_CODE] = { TLV_TYPE_FIXED, 2 }, + [GSM0808_IE_DOWNLINK_DTX_FLAG] = { TLV_TYPE_TV }, + [GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV }, + [GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV }, + [GSM0808_IE_GROUP_CALL_REFERENCE] = { TLV_TYPE_TLV }, + [GSM0808_IE_TALKER_FLAG] = { TLV_TYPE_T }, + [GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV }, + [GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV }, + [GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TLV }, + [GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV }, + [GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV }, + [GSM0808_IE_CELL_IDENTIFIER] = { TLV_TYPE_TLV }, + [GSM0808_IE_CHOSEN_CHANNEL] = { TLV_TYPE_TV }, + [GSM0808_IE_LAYER_3_INFORMATION] = { TLV_TYPE_TLV }, + [GSM0808_IE_SPEECH_VERSION] = { TLV_TYPE_TV }, + [GSM0808_IE_CHOSEN_ENCR_ALG] = { TLV_TYPE_TV }, + }, +}; + +const struct tlv_definition *gsm0808_att_tlvdef() +{ + return &bss_att_tlvdef; +} diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c new file mode 100644 index 00000000..daec4f39 --- /dev/null +++ b/src/gsm/gsm48.c @@ -0,0 +1,415 @@ +/* GSM Mobile Radio Interface Layer 3 messages + * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ + +/* (C) 2008-2010 by Harald Welte + * (C) 2008, 2009 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +const struct tlv_definition gsm48_att_tlvdef = { + .def = { + [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV }, + [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV }, + [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV }, + [GSM48_IE_UTC] = { TLV_TYPE_TV }, + [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 }, + [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV }, + + [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV }, + [GSM48_IE_CAUSE] = { TLV_TYPE_TLV }, + [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV }, + [GSM48_IE_ALERT] = { TLV_TYPE_TLV }, + [GSM48_IE_FACILITY] = { TLV_TYPE_TLV }, + [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV }, + [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV }, + [GSM48_IE_NOTIFY] = { TLV_TYPE_TV }, + [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV }, + [GSM48_IE_SIGNAL] = { TLV_TYPE_TV }, + [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV }, + [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV }, + [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV }, + [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV }, + [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV }, + [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV }, + [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV }, + [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV }, + [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV }, + [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV }, + [GSM48_IE_USER_USER] = { TLV_TYPE_TLV }, + [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV }, + [GSM48_IE_MORE_DATA] = { TLV_TYPE_T }, + [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T }, + [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T }, + [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T }, + [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T }, + [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T }, + /* FIXME: more elements */ + }, +}; + +/* RR elements */ +const struct tlv_definition gsm48_rr_att_tlvdef = { + .def = { + /* NOTE: Don't add IE 17 = MOBILE_ID here, it already used. */ + [GSM48_IE_VGCS_TARGET] = { TLV_TYPE_TLV }, + [GSM48_IE_FRQSHORT_AFTER] = { TLV_TYPE_FIXED, 9 }, + [GSM48_IE_MUL_RATE_CFG] = { TLV_TYPE_TLV }, + [GSM48_IE_FREQ_L_AFTER] = { TLV_TYPE_TLV }, + [GSM48_IE_MSLOT_DESC] = { TLV_TYPE_TLV }, + [GSM48_IE_CHANMODE_2] = { TLV_TYPE_TV }, + [GSM48_IE_FRQSHORT_BEFORE] = { TLV_TYPE_FIXED, 9 }, + [GSM48_IE_CHANMODE_3] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_4] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_5] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_6] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_7] = { TLV_TYPE_TV }, + [GSM48_IE_CHANMODE_8] = { TLV_TYPE_TV }, + [GSM48_IE_FREQ_L_BEFORE] = { TLV_TYPE_TLV }, + [GSM48_IE_CH_DESC_1_BEFORE] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_CH_DESC_2_BEFORE] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_F_CH_SEQ_BEFORE] = { TLV_TYPE_FIXED, 9 }, + [GSM48_IE_CLASSMARK3] = { TLV_TYPE_TLV }, + [GSM48_IE_MA_BEFORE] = { TLV_TYPE_TLV }, + [GSM48_IE_RR_PACKET_UL] = { TLV_TYPE_TLV }, + [GSM48_IE_RR_PACKET_DL] = { TLV_TYPE_TLV }, + [GSM48_IE_CELL_CH_DESC] = { TLV_TYPE_FIXED, 16 }, + [GSM48_IE_CHANMODE_1] = { TLV_TYPE_TV }, + [GSM48_IE_CHDES_2_AFTER] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_MODE_SEC_CH] = { TLV_TYPE_TV }, + [GSM48_IE_F_CH_SEQ_AFTER] = { TLV_TYPE_FIXED, 9 }, + [GSM48_IE_MA_AFTER] = { TLV_TYPE_TLV }, + [GSM48_IE_BA_RANGE] = { TLV_TYPE_TLV }, + [GSM48_IE_GROUP_CHDES] = { TLV_TYPE_TLV }, + [GSM48_IE_BA_LIST_PREF] = { TLV_TYPE_TLV }, + [GSM48_IE_MOB_OVSERV_DIF] = { TLV_TYPE_TLV }, + [GSM48_IE_REALTIME_DIFF] = { TLV_TYPE_TLV }, + [GSM48_IE_START_TIME] = { TLV_TYPE_FIXED, 2 }, + [GSM48_IE_TIMING_ADVANCE] = { TLV_TYPE_TV }, + [GSM48_IE_GROUP_CIP_SEQ] = { TLV_TYPE_SINGLE_TV }, + [GSM48_IE_CIP_MODE_SET] = { TLV_TYPE_SINGLE_TV }, + [GSM48_IE_GPRS_RESUMPT] = { TLV_TYPE_SINGLE_TV }, + [GSM48_IE_SYNC_IND] = { TLV_TYPE_SINGLE_TV }, + }, +}; + +/* MM elements */ +const struct tlv_definition gsm48_mm_att_tlvdef = { + .def = { + [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV }, + [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV }, + [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV }, + [GSM48_IE_UTC] = { TLV_TYPE_TV }, + [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 }, + [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV }, + + [GSM48_IE_LOCATION_AREA] = { TLV_TYPE_FIXED, 5 }, + [GSM48_IE_PRIORITY_LEV] = { TLV_TYPE_SINGLE_TV }, + [GSM48_IE_FOLLOW_ON_PROC] = { TLV_TYPE_T }, + [GSM48_IE_CTS_PERMISSION] = { TLV_TYPE_T }, + }, +}; + +static const struct value_string rr_cause_names[] = { + { GSM48_RR_CAUSE_NORMAL, "Normal event" }, + { GSM48_RR_CAUSE_ABNORMAL_UNSPEC, "Abnormal release, unspecified" }, + { GSM48_RR_CAUSE_ABNORMAL_UNACCT, "Abnormal release, channel unacceptable" }, + { GSM48_RR_CAUSE_ABNORMAL_TIMER, "Abnormal release, timer expired" }, + { GSM48_RR_CAUSE_ABNORMAL_NOACT, "Abnormal release, no activity on radio path" }, + { GSM48_RR_CAUSE_PREMPTIVE_REL, "Preemptive release" }, + { GSM48_RR_CAUSE_HNDOVER_IMP, "Handover impossible, timing advance out of range" }, + { GSM48_RR_CAUSE_CHAN_MODE_UNACCT, "Channel mode unacceptable" }, + { GSM48_RR_CAUSE_FREQ_NOT_IMPL, "Frequency not implemented" }, + { GSM48_RR_CAUSE_CALL_CLEARED, "Call already cleared" }, + { GSM48_RR_CAUSE_SEMANT_INCORR, "Semantically incorrect message" }, + { GSM48_RR_CAUSE_INVALID_MAND_INF, "Invalid mandatory information" }, + { GSM48_RR_CAUSE_MSG_TYPE_N, "Message type non-existant or not implemented" }, + { GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT, "Message type not compatible with protocol state" }, + { GSM48_RR_CAUSE_COND_IE_ERROR, "Conditional IE error" }, + { GSM48_RR_CAUSE_NO_CELL_ALLOC_A, "No cell allocation available" }, + { GSM48_RR_CAUSE_PROT_ERROR_UNSPC, "Protocol error unspecified" }, + { 0, NULL }, +}; + +/* FIXME: convert to value_string */ +static const char *cc_state_names[32] = { + "NULL", + "INITIATED", + "MM_CONNECTION_PEND", + "MO_CALL_PROC", + "CALL_DELIVERED", + "illegal state 5", + "CALL_PRESENT", + "CALL_RECEIVED", + "CONNECT_REQUEST", + "MO_TERM_CALL_CONF", + "ACTIVE", + "DISCONNECT_REQ", + "DISCONNECT_IND", + "illegal state 13", + "illegal state 14", + "illegal state 15", + "illegal state 16", + "illegal state 17", + "illegal state 18", + "RELEASE_REQ", + "illegal state 20", + "illegal state 21", + "illegal state 22", + "illegal state 23", + "illegal state 24", + "illegal state 25", + "MO_ORIG_MODIFY", + "MO_TERM_MODIFY", + "CONNECT_IND", + "illegal state 29", + "illegal state 30", + "illegal state 31", +}; + +const char *gsm48_cc_state_name(uint8_t state) +{ + if (state < ARRAY_SIZE(cc_state_names)) + return cc_state_names[state]; + + return "invalid"; +} + +static const struct value_string cc_msg_names[] = { + { GSM48_MT_CC_ALERTING, "ALERTING" }, + { GSM48_MT_CC_CALL_PROC, "CALL_PROC" }, + { GSM48_MT_CC_PROGRESS, "PROGRESS" }, + { GSM48_MT_CC_ESTAB, "ESTAB" }, + { GSM48_MT_CC_SETUP, "SETUP" }, + { GSM48_MT_CC_ESTAB_CONF, "ESTAB_CONF" }, + { GSM48_MT_CC_CONNECT, "CONNECT" }, + { GSM48_MT_CC_CALL_CONF, "CALL_CONF" }, + { GSM48_MT_CC_START_CC, "START_CC" }, + { GSM48_MT_CC_RECALL, "RECALL" }, + { GSM48_MT_CC_EMERG_SETUP, "EMERG_SETUP" }, + { GSM48_MT_CC_CONNECT_ACK, "CONNECT_ACK" }, + { GSM48_MT_CC_USER_INFO, "USER_INFO" }, + { GSM48_MT_CC_MODIFY_REJECT, "MODIFY_REJECT" }, + { GSM48_MT_CC_MODIFY, "MODIFY" }, + { GSM48_MT_CC_HOLD, "HOLD" }, + { GSM48_MT_CC_HOLD_ACK, "HOLD_ACK" }, + { GSM48_MT_CC_HOLD_REJ, "HOLD_REJ" }, + { GSM48_MT_CC_RETR, "RETR" }, + { GSM48_MT_CC_RETR_ACK, "RETR_ACK" }, + { GSM48_MT_CC_RETR_REJ, "RETR_REJ" }, + { GSM48_MT_CC_MODIFY_COMPL, "MODIFY_COMPL" }, + { GSM48_MT_CC_DISCONNECT, "DISCONNECT" }, + { GSM48_MT_CC_RELEASE_COMPL, "RELEASE_COMPL" }, + { GSM48_MT_CC_RELEASE, "RELEASE" }, + { GSM48_MT_CC_STOP_DTMF, "STOP_DTMF" }, + { GSM48_MT_CC_STOP_DTMF_ACK, "STOP_DTMF_ACK" }, + { GSM48_MT_CC_STATUS_ENQ, "STATUS_ENQ" }, + { GSM48_MT_CC_START_DTMF, "START_DTMF" }, + { GSM48_MT_CC_START_DTMF_ACK, "START_DTMF_ACK" }, + { GSM48_MT_CC_START_DTMF_REJ, "START_DTMF_REJ" }, + { GSM48_MT_CC_CONG_CTRL, "CONG_CTRL" }, + { GSM48_MT_CC_FACILITY, "FACILITY" }, + { GSM48_MT_CC_STATUS, "STATUS" }, + { GSM48_MT_CC_NOTIFY, "NOTFIY" }, + { 0, NULL } +}; + +const char *gsm48_cc_msg_name(uint8_t msgtype) +{ + return get_value_string(cc_msg_names, msgtype); +} + +const char *rr_cause_name(uint8_t cause) +{ + return get_value_string(rr_cause_names, cause); +} + +static void to_bcd(uint8_t *bcd, uint16_t val) +{ + bcd[2] = val % 10; + val = val / 10; + bcd[1] = val % 10; + val = val / 10; + bcd[0] = val % 10; + val = val / 10; +} + +void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc, + uint16_t mnc, uint16_t lac) +{ + uint8_t bcd[3]; + + to_bcd(bcd, mcc); + lai48->digits[0] = bcd[0] | (bcd[1] << 4); + lai48->digits[1] = bcd[2]; + + to_bcd(bcd, mnc); + /* FIXME: do we need three-digit MNC? See Table 10.5.3 */ + if (mnc > 99) { + lai48->digits[1] |= bcd[2] << 4; + lai48->digits[2] = bcd[0] | (bcd[1] << 4); + } else { + lai48->digits[1] |= 0xf << 4; + lai48->digits[2] = bcd[1] | (bcd[2] << 4); + } + + lai48->lac = htons(lac); +} + +int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi) +{ + uint32_t *tptr = (uint32_t *) &buf[3]; + + buf[0] = GSM48_IE_MOBILE_ID; + buf[1] = GSM48_TMSI_LEN; + buf[2] = 0xf0 | GSM_MI_TYPE_TMSI; + *tptr = htonl(tmsi); + + return 7; +} + +int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi) +{ + unsigned int length = strlen(imsi), i, off = 0; + uint8_t odd = (length & 0x1) == 1; + + buf[0] = GSM48_IE_MOBILE_ID; + buf[2] = char2bcd(imsi[0]) << 4 | GSM_MI_TYPE_IMSI | (odd << 3); + + /* if the length is even we will fill half of the last octet */ + if (odd) + buf[1] = (length + 1) >> 1; + else + buf[1] = (length + 2) >> 1; + + for (i = 1; i < buf[1]; ++i) { + uint8_t lower, upper; + + lower = char2bcd(imsi[++off]); + if (!odd && off + 1 == length) + upper = 0x0f; + else + upper = char2bcd(imsi[++off]) & 0x0f; + + buf[2 + i] = (upper << 4) | lower; + } + + return 2 + buf[1]; +} + +/* Convert Mobile Identity (10.5.1.4) to string */ +int gsm48_mi_to_string(char *string, const int str_len, const uint8_t *mi, + const int mi_len) +{ + int i; + uint8_t mi_type; + char *str_cur = string; + uint32_t tmsi; + + mi_type = mi[0] & GSM_MI_TYPE_MASK; + + switch (mi_type) { + case GSM_MI_TYPE_NONE: + break; + case GSM_MI_TYPE_TMSI: + /* Table 10.5.4.3, reverse generate_mid_from_tmsi */ + if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) { + memcpy(&tmsi, &mi[1], 4); + tmsi = ntohl(tmsi); + return snprintf(string, str_len, "%u", tmsi); + } + break; + case GSM_MI_TYPE_IMSI: + case GSM_MI_TYPE_IMEI: + case GSM_MI_TYPE_IMEISV: + *str_cur++ = bcd2char(mi[0] >> 4); + + for (i = 1; i < mi_len; i++) { + if (str_cur + 2 >= string + str_len) + return str_cur - string; + *str_cur++ = bcd2char(mi[i] & 0xf); + /* skip last nibble in last input byte when GSM_EVEN */ + if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD)) + *str_cur++ = bcd2char(mi[i] >> 4); + } + break; + default: + break; + } + *str_cur++ = '\0'; + + return str_cur - string; +} + +void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf) +{ + raid->mcc = (buf[0] & 0xf) * 100; + raid->mcc += (buf[0] >> 4) * 10; + raid->mcc += (buf[1] & 0xf) * 1; + + /* I wonder who came up with the stupidity of encoding the MNC + * differently depending on how many digits its decimal number has! */ + if ((buf[1] >> 4) == 0xf) { + raid->mnc = (buf[2] & 0xf) * 10; + raid->mnc += (buf[2] >> 4) * 1; + } else { + raid->mnc = (buf[2] & 0xf) * 100; + raid->mnc += (buf[2] >> 4) * 10; + raid->mnc += (buf[1] >> 4) * 1; + } + + raid->lac = ntohs(*(uint16_t *)(buf + 3)); + raid->rac = buf[5]; +} + +int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid) +{ + uint16_t mcc = raid->mcc; + uint16_t mnc = raid->mnc; + + buf[0] = ((mcc / 100) % 10) | (((mcc / 10) % 10) << 4); + buf[1] = (mcc % 10); + + /* I wonder who came up with the stupidity of encoding the MNC + * differently depending on how many digits its decimal number has! */ + if (mnc < 100) { + buf[1] |= 0xf0; + buf[2] = ((mnc / 10) % 10) | ((mnc % 10) << 4); + } else { + buf[1] |= (mnc % 10) << 4; + buf[2] = ((mnc / 100) % 10) | (((mcc / 10) % 10) << 4); + } + + *(uint16_t *)(buf+3) = htons(raid->lac); + + buf[5] = raid->rac; + + return 6; +} diff --git a/src/gsm/gsm48_ie.c b/src/gsm/gsm48_ie.c new file mode 100644 index 00000000..0e270881 --- /dev/null +++ b/src/gsm/gsm48_ie.c @@ -0,0 +1,1095 @@ +/* GSM Mobile Radio Interface Layer 3 messages + * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ + +/* (C) 2008 by Harald Welte + * (C) 2009-2010 by Andreas Eversberg + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static const char bcd_num_digits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '*', '#', 'a', 'b', 'c', '\0' +}; + +/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */ +int gsm48_decode_bcd_number(char *output, int output_len, + const uint8_t *bcd_lv, int h_len) +{ + uint8_t in_len = bcd_lv[0]; + int i; + + for (i = 1 + h_len; i <= in_len; i++) { + /* lower nibble */ + output_len--; + if (output_len <= 1) + break; + *output++ = bcd_num_digits[bcd_lv[i] & 0xf]; + + /* higher nibble */ + output_len--; + if (output_len <= 1) + break; + *output++ = bcd_num_digits[bcd_lv[i] >> 4]; + } + if (output_len >= 1) + *output++ = '\0'; + + return 0; +} + +/* convert a single ASCII character to call-control BCD */ +static int asc_to_bcd(const char asc) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) { + if (bcd_num_digits[i] == asc) + return i; + } + return -EINVAL; +} + +/* convert a ASCII phone number to 'called/calling/connect party BCD number' */ +int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len, + int h_len, const char *input) +{ + int in_len = strlen(input); + int i; + uint8_t *bcd_cur = bcd_lv + 1 + h_len; + + /* two digits per byte, plus type byte */ + bcd_lv[0] = in_len/2 + h_len; + if (in_len % 2) + bcd_lv[0]++; + + if (bcd_lv[0] > max_len) + return -EIO; + + for (i = 0; i < in_len; i++) { + int rc = asc_to_bcd(input[i]); + if (rc < 0) + return rc; + if (i % 2 == 0) + *bcd_cur = rc; + else + *bcd_cur++ |= (rc << 4); + } + /* append padding nibble in case of odd length */ + if (i % 2) + *bcd_cur++ |= 0xf0; + + /* return how many bytes we used */ + return (bcd_cur - bcd_lv); +} + +/* decode 'bearer capability' */ +int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap, + const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + int i, s; + + if (in_len < 1) + return -EINVAL; + + bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */ + + /* octet 3 */ + bcap->transfer = lv[1] & 0x07; + bcap->mode = (lv[1] & 0x08) >> 3; + bcap->coding = (lv[1] & 0x10) >> 4; + bcap->radio = (lv[1] & 0x60) >> 5; + + if (bcap->transfer == GSM_MNCC_BCAP_SPEECH) { + i = 1; + s = 0; + while(!(lv[i] & 0x80)) { + i++; /* octet 3a etc */ + if (in_len < i) + return 0; + bcap->speech_ver[s++] = lv[i] & 0x0f; + bcap->speech_ver[s] = -1; /* end of list */ + if (i == 2) /* octet 3a */ + bcap->speech_ctm = (lv[i] & 0x20) >> 5; + if (s == 7) /* maximum speech versions + end of list */ + return 0; + } + } else { + i = 1; + while (!(lv[i] & 0x80)) { + i++; /* octet 3a etc */ + if (in_len < i) + return 0; + /* ignore them */ + } + /* FIXME: implement OCTET 4+ parsing */ + } + + return 0; +} + +/* encode 'bearer capability' */ +int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only, + const struct gsm_mncc_bearer_cap *bcap) +{ + uint8_t lv[32 + 1]; + int i = 1, s; + + lv[1] = bcap->transfer; + lv[1] |= bcap->mode << 3; + lv[1] |= bcap->coding << 4; + lv[1] |= bcap->radio << 5; + + if (bcap->transfer == GSM_MNCC_BCAP_SPEECH) { + for (s = 0; bcap->speech_ver[s] >= 0; s++) { + i++; /* octet 3a etc */ + lv[i] = bcap->speech_ver[s]; + if (i == 2) /* octet 3a */ + lv[i] |= bcap->speech_ctm << 5; + } + lv[i] |= 0x80; /* last IE of octet 3 etc */ + } else { + /* FIXME: implement OCTET 4+ encoding */ + } + + lv[0] = i; + if (lv_only) + msgb_lv_put(msg, lv[0], lv+1); + else + msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1); + + return 0; +} + +/* decode 'call control cap' */ +int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + + if (in_len < 1) + return -EINVAL; + + /* octet 3 */ + ccap->dtmf = lv[1] & 0x01; + ccap->pcp = (lv[1] & 0x02) >> 1; + + return 0; +} + +/* encode 'call control cap' */ +int gsm48_encode_cccap(struct msgb *msg, + const struct gsm_mncc_cccap *ccap) +{ + uint8_t lv[2]; + + lv[0] = 1; + lv[1] = 0; + if (ccap->dtmf) + lv [1] |= 0x01; + if (ccap->pcp) + lv [1] |= 0x02; + + msgb_tlv_put(msg, GSM48_IE_CC_CAP, lv[0], lv+1); + + return 0; +} + +/* decode 'called party BCD number' */ +int gsm48_decode_called(struct gsm_mncc_number *called, + const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + + if (in_len < 1) + return -EINVAL; + + /* octet 3 */ + called->plan = lv[1] & 0x0f; + called->type = (lv[1] & 0x70) >> 4; + + /* octet 4..N */ + gsm48_decode_bcd_number(called->number, sizeof(called->number), lv, 1); + + return 0; +} + +/* encode 'called party BCD number' */ +int gsm48_encode_called(struct msgb *msg, + const struct gsm_mncc_number *called) +{ + uint8_t lv[18]; + int ret; + + /* octet 3 */ + lv[1] = 0x80; /* no extension */ + lv[1] |= called->plan; + lv[1] |= called->type << 4; + + /* octet 4..N, octet 2 */ + ret = gsm48_encode_bcd_number(lv, sizeof(lv), 1, called->number); + if (ret < 0) + return ret; + + msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1); + + return 0; +} + +/* decode callerid of various IEs */ +int gsm48_decode_callerid(struct gsm_mncc_number *callerid, + const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + int i = 1; + + if (in_len < 1) + return -EINVAL; + + /* octet 3 */ + callerid->plan = lv[1] & 0x0f; + callerid->type = (lv[1] & 0x70) >> 4; + + /* octet 3a */ + if (!(lv[1] & 0x80)) { + callerid->screen = lv[2] & 0x03; + callerid->present = (lv[2] & 0x60) >> 5; + i = 2; + } + + /* octet 4..N */ + gsm48_decode_bcd_number(callerid->number, sizeof(callerid->number), lv, i); + + return 0; +} + +/* encode callerid of various IEs */ +int gsm48_encode_callerid(struct msgb *msg, int ie, int max_len, + const struct gsm_mncc_number *callerid) +{ + uint8_t lv[max_len - 1]; + int h_len = 1; + int ret; + + /* octet 3 */ + lv[1] = callerid->plan; + lv[1] |= callerid->type << 4; + + if (callerid->present || callerid->screen) { + /* octet 3a */ + lv[2] = callerid->screen; + lv[2] |= callerid->present << 5; + lv[2] |= 0x80; + h_len++; + } else + lv[1] |= 0x80; + + /* octet 4..N, octet 2 */ + ret = gsm48_encode_bcd_number(lv, sizeof(lv), h_len, callerid->number); + if (ret < 0) + return ret; + + msgb_tlv_put(msg, ie, lv[0], lv+1); + + return 0; +} + +/* decode 'cause' */ +int gsm48_decode_cause(struct gsm_mncc_cause *cause, + const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + int i; + + if (in_len < 2) + return -EINVAL; + + cause->diag_len = 0; + + /* octet 3 */ + cause->location = lv[1] & 0x0f; + cause->coding = (lv[1] & 0x60) >> 5; + + i = 1; + if (!(lv[i] & 0x80)) { + i++; /* octet 3a */ + if (in_len < i+1) + return 0; + cause->rec = 1; + cause->rec_val = lv[i] & 0x7f; + } + i++; + + /* octet 4 */ + cause->value = lv[i] & 0x7f; + i++; + + if (in_len < i) /* no diag */ + return 0; + + if (in_len - (i-1) > 32) /* maximum 32 octets */ + return 0; + + /* octet 5-N */ + memcpy(cause->diag, lv + i, in_len - (i-1)); + cause->diag_len = in_len - (i-1); + + return 0; +} + +/* encode 'cause' */ +int gsm48_encode_cause(struct msgb *msg, int lv_only, + const struct gsm_mncc_cause *cause) +{ + uint8_t lv[32+4]; + int i; + + if (cause->diag_len > 32) + return -EINVAL; + + /* octet 3 */ + lv[1] = cause->location; + lv[1] |= cause->coding << 5; + + i = 1; + if (cause->rec) { + i++; /* octet 3a */ + lv[i] = cause->rec_val; + } + lv[i] |= 0x80; /* end of octet 3 */ + + /* octet 4 */ + i++; + lv[i] = 0x80 | cause->value; + + /* octet 5-N */ + if (cause->diag_len) { + memcpy(lv + i, cause->diag, cause->diag_len); + i += cause->diag_len; + } + + lv[0] = i; + if (lv_only) + msgb_lv_put(msg, lv[0], lv+1); + else + msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1); + + return 0; +} + +/* decode 'calling number' */ +int gsm48_decode_calling(struct gsm_mncc_number *calling, + const uint8_t *lv) +{ + return gsm48_decode_callerid(calling, lv); +} + +/* encode 'calling number' */ +int gsm48_encode_calling(struct msgb *msg, + const struct gsm_mncc_number *calling) +{ + return gsm48_encode_callerid(msg, GSM48_IE_CALLING_BCD, 14, calling); +} + +/* decode 'connected number' */ +int gsm48_decode_connected(struct gsm_mncc_number *connected, + const uint8_t *lv) +{ + return gsm48_decode_callerid(connected, lv); +} + +/* encode 'connected number' */ +int gsm48_encode_connected(struct msgb *msg, + const struct gsm_mncc_number *connected) +{ + return gsm48_encode_callerid(msg, GSM48_IE_CONN_BCD, 14, connected); +} + +/* decode 'redirecting number' */ +int gsm48_decode_redirecting(struct gsm_mncc_number *redirecting, + const uint8_t *lv) +{ + return gsm48_decode_callerid(redirecting, lv); +} + +/* encode 'redirecting number' */ +int gsm48_encode_redirecting(struct msgb *msg, + const struct gsm_mncc_number *redirecting) +{ + return gsm48_encode_callerid(msg, GSM48_IE_REDIR_BCD, 19, redirecting); +} + +/* decode 'facility' */ +int gsm48_decode_facility(struct gsm_mncc_facility *facility, + const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + + if (in_len < 1) + return -EINVAL; + + if (in_len > sizeof(facility->info)) + return -EINVAL; + + memcpy(facility->info, lv+1, in_len); + facility->len = in_len; + + return 0; +} + +/* encode 'facility' */ +int gsm48_encode_facility(struct msgb *msg, int lv_only, + const struct gsm_mncc_facility *facility) +{ + uint8_t lv[GSM_MAX_FACILITY + 1]; + + if (facility->len < 1 || facility->len > GSM_MAX_FACILITY) + return -EINVAL; + + memcpy(lv+1, facility->info, facility->len); + lv[0] = facility->len; + if (lv_only) + msgb_lv_put(msg, lv[0], lv+1); + else + msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1); + + return 0; +} + +/* decode 'notify' */ +int gsm48_decode_notify(int *notify, const uint8_t *v) +{ + *notify = v[0] & 0x7f; + + return 0; +} + +/* encode 'notify' */ +int gsm48_encode_notify(struct msgb *msg, int notify) +{ + msgb_v_put(msg, notify | 0x80); + + return 0; +} + +/* decode 'signal' */ +int gsm48_decode_signal(int *signal, const uint8_t *v) +{ + *signal = v[0]; + + return 0; +} + +/* encode 'signal' */ +int gsm48_encode_signal(struct msgb *msg, int signal) +{ + msgb_tv_put(msg, GSM48_IE_SIGNAL, signal); + + return 0; +} + +/* decode 'keypad' */ +int gsm48_decode_keypad(int *keypad, const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + + if (in_len < 1) + return -EINVAL; + + *keypad = lv[1] & 0x7f; + + return 0; +} + +/* encode 'keypad' */ +int gsm48_encode_keypad(struct msgb *msg, int keypad) +{ + msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad); + + return 0; +} + +/* decode 'progress' */ +int gsm48_decode_progress(struct gsm_mncc_progress *progress, + const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + + if (in_len < 2) + return -EINVAL; + + progress->coding = (lv[1] & 0x60) >> 5; + progress->location = lv[1] & 0x0f; + progress->descr = lv[2] & 0x7f; + + return 0; +} + +/* encode 'progress' */ +int gsm48_encode_progress(struct msgb *msg, int lv_only, + const struct gsm_mncc_progress *p) +{ + uint8_t lv[3]; + + lv[0] = 2; + lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf); + lv[2] = 0x80 | (p->descr & 0x7f); + if (lv_only) + msgb_lv_put(msg, lv[0], lv+1); + else + msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1); + + return 0; +} + +/* decode 'user-user' */ +int gsm48_decode_useruser(struct gsm_mncc_useruser *uu, + const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + char *info = uu->info; + int info_len = sizeof(uu->info); + int i; + + if (in_len < 1) + return -EINVAL; + + uu->proto = lv[1]; + + for (i = 2; i <= in_len; i++) { + info_len--; + if (info_len <= 1) + break; + *info++ = lv[i]; + } + if (info_len >= 1) + *info++ = '\0'; + + return 0; +} + +/* encode 'useruser' */ +int gsm48_encode_useruser(struct msgb *msg, int lv_only, + const struct gsm_mncc_useruser *uu) +{ + uint8_t lv[GSM_MAX_USERUSER + 2]; + + if (strlen(uu->info) > GSM_MAX_USERUSER) + return -EINVAL; + + lv[0] = 1 + strlen(uu->info); + lv[1] = uu->proto; + memcpy(lv + 2, uu->info, strlen(uu->info)); + if (lv_only) + msgb_lv_put(msg, lv[0], lv+1); + else + msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1); + + return 0; +} + +/* decode 'ss version' */ +int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv, + const uint8_t *lv) +{ + uint8_t in_len = lv[0]; + + if (in_len < 1 || in_len < sizeof(ssv->info)) + return -EINVAL; + + memcpy(ssv->info, lv + 1, in_len); + ssv->len = in_len; + + return 0; +} + +/* encode 'ss version' */ +int gsm48_encode_ssversion(struct msgb *msg, + const struct gsm_mncc_ssversion *ssv) +{ + uint8_t lv[GSM_MAX_SSVERSION + 1]; + + if (ssv->len > GSM_MAX_SSVERSION) + return -EINVAL; + + lv[0] = ssv->len; + memcpy(lv + 1, ssv->info, ssv->len); + msgb_tlv_put(msg, GSM48_IE_SS_VERS, lv[0], lv+1); + + return 0; +} + +/* decode 'more data' does not require a function, because it has no value */ + +/* encode 'more data' */ +int gsm48_encode_more(struct msgb *msg) +{ + uint8_t *ie; + + ie = msgb_put(msg, 1); + ie[0] = GSM48_IE_MORE_DATA; + + return 0; +} + +/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */ +int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd, + uint8_t len, uint8_t mask, uint8_t frqt) +{ + int i; + + /* NOTES: + * + * The Range format uses "SMOD" computation. + * e.g. "n SMOD m" equals "((n - 1) % m) + 1" + * A cascade of multiple SMOD computations is simpified: + * "(n SMOD m) SMOD o" equals "(((n - 1) % m) % o) + 1" + * + * The Range format uses 16 octets of data in SYSTEM INFORMATION. + * When used in dedicated messages, the length can be less. + * In this case the ranges are decoded for all frequencies that + * fit in the block of given length. + */ + + /* tabula rasa */ + for (i = 0; i < 1024; i++) + f[i].mask &= ~frqt; + + /* 00..XXX. */ + if ((cd[0] & 0xc0 & mask) == 0x00) { + /* Bit map 0 format */ + if (len < 16) + return -EINVAL; + for (i = 1; i <= 124; i++) + if ((cd[15 - ((i-1) >> 3)] & (1 << ((i-1) & 7)))) + f[i].mask |= frqt; + + return 0; + } + + /* 10..0XX. */ + if ((cd[0] & 0xc8 & mask) == 0x80) { + /* Range 1024 format */ + uint16_t w[17]; /* 1..16 */ + struct gsm48_range_1024 *r = (struct gsm48_range_1024 *)cd; + + if (len < 2) + return -EINVAL; + memset(w, 0, sizeof(w)); + if (r->f0) + f[0].mask |= frqt; + w[1] = (r->w1_hi << 8) | r->w1_lo; + if (len >= 4) + w[2] = (r->w2_hi << 1) | r->w2_lo; + if (len >= 5) + w[3] = (r->w3_hi << 2) | r->w3_lo; + if (len >= 6) + w[4] = (r->w4_hi << 2) | r->w4_lo; + if (len >= 7) + w[5] = (r->w5_hi << 2) | r->w5_lo; + if (len >= 8) + w[6] = (r->w6_hi << 2) | r->w6_lo; + if (len >= 9) + w[7] = (r->w7_hi << 2) | r->w7_lo; + if (len >= 10) + w[8] = (r->w8_hi << 1) | r->w8_lo; + if (len >= 10) + w[9] = r->w9; + if (len >= 11) + w[10] = r->w10; + if (len >= 12) + w[11] = (r->w11_hi << 6) | r->w11_lo; + if (len >= 13) + w[12] = (r->w12_hi << 5) | r->w12_lo; + if (len >= 14) + w[13] = (r->w13_hi << 4) | r->w13_lo; + if (len >= 15) + w[14] = (r->w14_hi << 3) | r->w14_lo; + if (len >= 16) + w[15] = (r->w15_hi << 2) | r->w15_lo; + if (len >= 16) + w[16] = r->w16; + if (w[1]) + f[w[1]].mask |= frqt; + if (w[2]) + f[((w[1] - 512 + w[2] - 1) % 1023) + 1].mask |= frqt; + if (w[3]) + f[((w[1] + w[3] - 1) % 1023) + 1].mask |= frqt; + if (w[4]) + f[((w[1] - 512 + ((w[2] - 256 + w[4] - 1) % 511)) % 1023) + 1].mask |= frqt; + if (w[5]) + f[((w[1] + ((w[3] - 256 - w[5] - 1) % 511)) % 1023) + 1].mask |= frqt; + if (w[6]) + f[((w[1] - 512 + ((w[2] + w[6] - 1) % 511)) % 1023) + 1].mask |= frqt; + if (w[7]) + f[((w[1] + ((w[3] + w[7] - 1) % 511)) % 1023) + 1].mask |= frqt; + if (w[8]) + f[((w[1] - 512 + ((w[2] - 256 + ((w[4] - 128 + w[8] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; + if (w[9]) + f[((w[1] + ((w[3] - 256 + ((w[5] - 128 + w[9] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; + if (w[10]) + f[((w[1] - 512 + ((w[2] + ((w[6] - 128 + w[10] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; + if (w[11]) + f[((w[1] + ((w[3] + ((w[7] - 128 + w[11] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; + if (w[12]) + f[((w[1] - 512 + ((w[2] - 256 + ((w[4] + w[12] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; + if (w[13]) + f[((w[1] + ((w[3] - 256 + ((w[5] + w[13] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; + if (w[14]) + f[((w[1] - 512 + ((w[2] + ((w[6] + w[14] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; + if (w[15]) + f[((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; + if (w[16]) + f[((w[1] - 512 + ((w[2] - 256 + ((w[4] - 128 + ((w[8] - 64 + w[16] - 1) % 127)) % 255)) % 511)) % 1023) + 1].mask |= frqt; + + return 0; + } + /* 10..100. */ + if ((cd[0] & 0xce & mask) == 0x88) { + /* Range 512 format */ + uint16_t w[18]; /* 1..17 */ + struct gsm48_range_512 *r = (struct gsm48_range_512 *)cd; + + if (len < 4) + return -EINVAL; + memset(w, 0, sizeof(w)); + w[0] = (r->orig_arfcn_hi << 9) | (r->orig_arfcn_mid << 1) | r->orig_arfcn_lo; + w[1] = (r->w1_hi << 2) | r->w1_lo; + if (len >= 5) + w[2] = (r->w2_hi << 2) | r->w2_lo; + if (len >= 6) + w[3] = (r->w3_hi << 2) | r->w3_lo; + if (len >= 7) + w[4] = (r->w4_hi << 1) | r->w4_lo; + if (len >= 7) + w[5] = r->w5; + if (len >= 8) + w[6] = r->w6; + if (len >= 9) + w[7] = (r->w7_hi << 6) | r->w7_lo; + if (len >= 10) + w[8] = (r->w8_hi << 4) | r->w8_lo; + if (len >= 11) + w[9] = (r->w9_hi << 2) | r->w9_lo; + if (len >= 11) + w[10] = r->w10; + if (len >= 12) + w[11] = r->w11; + if (len >= 13) + w[12] = (r->w12_hi << 4) | r->w12_lo; + if (len >= 14) + w[13] = (r->w13_hi << 2) | r->w13_lo; + if (len >= 14) + w[14] = r->w14; + if (len >= 15) + w[15] = r->w15; + if (len >= 16) + w[16] = (r->w16_hi << 3) | r->w16_lo; + if (len >= 16) + w[17] = r->w17; + f[w[0]].mask |= frqt; + if (w[1]) + f[(w[0] + w[1]) % 1024].mask |= frqt; + if (w[2]) + f[(w[0] + ((w[1] - 256 + w[2] - 1) % 511) + 1) % 1024].mask |= frqt; + if (w[3]) + f[(w[0] + ((w[1] + w[3] - 1) % 511) + 1) % 1024].mask |= frqt; + if (w[4]) + f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + w[4] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[5]) + f[(w[0] + ((w[1] + ((w[3] - 128 + w[5] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[6]) + f[(w[0] + ((w[1] - 256 + ((w[2] + w[6] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[7]) + f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[8]) + f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] - 64 + w[8] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[9]) + f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] - 64 + w[9] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[10]) + f[(w[0] + ((w[1] - 256 + ((w[2] + ((w[6] - 64 + w[10] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[11]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 64 + w[11] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[12]) + f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] + w[12] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[13]) + f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] + w[13] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[14]) + f[(w[0] + ((w[1] - 256 + ((w[2] + ((w[6] + w[14] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[15]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[16]) + f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] - 64 + ((w[8] - 32 + w[16] - 1) % 63)) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + if (w[17]) + f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] - 64 + ((w[9] - 32 + w[17] - 1) % 63)) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; + + return 0; + } + /* 10..101. */ + if ((cd[0] & 0xce & mask) == 0x8a) { + /* Range 256 format */ + uint16_t w[22]; /* 1..21 */ + struct gsm48_range_256 *r = (struct gsm48_range_256 *)cd; + + if (len < 4) + return -EINVAL; + memset(w, 0, sizeof(w)); + w[0] = (r->orig_arfcn_hi << 9) | (r->orig_arfcn_mid << 1) | r->orig_arfcn_lo; + w[1] = (r->w1_hi << 1) | r->w1_lo; + if (len >= 4) + w[2] = r->w2; + if (len >= 5) + w[3] = r->w3; + if (len >= 6) + w[4] = (r->w4_hi << 5) | r->w4_lo; + if (len >= 7) + w[5] = (r->w5_hi << 3) | r->w5_lo; + if (len >= 8) + w[6] = (r->w6_hi << 1) | r->w6_lo; + if (len >= 8) + w[7] = r->w7; + if (len >= 9) + w[8] = (r->w8_hi << 4) | r->w8_lo; + if (len >= 10) + w[9] = (r->w9_hi << 1) | r->w9_lo; + if (len >= 10) + w[10] = r->w10; + if (len >= 11) + w[11] = (r->w11_hi << 3) | r->w11_lo; + if (len >= 11) + w[12] = r->w12; + if (len >= 12) + w[13] = r->w13; + if (len >= 13) + w[14] = r->w15; + if (len >= 13) + w[15] = (r->w14_hi << 2) | r->w14_lo; + if (len >= 14) + w[16] = (r->w16_hi << 3) | r->w16_lo; + if (len >= 14) + w[17] = r->w17; + if (len >= 15) + w[18] = r->w19; + if (len >= 15) + w[19] = (r->w18_hi << 3) | r->w18_lo; + if (len >= 16) + w[20] = (r->w20_hi << 3) | r->w20_lo; + if (len >= 16) + w[21] = r->w21; + f[w[0]].mask |= frqt; + if (w[1]) + f[(w[0] + w[1]) % 1024].mask |= frqt; + if (w[2]) + f[(w[0] + ((w[1] - 128 + w[2] - 1) % 255) + 1) % 1024].mask |= frqt; + if (w[3]) + f[(w[0] + ((w[1] + w[3] - 1) % 255) + 1) % 1024].mask |= frqt; + if (w[4]) + f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + w[4] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[5]) + f[(w[0] + ((w[1] + ((w[3] - 64 + w[5] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[6]) + f[(w[0] + ((w[1] - 128 + ((w[2] + w[6] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[7]) + f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[8]) + f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] - 32 + w[8] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[9]) + f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] - 32 + w[9] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[10]) + f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] - 32 + w[10] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[11]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 32 + w[11] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[12]) + f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] + w[12] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[13]) + f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] + w[13] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[14]) + f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] + w[14] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[15]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[16]) + f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] - 32 + ((w[8] - 16 + w[16] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[17]) + f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] - 32 + ((w[9] - 16 + w[17] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[18]) + f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] - 32 + ((w[10] - 16 + w[18] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[19]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 32 + ((w[11] - 16 + w[19] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[20]) + f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] + ((w[12] - 16 + w[20] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + if (w[21]) + f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] + ((w[13] - 16 + w[21] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; + + return 0; + } + /* 10..110. */ + if ((cd[0] & 0xce & mask) == 0x8c) { + /* Range 128 format */ + uint16_t w[29]; /* 1..28 */ + struct gsm48_range_128 *r = (struct gsm48_range_128 *)cd; + + if (len < 3) + return -EINVAL; + memset(w, 0, sizeof(w)); + w[0] = (r->orig_arfcn_hi << 9) | (r->orig_arfcn_mid << 1) | r->orig_arfcn_lo; + w[1] = r->w1; + if (len >= 4) + w[2] = r->w2; + if (len >= 5) + w[3] = (r->w3_hi << 4) | r->w3_lo; + if (len >= 6) + w[4] = (r->w4_hi << 1) | r->w4_lo; + if (len >= 6) + w[5] = r->w5; + if (len >= 7) + w[6] = (r->w6_hi << 3) | r->w6_lo; + if (len >= 7) + w[7] = r->w7; + if (len >= 8) + w[8] = r->w8; + if (len >= 8) + w[9] = r->w9; + if (len >= 9) + w[10] = r->w10; + if (len >= 9) + w[11] = r->w11; + if (len >= 10) + w[12] = r->w12; + if (len >= 10) + w[13] = r->w13; + if (len >= 11) + w[14] = r->w14; + if (len >= 11) + w[15] = r->w15; + if (len >= 12) + w[16] = r->w16; + if (len >= 12) + w[17] = r->w17; + if (len >= 13) + w[18] = (r->w18_hi << 1) | r->w18_lo; + if (len >= 13) + w[19] = r->w19; + if (len >= 13) + w[20] = r->w20; + if (len >= 14) + w[21] = (r->w21_hi << 2) | r->w21_lo; + if (len >= 14) + w[22] = r->w22; + if (len >= 14) + w[23] = r->w23; + if (len >= 15) + w[24] = r->w24; + if (len >= 15) + w[25] = r->w25; + if (len >= 16) + w[26] = (r->w26_hi << 1) | r->w26_lo; + if (len >= 16) + w[27] = r->w27; + if (len >= 16) + w[28] = r->w28; + f[w[0]].mask |= frqt; + if (w[1]) + f[(w[0] + w[1]) % 1024].mask |= frqt; + if (w[2]) + f[(w[0] + ((w[1] - 64 + w[2] - 1) % 127) + 1) % 1024].mask |= frqt; + if (w[3]) + f[(w[0] + ((w[1] + w[3] - 1) % 127) + 1) % 1024].mask |= frqt; + if (w[4]) + f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + w[4] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[5]) + f[(w[0] + ((w[1] + ((w[3] - 32 + w[5] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[6]) + f[(w[0] + ((w[1] - 64 + ((w[2] + w[6] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[7]) + f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[8]) + f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + w[8] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[9]) + f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + w[9] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[10]) + f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + w[10] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[11]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + w[11] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[12]) + f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + w[12] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[13]) + f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] + w[13] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[14]) + f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] + w[14] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[15]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[16]) + f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + ((w[8] - 8 + w[16] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[17]) + f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + ((w[9] - 8 + w[17] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[18]) + f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + ((w[10] - 8 + w[18] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[19]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + ((w[11] - 8 + w[19] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[20]) + f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + ((w[12] - 8 + w[20] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[21]) + f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] + ((w[13] - 8 + w[21] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[22]) + f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] + ((w[14] - 8 + w[22] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[23]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] + ((w[15] - 8 + w[23] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[24]) + f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + ((w[8] + w[24] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[25]) + f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + ((w[9] + w[25] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[26]) + f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + ((w[10] + w[26] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[27]) + f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + ((w[11] + w[27] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + if (w[28]) + f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + ((w[12] + w[28] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; + + return 0; + } + /* 10..111. */ + if ((cd[0] & 0xce & mask) == 0x8e) { + /* Variable bitmap format (can be any length >= 3) */ + uint16_t orig = 0; + struct gsm48_var_bit *r = (struct gsm48_var_bit *)cd; + + if (len < 3) + return -EINVAL; + orig = (r->orig_arfcn_hi << 9) | (r->orig_arfcn_mid << 1) | r->orig_arfcn_lo; + f[orig].mask |= frqt; + for (i = 1; 2 + (i >> 3) < len; i++) + if ((cd[2 + (i >> 3)] & (0x80 >> (i & 7)))) + f[(orig + i) % 1024].mask |= frqt; + + return 0; + } + + return 0; +} diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c new file mode 100644 index 00000000..54a13ad8 --- /dev/null +++ b/src/gsm/gsm_utils.c @@ -0,0 +1,465 @@ +/* + * (C) 2008 by Daniel Willmann + * (C) 2009 by Holger Hans Peter Freyther + * (C) 2009-2010 by Harald Welte + * (C) 2010 by Nico Golde + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +//#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../config.h" + +/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet + * Greek symbols at hex positions 0x10 and 0x12-0x1a + * left out as they can't be handled with a char and + * since most phones don't display or write these + * characters this would only needlessly make the code + * more complex +*/ +static unsigned char gsm_7bit_alphabet[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, + 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff, + 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff, + 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, + 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f, + 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, + 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff +}; + +/* GSM 03.38 6.2.1 Character lookup for decoding */ +static int gsm_septet_lookup(uint8_t ch) +{ + int i = 0; + for(; i < sizeof(gsm_7bit_alphabet); i++){ + if(gsm_7bit_alphabet[i] == ch) + return i; + } + return -1; +} + +/* GSM 03.38 6.2.1 Character unpacking */ +int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t length) +{ + int i = 0; + int l = 0; + int septet_l = (length * 8) / 7; + uint8_t *rtext = calloc(septet_l, sizeof(uint8_t)); + uint8_t tmp; + + /* FIXME: We need to account for user data headers here */ + i += l; + for (; i < septet_l; i++){ + rtext[i] = + ((user_data[(i * 7 + 7) >> 3] << + (7 - ((i * 7 + 7) & 7))) | + (user_data[(i * 7) >> 3] >> + ((i * 7) & 7))) & 0x7f; + } + + for(i = 0; i < septet_l; i++){ + /* this is an extension character */ + if(rtext[i] == 0x1b && i + 1 < length){ + tmp = rtext[i+1]; + *(text++) = gsm_7bit_alphabet[0x7f + tmp]; + i++; + continue; + } + + *(text++) = gsm_septet_lookup(rtext[i]); + } + + *text = '\0'; + free(rtext); + + return i; +} + +/* GSM 03.38 6.2.1 Prepare character packing */ +static int gsm_septet_encode(uint8_t *result, const char *data) +{ + int i, y = 0; + uint8_t ch; + for(i = 0; i < strlen(data); i++){ + ch = data[i]; + switch(ch){ + /* fall-through for extension characters */ + case 0x0c: + case 0x5e: + case 0x7b: + case 0x7d: + case 0x5c: + case 0x5b: + case 0x7e: + case 0x5d: + case 0x7c: + result[y++] = 0x1b; + default: + result[y] = gsm_7bit_alphabet[ch]; + break; + } + y++; + } + + return y; +} + +/* GSM 03.38 6.2.1 Character packing */ +int gsm_7bit_encode(uint8_t *result, const char *data) +{ + int i,y,z = 0; + /* prepare for the worst case, every character expanding to two bytes */ + uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t)); + uint8_t cb, nb; + int shift = 0; + + y = gsm_septet_encode(rdata, data); + + for(i = 0; i < y; i++) { + if(shift == 7 && i + 1 < y){ + shift = 0; + continue; + } + + cb = (rdata[i] & 0x7f) >> shift; + if(i + 1 < y){ + nb = (rdata[i + 1] & 0x7f) << (7 - shift); + cb = cb | nb; + } + + result[z++] = cb; + + shift++; + } + + free(rdata); + return z; +} + +/* determine power control level for given dBm value, as indicated + * by the tables in chapter 4.1.1 of GSM TS 05.05 */ +int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm) +{ + switch (band) { + case GSM_BAND_450: + case GSM_BAND_480: + case GSM_BAND_750: + case GSM_BAND_900: + case GSM_BAND_810: + case GSM_BAND_850: + if (dbm >= 39) + return 0; + else if (dbm < 5) + return 19; + else { + /* we are guaranteed to have (5 <= dbm < 39) */ + return 2 + ((39 - dbm) / 2); + } + break; + case GSM_BAND_1800: + if (dbm >= 36) + return 29; + else if (dbm >= 34) + return 30; + else if (dbm >= 32) + return 31; + else if (dbm == 31) + return 0; + else { + /* we are guaranteed to have (0 <= dbm < 31) */ + return (30 - dbm) / 2; + } + break; + case GSM_BAND_1900: + if (dbm >= 33) + return 30; + else if (dbm >= 32) + return 31; + else if (dbm == 31) + return 0; + else { + /* we are guaranteed to have (0 <= dbm < 31) */ + return (30 - dbm) / 2; + } + break; + } + return -EINVAL; +} + +int ms_pwr_dbm(enum gsm_band band, uint8_t lvl) +{ + lvl &= 0x1f; + + switch (band) { + case GSM_BAND_450: + case GSM_BAND_480: + case GSM_BAND_750: + case GSM_BAND_900: + case GSM_BAND_810: + case GSM_BAND_850: + if (lvl < 2) + return 39; + else if (lvl < 20) + return 39 - ((lvl - 2) * 2) ; + else + return 5; + break; + case GSM_BAND_1800: + if (lvl < 16) + return 30 - (lvl * 2); + else if (lvl < 29) + return 0; + else + return 36 - ((lvl - 29) * 2); + break; + case GSM_BAND_1900: + if (lvl < 16) + return 30 - (lvl * 2); + else if (lvl < 30) + return -EINVAL; + else + return 33 - (lvl - 30); + break; + } + return -EINVAL; +} + +/* According to TS 08.05 Chapter 8.1.4 */ +int rxlev2dbm(uint8_t rxlev) +{ + if (rxlev > 63) + rxlev = 63; + + return -110 + rxlev; +} + +/* According to TS 08.05 Chapter 8.1.4 */ +uint8_t dbm2rxlev(int dbm) +{ + int rxlev = dbm + 110; + + if (rxlev > 63) + rxlev = 63; + else if (rxlev < 0) + rxlev = 0; + + return rxlev; +} + +const char *gsm_band_name(enum gsm_band band) +{ + switch (band) { + case GSM_BAND_450: + return "GSM450"; + case GSM_BAND_480: + return "GSM480"; + case GSM_BAND_750: + return "GSM750"; + case GSM_BAND_810: + return "GSM810"; + case GSM_BAND_850: + return "GSM850"; + case GSM_BAND_900: + return "GSM900"; + case GSM_BAND_1800: + return "DCS1800"; + case GSM_BAND_1900: + return "PCS1900"; + } + return "invalid"; +} + +enum gsm_band gsm_band_parse(const char* mhz) +{ + while (*mhz && !isdigit(*mhz)) + mhz++; + + if (*mhz == '\0') + return -EINVAL; + + switch (strtol(mhz, NULL, 10)) { + case 450: + return GSM_BAND_450; + case 480: + return GSM_BAND_480; + case 750: + return GSM_BAND_750; + case 810: + return GSM_BAND_810; + case 850: + return GSM_BAND_850; + case 900: + return GSM_BAND_900; + case 1800: + return GSM_BAND_1800; + case 1900: + return GSM_BAND_1900; + default: + return -EINVAL; + } +} + +enum gsm_band gsm_arfcn2band(uint16_t arfcn) +{ + int is_pcs = arfcn & ARFCN_PCS; + + arfcn &= ~ARFCN_FLAG_MASK; + + if (is_pcs) + return GSM_BAND_1900; + else if (arfcn <= 124) + return GSM_BAND_900; + else if (arfcn >= 955 && arfcn <= 1023) + return GSM_BAND_900; + else if (arfcn >= 128 && arfcn <= 251) + return GSM_BAND_850; + else if (arfcn >= 512 && arfcn <= 885) + return GSM_BAND_1800; + else if (arfcn >= 259 && arfcn <= 293) + return GSM_BAND_450; + else if (arfcn >= 306 && arfcn <= 340) + return GSM_BAND_480; + else if (arfcn >= 350 && arfcn <= 425) + return GSM_BAND_810; + else if (arfcn >= 438 && arfcn <= 511) + return GSM_BAND_750; + else + return GSM_BAND_1800; +} + +/* Convert an ARFCN to the frequency in MHz * 10 */ +uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink) +{ + uint16_t freq10_ul; + uint16_t freq10_dl; + int is_pcs = arfcn & ARFCN_PCS; + + arfcn &= ~ARFCN_FLAG_MASK; + + if (is_pcs) { + /* DCS 1900 */ + arfcn &= ~ARFCN_PCS; + freq10_ul = 18502 + 2 * (arfcn-512); + freq10_dl = freq10_ul + 800; + } else if (arfcn <= 124) { + /* Primary GSM + ARFCN 0 of E-GSM */ + freq10_ul = 8900 + 2 * arfcn; + freq10_dl = freq10_ul + 450; + } else if (arfcn >= 955 && arfcn <= 1023) { + /* E-GSM and R-GSM */ + freq10_ul = 8900 + 2 * (arfcn - 1024); + freq10_dl = freq10_ul + 450; + } else if (arfcn >= 128 && arfcn <= 251) { + /* GSM 850 */ + freq10_ul = 8242 + 2 * (arfcn - 128); + freq10_dl = freq10_ul + 450; + } else if (arfcn >= 512 && arfcn <= 885) { + /* DCS 1800 */ + freq10_ul = 17102 + 2 * (arfcn - 512); + freq10_dl = freq10_ul + 950; + } else if (arfcn >= 259 && arfcn <= 293) { + /* GSM 450 */ + freq10_ul = 4506 + 2 * (arfcn - 259); + freq10_dl = freq10_ul + 100; + } else if (arfcn >= 306 && arfcn <= 340) { + /* GSM 480 */ + freq10_ul = 4790 + 2 * (arfcn - 306); + freq10_dl = freq10_ul + 100; + } else if (arfcn >= 350 && arfcn <= 425) { + /* GSM 810 */ + freq10_ul = 8060 + 2 * (arfcn - 350); + freq10_dl = freq10_ul + 450; + } else if (arfcn >= 438 && arfcn <= 511) { + /* GSM 750 */ + freq10_ul = 7472 + 2 * (arfcn - 438); + freq10_dl = freq10_ul + 300; + } else + return 0xffff; + + if (uplink) + return freq10_ul; + else + return freq10_dl; +} + +void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn) +{ + time->fn = fn; + time->t1 = time->fn / (26*51); + time->t2 = time->fn % 26; + time->t3 = time->fn % 51; + time->tc = (time->fn / 51) % 8; +} + +uint32_t gsm_gsmtime2fn(struct gsm_time *time) +{ + /* TS 05.02 Chapter 4.3.3 TDMA frame number */ + return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1)); +} + +/* TS 03.03 Chapter 2.6 */ +int gprs_tlli_type(uint32_t tlli) +{ + if ((tlli & 0xc0000000) == 0xc0000000) + return TLLI_LOCAL; + else if ((tlli & 0xc0000000) == 0x80000000) + return TLLI_FOREIGN; + else if ((tlli & 0xf8000000) == 0x78000000) + return TLLI_RANDOM; + else if ((tlli & 0xf8000000) == 0x70000000) + return TLLI_AUXILIARY; + + return TLLI_RESERVED; +} + +uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type) +{ + uint32_t tlli; + switch (type) { + case TLLI_LOCAL: + tlli = p_tmsi | 0xc0000000; + break; + case TLLI_FOREIGN: + tlli = (p_tmsi & 0x3fffffff) | 0x80000000; + break; + default: + tlli = 0; + break; + } + return tlli; +} diff --git a/src/gsm/rsl.c b/src/gsm/rsl.c new file mode 100644 index 00000000..3bfeffb9 --- /dev/null +++ b/src/gsm/rsl.c @@ -0,0 +1,371 @@ +/* GSM Radio Signalling Link messages on the A-bis interface + * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */ + +/* (C) 2008-2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include + +#include +#include + +#define RSL_ALLOC_SIZE 200 +#define RSL_ALLOC_HEADROOM 56 + +void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type) +{ + dh->c.msg_discr = ABIS_RSL_MDISC_RLL; + dh->c.msg_type = msg_type; + dh->ie_chan = RSL_IE_CHAN_NR; + dh->ie_link_id = RSL_IE_LINK_IDENT; +} + +void rsl_init_cchan_hdr(struct abis_rsl_cchan_hdr *ch, uint8_t msg_type) +{ + ch->c.msg_discr = ABIS_RSL_MDISC_COM_CHAN; + ch->c.msg_type = msg_type; + ch->ie_chan = RSL_IE_CHAN_NR; +} + +const struct tlv_definition rsl_att_tlvdef = { + .def = { + [RSL_IE_CHAN_NR] = { TLV_TYPE_TV }, + [RSL_IE_LINK_IDENT] = { TLV_TYPE_TV }, + [RSL_IE_ACT_TYPE] = { TLV_TYPE_TV }, + [RSL_IE_BS_POWER] = { TLV_TYPE_TV }, + [RSL_IE_CHAN_IDENT] = { TLV_TYPE_TLV }, + [RSL_IE_CHAN_MODE] = { TLV_TYPE_TLV }, + [RSL_IE_ENCR_INFO] = { TLV_TYPE_TLV }, + [RSL_IE_FRAME_NUMBER] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_HANDO_REF] = { TLV_TYPE_TV }, + [RSL_IE_L1_INFO] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_L3_INFO] = { TLV_TYPE_TL16V }, + [RSL_IE_MS_IDENTITY] = { TLV_TYPE_TLV }, + [RSL_IE_MS_POWER] = { TLV_TYPE_TV }, + [RSL_IE_PAGING_GROUP] = { TLV_TYPE_TV }, + [RSL_IE_PAGING_LOAD] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_PYHS_CONTEXT] = { TLV_TYPE_TLV }, + [RSL_IE_ACCESS_DELAY] = { TLV_TYPE_TV }, + [RSL_IE_RACH_LOAD] = { TLV_TYPE_TLV }, + [RSL_IE_REQ_REFERENCE] = { TLV_TYPE_FIXED, 3 }, + [RSL_IE_RELEASE_MODE] = { TLV_TYPE_TV }, + [RSL_IE_RESOURCE_INFO] = { TLV_TYPE_TLV }, + [RSL_IE_RLM_CAUSE] = { TLV_TYPE_TLV }, + [RSL_IE_STARTNG_TIME] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_TIMING_ADVANCE] = { TLV_TYPE_TV }, + [RSL_IE_UPLINK_MEAS] = { TLV_TYPE_TLV }, + [RSL_IE_CAUSE] = { TLV_TYPE_TLV }, + [RSL_IE_MEAS_RES_NR] = { TLV_TYPE_TV }, + [RSL_IE_MSG_ID] = { TLV_TYPE_TV }, + [RSL_IE_SYSINFO_TYPE] = { TLV_TYPE_TV }, + [RSL_IE_MS_POWER_PARAM] = { TLV_TYPE_TLV }, + [RSL_IE_BS_POWER_PARAM] = { TLV_TYPE_TLV }, + [RSL_IE_PREPROC_PARAM] = { TLV_TYPE_TLV }, + [RSL_IE_PREPROC_MEAS] = { TLV_TYPE_TLV }, + [RSL_IE_IMM_ASS_INFO] = { TLV_TYPE_TLV }, + [RSL_IE_SMSCB_INFO] = { TLV_TYPE_FIXED, 23 }, + [RSL_IE_MS_TIMING_OFFSET] = { TLV_TYPE_TV }, + [RSL_IE_ERR_MSG] = { TLV_TYPE_TLV }, + [RSL_IE_FULL_BCCH_INFO] = { TLV_TYPE_TLV }, + [RSL_IE_CHAN_NEEDED] = { TLV_TYPE_TV }, + [RSL_IE_CB_CMD_TYPE] = { TLV_TYPE_TV }, + [RSL_IE_SMSCB_MSG] = { TLV_TYPE_TLV }, + [RSL_IE_FULL_IMM_ASS_INFO] = { TLV_TYPE_TLV }, + [RSL_IE_SACCH_INFO] = { TLV_TYPE_TLV }, + [RSL_IE_CBCH_LOAD_INFO] = { TLV_TYPE_TV }, + [RSL_IE_SMSCB_CHAN_INDICATOR] = { TLV_TYPE_TV }, + [RSL_IE_GROUP_CALL_REF] = { TLV_TYPE_TLV }, + [RSL_IE_CHAN_DESC] = { TLV_TYPE_TLV }, + [RSL_IE_NCH_DRX_INFO] = { TLV_TYPE_TLV }, + [RSL_IE_CMD_INDICATOR] = { TLV_TYPE_TLV }, + [RSL_IE_EMLPP_PRIO] = { TLV_TYPE_TV }, + [RSL_IE_UIC] = { TLV_TYPE_TLV }, + [RSL_IE_MAIN_CHAN_REF] = { TLV_TYPE_TV }, + [RSL_IE_MR_CONFIG] = { TLV_TYPE_TLV }, + [RSL_IE_MR_CONTROL] = { TLV_TYPE_TV }, + [RSL_IE_SUP_CODEC_TYPES] = { TLV_TYPE_TLV }, + [RSL_IE_CODEC_CONFIG] = { TLV_TYPE_TLV }, + [RSL_IE_RTD] = { TLV_TYPE_TV }, + [RSL_IE_TFO_STATUS] = { TLV_TYPE_TV }, + [RSL_IE_LLP_APDU] = { TLV_TYPE_TLV }, + [RSL_IE_SIEMENS_MRPCI] = { TLV_TYPE_TV }, + [RSL_IE_IPAC_PROXY_UDP] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_IPAC_BSCMPL_TOUT] = { TLV_TYPE_TV }, + [RSL_IE_IPAC_REMOTE_IP] = { TLV_TYPE_FIXED, 4 }, + [RSL_IE_IPAC_REMOTE_PORT] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_IPAC_RTP_PAYLOAD] = { TLV_TYPE_TV }, + [RSL_IE_IPAC_LOCAL_PORT] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_IPAC_SPEECH_MODE] = { TLV_TYPE_TV }, + [RSL_IE_IPAC_LOCAL_IP] = { TLV_TYPE_FIXED, 4 }, + [RSL_IE_IPAC_CONN_ID] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_IPAC_RTP_CSD_FMT] = { TLV_TYPE_TV }, + [RSL_IE_IPAC_RTP_JIT_BUF] = { TLV_TYPE_FIXED, 2 }, + [RSL_IE_IPAC_RTP_COMPR] = { TLV_TYPE_TV }, + [RSL_IE_IPAC_RTP_PAYLOAD2] = { TLV_TYPE_TV }, + [RSL_IE_IPAC_RTP_MPLEX] = { TLV_TYPE_FIXED, 8 }, + [RSL_IE_IPAC_RTP_MPLEX_ID] = { TLV_TYPE_TV }, + }, +}; + +/* encode channel number as per Section 9.3.1 */ +uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot) +{ + uint8_t ret; + + ret = (timeslot & 0x07) | type; + + switch (type) { + case RSL_CHAN_Lm_ACCHs: + subch &= 0x01; + break; + case RSL_CHAN_SDCCH4_ACCH: + subch &= 0x03; + break; + case RSL_CHAN_SDCCH8_ACCH: + subch &= 0x07; + break; + default: + /* no subchannels allowed */ + subch = 0x00; + break; + } + ret |= (subch << 3); + + return ret; +} + +int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot) +{ + *timeslot = chan_nr & 0x7; + + if ((chan_nr & 0xf8) == RSL_CHAN_Bm_ACCHs) { + *type = RSL_CHAN_Bm_ACCHs; + *subch = 0; + } else if ((chan_nr & 0xf0) == RSL_CHAN_Lm_ACCHs) { + *type = RSL_CHAN_Lm_ACCHs; + *subch = (chan_nr >> 3) & 0x1; + } else if ((chan_nr & 0xe0) == RSL_CHAN_SDCCH4_ACCH) { + *type = RSL_CHAN_SDCCH4_ACCH; + *subch = (chan_nr >> 3) & 0x3; + } else if ((chan_nr & 0xc0) == RSL_CHAN_SDCCH8_ACCH) { + *type = RSL_CHAN_SDCCH8_ACCH; + *subch = (chan_nr >> 3) & 0x7; + } else if ((chan_nr & 0xf8) == RSL_CHAN_BCCH) { + *type = RSL_CHAN_BCCH; + *subch = 0; + } else if ((chan_nr & 0xf8) == RSL_CHAN_RACH) { + *type = RSL_CHAN_RACH; + *subch = 0; + } else if ((chan_nr & 0xf8) == RSL_CHAN_PCH_AGCH) { + *type = RSL_CHAN_PCH_AGCH; + *subch = 0; + } else + return -EINVAL; + + return 0; +} + +const char *rsl_chan_nr_str(uint8_t chan_nr) +{ + static char str[20]; + int ts = chan_nr & 7; + uint8_t cbits = chan_nr >> 3; + + if (cbits == 0x01) + sprintf(str, "TCH/F on TS%d", ts); + else if ((cbits & 0x1e) == 0x02) + sprintf(str, "TCH/H(%u) on TS%d", cbits & 0x01, ts); + else if ((cbits & 0x1c) == 0x04) + sprintf(str, "SDCCH/4(%u) on TS%d", cbits & 0x03, ts); + else if ((cbits & 0x18) == 0x08) + sprintf(str, "SDCCH/8(%u) on TS%d", cbits & 0x07, ts); + else if (cbits == 0x10) + sprintf(str, "BCCH on TS%d", ts); + else if (cbits == 0x11) + sprintf(str, "RACH on TS%d", ts); + else if (cbits == 0x12) + sprintf(str, "PCH/AGCH on TS%d", ts); + else + sprintf(str, "UNKNOWN on TS%d", ts); + + return str; +} + +static const struct value_string rsl_err_vals[] = { + { RSL_ERR_RADIO_IF_FAIL, "Radio Interface Failure" }, + { RSL_ERR_RADIO_LINK_FAIL, "Radio Link Failure" }, + { RSL_ERR_HANDOVER_ACC_FAIL, "Handover Access Failure" }, + { RSL_ERR_TALKER_ACC_FAIL, "Talker Access Failure" }, + { RSL_ERR_OM_INTERVENTION, "O&M Intervention" }, + { RSL_ERR_NORMAL_UNSPEC, "Normal event, unspecified" }, + { RSL_ERR_T_MSRFPCI_EXP, "Siemens: T_MSRFPCI Expired" }, + { RSL_ERR_EQUIPMENT_FAIL, "Equipment Failure" }, + { RSL_ERR_RR_UNAVAIL, "Radio Resource not available" }, + { RSL_ERR_TERR_CH_FAIL, "Terrestrial Channel Failure" }, + { RSL_ERR_CCCH_OVERLOAD, "CCCH Overload" }, + { RSL_ERR_ACCH_OVERLOAD, "ACCH Overload" }, + { RSL_ERR_PROCESSOR_OVERLOAD, "Processor Overload" }, + { RSL_ERR_RES_UNAVAIL, "Resource not available, unspecified" }, + { RSL_ERR_TRANSC_UNAVAIL, "Transcoding not available" }, + { RSL_ERR_SERV_OPT_UNAVAIL, "Service or Option not available" }, + { RSL_ERR_ENCR_UNIMPL, "Encryption algorithm not implemented" }, + { RSL_ERR_SERV_OPT_UNIMPL, "Service or Option not implemented" }, + { RSL_ERR_RCH_ALR_ACTV_ALLOC, "Radio channel already activated" }, + { RSL_ERR_INVALID_MESSAGE, "Invalid Message, unspecified" }, + { RSL_ERR_MSG_DISCR, "Message Discriminator Error" }, + { RSL_ERR_MSG_TYPE, "Message Type Error" }, + { RSL_ERR_MSG_SEQ, "Message Sequence Error" }, + { RSL_ERR_IE_ERROR, "General IE error" }, + { RSL_ERR_MAND_IE_ERROR, "Mandatory IE error" }, + { RSL_ERR_OPT_IE_ERROR, "Optional IE error" }, + { RSL_ERR_IE_NONEXIST, "IE non-existent" }, + { RSL_ERR_IE_LENGTH, "IE length error" }, + { RSL_ERR_IE_CONTENT, "IE content error" }, + { RSL_ERR_PROTO, "Protocol error, unspecified" }, + { RSL_ERR_INTERWORKING, "Interworking error, unspecified" }, + { 0, NULL } +}; + +const char *rsl_err_name(uint8_t err) +{ + return get_value_string(rsl_err_vals, err); +} + +static const struct value_string rsl_rlm_cause_strs[] = { + { RLL_CAUSE_T200_EXPIRED, "Timer T200 expired (N200+1) times" }, + { RLL_CAUSE_REEST_REQ, "Re-establishment request" }, + { RLL_CAUSE_UNSOL_UA_RESP, "Unsolicited UA response" }, + { RLL_CAUSE_UNSOL_DM_RESP, "Unsolicited DM response" }, + { RLL_CAUSE_UNSOL_DM_RESP_MF, "Unsolicited DM response, multiple frame" }, + { RLL_CAUSE_UNSOL_SPRV_RESP, "Unsolicited supervisory response" }, + { RLL_CAUSE_SEQ_ERR, "Sequence Error" }, + { RLL_CAUSE_UFRM_INC_PARAM, "U-Frame with incorrect parameters" }, + { RLL_CAUSE_SFRM_INC_PARAM, "S-Frame with incorrect parameters" }, + { RLL_CAUSE_IFRM_INC_MBITS, "I-Frame with incorrect use of M bit" }, + { RLL_CAUSE_IFRM_INC_LEN, "I-Frame with incorrect length" }, + { RLL_CAUSE_FRM_UNIMPL, "Fraeme not implemented" }, + { RLL_CAUSE_SABM_MF, "SABM command, multiple frame established state" }, + { RLL_CAUSE_SABM_INFO_NOTALL, "SABM frame with information not allowed in this state" }, + { 0, NULL }, +}; + +const char *rsl_rlm_cause_name(uint8_t err) +{ + return get_value_string(rsl_rlm_cause_strs, err); +} + +/* Section 3.3.2.3 TS 05.02. I think this looks like a table */ +int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf) +{ + switch (ccch_conf) { + case RSL_BCCH_CCCH_CONF_1_NC: + return 1; + case RSL_BCCH_CCCH_CONF_1_C: + return 1; + case RSL_BCCH_CCCH_CONF_2_NC: + return 2; + case RSL_BCCH_CCCH_CONF_3_NC: + return 3; + case RSL_BCCH_CCCH_CONF_4_NC: + return 4; + default: + return -1; + } +} + +/* Section 3.3.2.3 TS 05.02 */ +int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf) +{ + switch (ccch_conf) { + case RSL_BCCH_CCCH_CONF_1_NC: + return 0; + case RSL_BCCH_CCCH_CONF_1_C: + return 1; + case RSL_BCCH_CCCH_CONF_2_NC: + return 0; + case RSL_BCCH_CCCH_CONF_3_NC: + return 0; + case RSL_BCCH_CCCH_CONF_4_NC: + return 0; + default: + return -1; + } +} + +/* Push a RSL RLL header */ +void rsl_rll_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr, + uint8_t link_id, int transparent) +{ + struct abis_rsl_rll_hdr *rh; + + rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh)); + rsl_init_rll_hdr(rh, msg_type); + if (transparent) + rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP; + rh->chan_nr = chan_nr; + rh->link_id = link_id; + + /* set the l2 header pointer */ + msg->l2h = (uint8_t *)rh; +} + +/* Push a RSL RLL header with L3_INFO IE */ +void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr, + uint8_t link_id, int transparent) +{ + uint8_t l3_len = msg->tail - (uint8_t *)msgb_l3(msg); + + /* construct a RSLms RLL message (DATA INDICATION, UNIT DATA + * INDICATION) and send it off via RSLms */ + + /* Push the L3 IE tag and lengh */ + msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len); + + /* Then push the RSL header */ + rsl_rll_push_hdr(msg, msg_type, chan_nr, link_id, transparent); +} + +struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr, + uint8_t link_id, int transparent) +{ + struct abis_rsl_rll_hdr *rh; + struct msgb *msg; + + msg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM, + RSL_ALLOC_HEADROOM, "rsl_rll_simple"); + + if (!msg) + return NULL; + + /* put the RSL header */ + rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh)); + rsl_init_rll_hdr(rh, msg_type); + if (transparent) + rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP; + rh->chan_nr = chan_nr; + rh->link_id = link_id; + + /* set the l2 header pointer */ + msg->l2h = (uint8_t *)rh; + + return msg; +} diff --git a/src/gsm/rxlev_stat.c b/src/gsm/rxlev_stat.c new file mode 100644 index 00000000..b474aaa8 --- /dev/null +++ b/src/gsm/rxlev_stat.c @@ -0,0 +1,94 @@ +/* Rx Level statistics */ + +/* (C) 2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val) +{ + unsigned int i; + + for (i = n; i < bv->data_len*8; i++) { + if (bitvec_get_bit_pos(bv, i) == val) + return i; + } + + return -1; +} + +void rxlev_stat_input(struct rxlev_stats *st, uint16_t arfcn, uint8_t rxlev) +{ + struct bitvec bv; + + if (rxlev >= NUM_RXLEVS) + rxlev = NUM_RXLEVS-1; + + bv.data_len = NUM_ARFCNS/8; + bv.data = st->rxlev_buckets[rxlev]; + + bitvec_set_bit_pos(&bv, arfcn, ONE); +} + +/* get the next ARFCN that has the specified Rxlev */ +int16_t rxlev_stat_get_next(const struct rxlev_stats *st, uint8_t rxlev, int16_t arfcn) +{ + struct bitvec bv; + + if (rxlev >= NUM_RXLEVS) + rxlev = NUM_RXLEVS-1; + + bv.data_len = NUM_ARFCNS/8; + + if (arfcn < 0) + arfcn = -1; + + bv.data = (uint8_t *) st->rxlev_buckets[rxlev]; + + return bitvec_find_bit_pos(&bv, arfcn+1, ONE); +} + +void rxlev_stat_reset(struct rxlev_stats *st) +{ + memset(st, 0, sizeof(*st)); +} + +void rxlev_stat_dump(const struct rxlev_stats *st) +{ + int i; + + for (i = NUM_RXLEVS-1; i >= 0; i--) { + int16_t arfcn = -1; + + printf("ARFCN with RxLev %u: ", i); + while ((arfcn = rxlev_stat_get_next(st, i, arfcn)) >= 0) { + printf("%u ", arfcn); + } + printf("\n"); + } +} diff --git a/src/gsm/tlv_parser.c b/src/gsm/tlv_parser.c new file mode 100644 index 00000000..bbef7a9a --- /dev/null +++ b/src/gsm/tlv_parser.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include + +struct tlv_definition tvlv_att_def; + +int tlv_dump(struct tlv_parsed *dec) +{ + int i; + + for (i = 0; i <= 0xff; i++) { + if (!dec->lv[i].val) + continue; + printf("T=%02x L=%d\n", i, dec->lv[i].len); + } + return 0; +} + +/* o_tag: output: tag found + * o_len: output: length of the data + * o_val: output: pointer to the data + * def: input: a structure defining the valid TLV tags / configurations + * buf: input: the input data buffer to be parsed + * buf_len: input: the length of the input data buffer + * + * Also, returns the number of bytes consumed by the TLV entry + */ +int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val, + const struct tlv_definition *def, + const uint8_t *buf, int buf_len) +{ + uint8_t tag; + int len; + + tag = *buf; + *o_tag = tag; + + /* single octet TV IE */ + if (def->def[tag & 0xf0].type == TLV_TYPE_SINGLE_TV) { + *o_tag = tag & 0xf0; + *o_val = buf; + *o_len = 1; + return 1; + } + + /* FIXME: use tables for knwon IEI */ + switch (def->def[tag].type) { + case TLV_TYPE_T: + /* GSM TS 04.07 11.2.4: Type 1 TV or Type 2 T */ + *o_val = buf; + *o_len = 0; + len = 1; + break; + case TLV_TYPE_TV: + *o_val = buf+1; + *o_len = 1; + len = 2; + break; + case TLV_TYPE_FIXED: + *o_val = buf+1; + *o_len = def->def[tag].fixed_len; + len = def->def[tag].fixed_len + 1; + break; + case TLV_TYPE_TLV: + /* GSM TS 04.07 11.2.4: Type 4 TLV */ + if (buf + 1 > buf + buf_len) + return -1; + *o_val = buf+2; + *o_len = *(buf+1); + len = *o_len + 2; + if (len > buf_len) + return -2; + break; + case TLV_TYPE_TvLV: + if (*(buf+1) & 0x80) { + /* like TLV, but without highest bit of len */ + if (buf + 1 > buf + buf_len) + return -1; + *o_val = buf+2; + *o_len = *(buf+1) & 0x7f; + len = *o_len + 2; + if (len > buf_len) + return -2; + break; + } + /* like TL16V, fallthrough */ + case TLV_TYPE_TL16V: + if (2 > buf_len) + return -1; + *o_val = buf+3; + *o_len = *(buf+1) << 8 | *(buf+2); + len = *o_len + 3; + if (len > buf_len) + return -2; + break; + default: + return -3; + } + + return len; +} + +/* dec: output: a caller-allocated pointer to a struct tlv_parsed, + * def: input: a structure defining the valid TLV tags / configurations + * buf: input: the input data buffer to be parsed + * buf_len: input: the length of the input data buffer + * lv_tag: input: an initial LV tag at the start of the buffer + * lv_tag2: input: a second initial LV tag following lv_tag + */ +int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def, + const uint8_t *buf, int buf_len, uint8_t lv_tag, + uint8_t lv_tag2) +{ + int ofs = 0, num_parsed = 0; + uint16_t len; + + memset(dec, 0, sizeof(*dec)); + + if (lv_tag) { + if (ofs > buf_len) + return -1; + dec->lv[lv_tag].val = &buf[ofs+1]; + dec->lv[lv_tag].len = buf[ofs]; + len = dec->lv[lv_tag].len + 1; + if (ofs + len > buf_len) + return -2; + num_parsed++; + ofs += len; + } + if (lv_tag2) { + if (ofs > buf_len) + return -1; + dec->lv[lv_tag2].val = &buf[ofs+1]; + dec->lv[lv_tag2].len = buf[ofs]; + len = dec->lv[lv_tag2].len + 1; + if (ofs + len > buf_len) + return -2; + num_parsed++; + ofs += len; + } + + while (ofs < buf_len) { + int rv; + uint8_t tag; + const uint8_t *val; + + rv = tlv_parse_one(&tag, &len, &val, def, + &buf[ofs], buf_len-ofs); + if (rv < 0) + return rv; + dec->lv[tag].val = val; + dec->lv[tag].len = len; + ofs += rv; + num_parsed++; + } + //tlv_dump(dec); + return num_parsed; +} + +/* take a master (src) tlvdev and fill up all empty slots in 'dst' */ +void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dst->def); i++) { + if (src->def[i].type == TLV_TYPE_NONE) + continue; + if (dst->def[i].type == TLV_TYPE_NONE) + dst->def[i] = src->def[i]; + } +} + +static __attribute__((constructor)) void on_dso_load_tlv(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(tvlv_att_def.def); i++) + tvlv_att_def.def[i].type = TLV_TYPE_TvLV; +} diff --git a/src/gsm0480.c b/src/gsm0480.c deleted file mode 100644 index b6b345cb..00000000 --- a/src/gsm0480.c +++ /dev/null @@ -1,461 +0,0 @@ -/* Format functions for GSM 04.80 */ - -/* - * (C) 2010 by Holger Hans Peter Freyther - * (C) 2009 by Mike Haben - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include - -#include - -#include -#include - -#include - -static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag) -{ - uint8_t *data = msgb_push(msgb, 2); - - data[0] = tag; - data[1] = msgb->len - 2; - return data; -} - -static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag, - uint8_t value) -{ - uint8_t *data = msgb_push(msgb, 3); - - data[0] = tag; - data[1] = 1; - data[2] = value; - return data; -} - -/* wrap an invoke around it... the other way around - * - * 1.) Invoke Component tag - * 2.) Invoke ID Tag - * 3.) Operation - * 4.) Data - */ -int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id) -{ - /* 3. operation */ - msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, op); - - /* 2. invoke id tag */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, link_id); - - /* 1. component tag */ - msgb_wrap_with_TL(msg, GSM0480_CTYPE_INVOKE); - - return 0; -} - -/* wrap the GSM 04.08 Facility IE around it */ -int gsm0480_wrap_facility(struct msgb *msg) -{ - msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); - - return 0; -} - -struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text) -{ - struct msgb *msg; - uint8_t *seq_len_ptr, *ussd_len_ptr, *data; - int len; - - msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); - if (!msg) - return NULL; - - /* SEQUENCE { */ - msgb_put_u8(msg, GSM_0480_SEQUENCE_TAG); - seq_len_ptr = msgb_put(msg, 1); - - /* DCS { */ - msgb_put_u8(msg, ASN1_OCTET_STRING_TAG); - msgb_put_u8(msg, 1); - msgb_put_u8(msg, 0x0F); - /* } DCS */ - - /* USSD-String { */ - msgb_put_u8(msg, ASN1_OCTET_STRING_TAG); - ussd_len_ptr = msgb_put(msg, 1); - data = msgb_put(msg, 0); - len = gsm_7bit_encode(data, text); - msgb_put(msg, len); - ussd_len_ptr[0] = len; - /* USSD-String } */ - - /* alertingPattern { */ - msgb_put_u8(msg, ASN1_OCTET_STRING_TAG); - msgb_put_u8(msg, 1); - msgb_put_u8(msg, alertPattern); - /* } alertingPattern */ - - seq_len_ptr[0] = 3 + 2 + ussd_len_ptr[0] + 3; - /* } SEQUENCE */ - - return msg; -} - -struct msgb *gsm0480_create_notifySS(const char *text) -{ - struct msgb *msg; - uint8_t *data, *tmp_len; - uint8_t *seq_len_ptr, *cal_len_ptr, *opt_len_ptr, *nam_len_ptr; - int len; - - len = strlen(text); - if (len < 1 || len > 160) - return NULL; - - msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); - if (!msg) - return NULL; - - msgb_put_u8(msg, GSM_0480_SEQUENCE_TAG); - seq_len_ptr = msgb_put(msg, 1); - - /* ss_code for CNAP { */ - msgb_put_u8(msg, 0x81); - msgb_put_u8(msg, 1); - msgb_put_u8(msg, 0x19); - /* } ss_code */ - - - /* nameIndicator { */ - msgb_put_u8(msg, 0xB4); - nam_len_ptr = msgb_put(msg, 1); - - /* callingName { */ - msgb_put_u8(msg, 0xA0); - opt_len_ptr = msgb_put(msg, 1); - msgb_put_u8(msg, 0xA0); - cal_len_ptr = msgb_put(msg, 1); - - /* namePresentationAllowed { */ - /* add the DCS value */ - msgb_put_u8(msg, 0x80); - msgb_put_u8(msg, 1); - msgb_put_u8(msg, 0x0F); - - /* add the lengthInCharacters */ - msgb_put_u8(msg, 0x81); - msgb_put_u8(msg, 1); - msgb_put_u8(msg, strlen(text)); - - /* add the actual string */ - msgb_put_u8(msg, 0x82); - tmp_len = msgb_put(msg, 1); - data = msgb_put(msg, 0); - len = gsm_7bit_encode(data, text); - tmp_len[0] = len; - msgb_put(msg, len); - - /* }; namePresentationAllowed */ - - cal_len_ptr[0] = 3 + 3 + 2 + len; - opt_len_ptr[0] = cal_len_ptr[0] + 2; - /* }; callingName */ - - nam_len_ptr[0] = opt_len_ptr[0] + 2; - /* ); nameIndicator */ - - /* write the lengths... */ - seq_len_ptr[0] = 3 + nam_len_ptr[0] + 2; - - return msg; -} - -/* Forward declarations */ -static int parse_ussd(const struct gsm48_hdr *hdr, - uint16_t len, struct ussd_request *req); -static int parse_ussd_info_elements(const uint8_t *ussd_ie, uint16_t len, - struct ussd_request *req); -static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, - struct ussd_request *req); -static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, - struct ussd_request *req); -static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length, - struct ussd_request *req); - -/* Decode a mobile-originated USSD-request message */ -int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len, - struct ussd_request *req) -{ - int rc = 0; - - if (len < sizeof(*hdr) + 2) { - LOGP(0, LOGL_DEBUG, "USSD Request is too short.\n"); - return 0; - } - - if ((hdr->proto_discr & 0x0f) == GSM48_PDISC_NC_SS) { - req->transaction_id = hdr->proto_discr & 0x70; - rc = parse_ussd(hdr, len, req); - } - - if (!rc) - LOGP(0, LOGL_DEBUG, "Error occurred while parsing received USSD!\n"); - - return rc; -} - -static int parse_ussd(const struct gsm48_hdr *hdr, uint16_t len, struct ussd_request *req) -{ - int rc = 1; - uint8_t msg_type = hdr->msg_type & 0xBF; /* message-type - section 3.4 */ - - switch (msg_type) { - case GSM0480_MTYPE_RELEASE_COMPLETE: - LOGP(0, LOGL_DEBUG, "USS Release Complete\n"); - /* could also parse out the optional Cause/Facility data */ - req->text[0] = 0xFF; - break; - case GSM0480_MTYPE_REGISTER: - case GSM0480_MTYPE_FACILITY: - rc &= parse_ussd_info_elements(&hdr->data[0], len - sizeof(*hdr), req); - break; - default: - LOGP(0, LOGL_DEBUG, "Unknown GSM 04.80 message-type field 0x%02x\n", - hdr->msg_type); - rc = 0; - break; - } - - return rc; -} - -static int parse_ussd_info_elements(const uint8_t *ussd_ie, uint16_t len, - struct ussd_request *req) -{ - int rc = -1; - /* Information Element Identifier - table 3.2 & GSM 04.08 section 10.5 */ - uint8_t iei; - uint8_t iei_length; - - iei = ussd_ie[0]; - iei_length = ussd_ie[1]; - - /* If the data does not fit, report an error */ - if (len - 2 < iei_length) - return 0; - - switch (iei) { - case GSM48_IE_CAUSE: - break; - case GSM0480_IE_FACILITY: - rc = parse_facility_ie(ussd_ie+2, iei_length, req); - break; - case GSM0480_IE_SS_VERSION: - break; - default: - LOGP(0, LOGL_DEBUG, "Unhandled GSM 04.08 or 04.80 IEI 0x%02x\n", - iei); - rc = 0; - break; - } - - return rc; -} - -static int parse_facility_ie(const uint8_t *facility_ie, uint16_t length, - struct ussd_request *req) -{ - int rc = 1; - uint8_t offset = 0; - - while (offset + 2 <= length) { - /* Component Type tag - table 3.7 */ - uint8_t component_type = facility_ie[offset]; - uint8_t component_length = facility_ie[offset+1]; - - /* size check */ - if (offset + 2 + component_length > length) { - LOGP(0, LOGL_ERROR, "Component does not fit.\n"); - return 0; - } - - switch (component_type) { - case GSM0480_CTYPE_INVOKE: - rc &= parse_ss_invoke(facility_ie+2, - component_length, - req); - break; - case GSM0480_CTYPE_RETURN_RESULT: - break; - case GSM0480_CTYPE_RETURN_ERROR: - break; - case GSM0480_CTYPE_REJECT: - break; - default: - LOGP(0, LOGL_DEBUG, "Unknown GSM 04.80 Facility " - "Component Type 0x%02x\n", component_type); - rc = 0; - break; - } - offset += (component_length+2); - }; - - return rc; -} - -/* Parse an Invoke component - see table 3.3 */ -static int parse_ss_invoke(const uint8_t *invoke_data, uint16_t length, - struct ussd_request *req) -{ - int rc = 1; - uint8_t offset; - - if (length < 3) - return 0; - - /* mandatory part */ - if (invoke_data[0] != GSM0480_COMPIDTAG_INVOKE_ID) { - LOGP(0, LOGL_DEBUG, "Unexpected GSM 04.80 Component-ID tag " - "0x%02x (expecting Invoke ID tag)\n", invoke_data[0]); - } - - offset = invoke_data[1] + 2; - req->invoke_id = invoke_data[2]; - - /* look ahead once */ - if (offset + 1 > length) - return 0; - - /* optional part */ - if (invoke_data[offset] == GSM0480_COMPIDTAG_LINKED_ID) - offset += invoke_data[offset+1] + 2; /* skip over it */ - - /* mandatory part */ - if (invoke_data[offset] == GSM0480_OPERATION_CODE) { - if (offset + 2 > length) - return 0; - uint8_t operation_code = invoke_data[offset+2]; - switch (operation_code) { - case GSM0480_OP_CODE_PROCESS_USS_REQ: - rc = parse_process_uss_req(invoke_data + offset + 3, - length - offset - 3, - req); - break; - default: - LOGP(0, LOGL_DEBUG, "GSM 04.80 operation code 0x%02x " - "is not yet handled\n", operation_code); - rc = 0; - break; - } - } else { - LOGP(0, LOGL_DEBUG, "Unexpected GSM 04.80 Component-ID tag 0x%02x " - "(expecting Operation Code tag)\n", - invoke_data[0]); - rc = 0; - } - - return rc; -} - -/* Parse the parameters of a Process UnstructuredSS Request */ -static int parse_process_uss_req(const uint8_t *uss_req_data, uint16_t length, - struct ussd_request *req) -{ - int rc = 0; - int num_chars; - uint8_t dcs; - - - /* we need at least that much */ - if (length < 8) - return 0; - - - if (uss_req_data[0] == GSM_0480_SEQUENCE_TAG) { - if (uss_req_data[2] == ASN1_OCTET_STRING_TAG) { - dcs = uss_req_data[4]; - if ((dcs == 0x0F) && - (uss_req_data[5] == ASN1_OCTET_STRING_TAG)) { - num_chars = (uss_req_data[6] * 8) / 7; - /* Prevent a mobile-originated buffer-overrun! */ - if (num_chars > MAX_LEN_USSD_STRING) - num_chars = MAX_LEN_USSD_STRING; - gsm_7bit_decode(req->text, - &(uss_req_data[7]), num_chars); - rc = 1; - } - } - } - return rc; -} - -struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text) -{ - struct msgb *msg; - struct gsm48_hdr *gh; - uint8_t *ptr8; - int response_len; - - msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); - if (!msg) - return NULL; - - /* First put the payload text into the message */ - ptr8 = msgb_put(msg, 0); - response_len = gsm_7bit_encode(ptr8, text); - msgb_put(msg, response_len); - - /* Then wrap it as an Octet String */ - msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG); - - /* Pre-pend the DCS octet string */ - msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F); - - /* Then wrap these as a Sequence */ - msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); - - /* Pre-pend the operation code */ - msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, - GSM0480_OP_CODE_PROCESS_USS_REQ); - - /* Wrap the operation code and IA5 string as a sequence */ - msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); - - /* Pre-pend the invoke ID */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); - - /* Wrap this up as a Return Result component */ - msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT); - - /* Wrap the component in a Facility message */ - msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); - - /* And finally pre-pend the L3 header */ - gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); - gh->proto_discr = GSM48_PDISC_NC_SS | trans_id - | (1<<7); /* TI direction = 1 */ - gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE; - - return msg; -} diff --git a/src/gsm0808.c b/src/gsm0808.c deleted file mode 100644 index dc450cc4..00000000 --- a/src/gsm0808.c +++ /dev/null @@ -1,369 +0,0 @@ -/* (C) 2009,2010 by Holger Hans Peter Freyther - * (C) 2009,2010 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include - -#include - -#define BSSMAP_MSG_SIZE 512 -#define BSSMAP_MSG_HEADROOM 128 - -static void put_data_16(uint8_t *data, const uint16_t val) -{ - memcpy(data, &val, sizeof(val)); -} - -struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, uint16_t _ci) -{ - uint8_t *data; - uint8_t *ci; - struct msgb* msg; - struct gsm48_loc_area_id *lai; - - msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap cmpl l3"); - if (!msg) - return NULL; - - /* create the bssmap header */ - msg->l3h = msgb_put(msg, 2); - msg->l3h[0] = 0x0; - - /* create layer 3 header */ - data = msgb_put(msg, 1); - data[0] = BSS_MAP_MSG_COMPLETE_LAYER_3; - - /* create the cell header */ - data = msgb_put(msg, 3); - data[0] = GSM0808_IE_CELL_IDENTIFIER; - data[1] = 1 + sizeof(*lai) + 2; - data[2] = CELL_IDENT_WHOLE_GLOBAL; - - lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai)); - gsm48_generate_lai(lai, cc, nc, lac); - - ci = msgb_put(msg, 2); - put_data_16(ci, htons(_ci)); - - /* copy the layer3 data */ - data = msgb_put(msg, msgb_l3len(msg_l3) + 2); - data[0] = GSM0808_IE_LAYER_3_INFORMATION; - data[1] = msgb_l3len(msg_l3); - memcpy(&data[2], msg_l3->l3h, data[1]); - - /* update the size */ - msg->l3h[1] = msgb_l3len(msg) - 2; - - return msg; -} - -struct msgb *gsm0808_create_reset(void) -{ - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap: reset"); - if (!msg) - return NULL; - - msg->l3h = msgb_put(msg, 6); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 0x04; - msg->l3h[2] = 0x30; - msg->l3h[3] = 0x04; - msg->l3h[4] = 0x01; - msg->l3h[5] = 0x20; - return msg; -} - -struct msgb *gsm0808_create_clear_complete(void) -{ - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap: clear complete"); - if (!msg) - return NULL; - - msg->l3h = msgb_put(msg, 3); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 1; - msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE; - - return msg; -} - -struct msgb *gsm0808_create_clear_command(uint8_t reason) -{ - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap: clear command"); - if (!msg) - return NULL; - - msg->l3h = msgb_tv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 4); - msgb_v_put(msg, BSS_MAP_MSG_CLEAR_CMD); - msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &reason); - return msg; -} - -struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id) -{ - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "cipher-complete"); - if (!msg) - return NULL; - - /* send response with BSS override for A5/1... cheating */ - msg->l3h = msgb_put(msg, 3); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 0xff; - msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_COMPLETE; - - /* include layer3 in case we have at least two octets */ - if (layer3 && msgb_l3len(layer3) > 2) { - msg->l4h = msgb_put(msg, msgb_l3len(layer3) + 2); - msg->l4h[0] = GSM0808_IE_LAYER_3_MESSAGE_CONTENTS; - msg->l4h[1] = msgb_l3len(layer3); - memcpy(&msg->l4h[2], layer3->l3h, msgb_l3len(layer3)); - } - - /* and the optional BSS message */ - msg->l4h = msgb_put(msg, 2); - msg->l4h[0] = GSM0808_IE_CHOSEN_ENCR_ALG; - msg->l4h[1] = alg_id; - - /* update the size */ - msg->l3h[1] = msgb_l3len(msg) - 2; - return msg; -} - -struct msgb *gsm0808_create_cipher_reject(uint8_t cause) -{ - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap: clear complete"); - if (!msg) - return NULL; - - msg->l3h = msgb_put(msg, 3); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 2; - msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_REJECT; - msg->l3h[3] = cause; - - return msg; -} - -struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark_data, uint8_t length) -{ - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "classmark-update"); - if (!msg) - return NULL; - - msg->l3h = msgb_put(msg, 3); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 0xff; - msg->l3h[2] = BSS_MAP_MSG_CLASSMARK_UPDATE; - - msg->l4h = msgb_put(msg, length); - memcpy(msg->l4h, classmark_data, length); - - /* update the size */ - msg->l3h[1] = msgb_l3len(msg) - 2; - return msg; -} - -struct msgb *gsm0808_create_sapi_reject(uint8_t link_id) -{ - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap: sapi 'n' reject"); - if (!msg) - return NULL; - - msg->l3h = msgb_put(msg, 5); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 3; - msg->l3h[2] = BSS_MAP_MSG_SAPI_N_REJECT; - msg->l3h[3] = link_id; - msg->l3h[4] = GSM0808_CAUSE_BSS_NOT_EQUIPPED; - - return msg; -} - -struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause, - uint8_t chosen_channel, uint8_t encr_alg_id, - uint8_t speech_mode) -{ - uint8_t *data; - - struct msgb *msg = msgb_alloc(35, "bssmap: ass compl"); - if (!msg) - return NULL; - - msg->l3h = msgb_put(msg, 3); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 0xff; - msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_COMPLETE; - - /* write 3.2.2.22 */ - data = msgb_put(msg, 2); - data[0] = GSM0808_IE_RR_CAUSE; - data[1] = rr_cause; - - /* write cirtcuit identity code 3.2.2.2 */ - /* write cell identifier 3.2.2.17 */ - /* write chosen channel 3.2.2.33 when BTS picked it */ - data = msgb_put(msg, 2); - data[0] = GSM0808_IE_CHOSEN_CHANNEL; - data[1] = chosen_channel; - - /* write chosen encryption algorithm 3.2.2.44 */ - data = msgb_put(msg, 2); - data[0] = GSM0808_IE_CHOSEN_ENCR_ALG; - data[1] = encr_alg_id; - - /* write circuit pool 3.2.2.45 */ - /* write speech version chosen: 3.2.2.51 when BTS picked it */ - if (speech_mode != 0) { - data = msgb_put(msg, 2); - data[0] = GSM0808_IE_SPEECH_VERSION; - data[1] = speech_mode; - } - - /* write LSA identifier 3.2.2.15 */ - - - /* update the size */ - msg->l3h[1] = msgb_l3len(msg) - 2; - return msg; -} - -struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause) -{ - uint8_t *data; - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap: ass fail"); - if (!msg) - return NULL; - - msg->l3h = msgb_put(msg, 6); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 0xff; - msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE; - msg->l3h[3] = GSM0808_IE_CAUSE; - msg->l3h[4] = 1; - msg->l3h[5] = cause; - - /* RR cause 3.2.2.22 */ - if (rr_cause) { - data = msgb_put(msg, 2); - data[0] = GSM0808_IE_RR_CAUSE; - data[1] = *rr_cause; - } - - /* Circuit pool 3.22.45 */ - /* Circuit pool list 3.2.2.46 */ - - /* update the size */ - msg->l3h[1] = msgb_l3len(msg) - 2; - return msg; -} - -struct msgb *gsm0808_create_clear_rqst(uint8_t cause) -{ - struct msgb *msg; - - msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap: clear rqst"); - if (!msg) - return NULL; - - msg->l3h = msgb_put(msg, 2 + 4); - msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT; - msg->l3h[1] = 4; - - msg->l3h[2] = BSS_MAP_MSG_CLEAR_RQST; - msg->l3h[3] = GSM0808_IE_CAUSE; - msg->l3h[4] = 1; - msg->l3h[5] = cause; - return msg; -} - -void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id) -{ - uint8_t *hh = msgb_push(msg, 3); - hh[0] = BSSAP_MSG_DTAP; - hh[1] = link_id; - hh[2] = msg->len - 3; -} - -struct msgb *gsm0808_create_dtap(struct msgb *msg_l3, uint8_t link_id) -{ - struct dtap_header *header; - uint8_t *data; - struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "dtap"); - if (!msg) - return NULL; - - /* DTAP header */ - msg->l3h = msgb_put(msg, sizeof(*header)); - header = (struct dtap_header *) &msg->l3h[0]; - header->type = BSSAP_MSG_DTAP; - header->link_id = link_id; - header->length = msgb_l3len(msg_l3); - - /* Payload */ - data = msgb_put(msg, header->length); - memcpy(data, msg_l3->l3h, header->length); - - return msg; -} - -static const struct tlv_definition bss_att_tlvdef = { - .def = { - [GSM0808_IE_IMSI] = { TLV_TYPE_TLV }, - [GSM0808_IE_TMSI] = { TLV_TYPE_TLV }, - [GSM0808_IE_CELL_IDENTIFIER_LIST] = { TLV_TYPE_TLV }, - [GSM0808_IE_CHANNEL_NEEDED] = { TLV_TYPE_TV }, - [GSM0808_IE_EMLPP_PRIORITY] = { TLV_TYPE_TV }, - [GSM0808_IE_CHANNEL_TYPE] = { TLV_TYPE_TLV }, - [GSM0808_IE_PRIORITY] = { TLV_TYPE_TLV }, - [GSM0808_IE_CIRCUIT_IDENTITY_CODE] = { TLV_TYPE_FIXED, 2 }, - [GSM0808_IE_DOWNLINK_DTX_FLAG] = { TLV_TYPE_TV }, - [GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV }, - [GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV }, - [GSM0808_IE_GROUP_CALL_REFERENCE] = { TLV_TYPE_TLV }, - [GSM0808_IE_TALKER_FLAG] = { TLV_TYPE_T }, - [GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV }, - [GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV }, - [GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TLV }, - [GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV }, - [GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV }, - [GSM0808_IE_CELL_IDENTIFIER] = { TLV_TYPE_TLV }, - [GSM0808_IE_CHOSEN_CHANNEL] = { TLV_TYPE_TV }, - [GSM0808_IE_LAYER_3_INFORMATION] = { TLV_TYPE_TLV }, - [GSM0808_IE_SPEECH_VERSION] = { TLV_TYPE_TV }, - [GSM0808_IE_CHOSEN_ENCR_ALG] = { TLV_TYPE_TV }, - }, -}; - -const struct tlv_definition *gsm0808_att_tlvdef() -{ - return &bss_att_tlvdef; -} diff --git a/src/gsm48.c b/src/gsm48.c deleted file mode 100644 index daec4f39..00000000 --- a/src/gsm48.c +++ /dev/null @@ -1,415 +0,0 @@ -/* GSM Mobile Radio Interface Layer 3 messages - * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ - -/* (C) 2008-2010 by Harald Welte - * (C) 2008, 2009 by Holger Hans Peter Freyther - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include - -#include - -#include -#include -#include - -#include - -const struct tlv_definition gsm48_att_tlvdef = { - .def = { - [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV }, - [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV }, - [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV }, - [GSM48_IE_UTC] = { TLV_TYPE_TV }, - [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 }, - [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV }, - - [GSM48_IE_BEARER_CAP] = { TLV_TYPE_TLV }, - [GSM48_IE_CAUSE] = { TLV_TYPE_TLV }, - [GSM48_IE_CC_CAP] = { TLV_TYPE_TLV }, - [GSM48_IE_ALERT] = { TLV_TYPE_TLV }, - [GSM48_IE_FACILITY] = { TLV_TYPE_TLV }, - [GSM48_IE_PROGR_IND] = { TLV_TYPE_TLV }, - [GSM48_IE_AUX_STATUS] = { TLV_TYPE_TLV }, - [GSM48_IE_NOTIFY] = { TLV_TYPE_TV }, - [GSM48_IE_KPD_FACILITY] = { TLV_TYPE_TV }, - [GSM48_IE_SIGNAL] = { TLV_TYPE_TV }, - [GSM48_IE_CONN_BCD] = { TLV_TYPE_TLV }, - [GSM48_IE_CONN_SUB] = { TLV_TYPE_TLV }, - [GSM48_IE_CALLING_BCD] = { TLV_TYPE_TLV }, - [GSM48_IE_CALLING_SUB] = { TLV_TYPE_TLV }, - [GSM48_IE_CALLED_BCD] = { TLV_TYPE_TLV }, - [GSM48_IE_CALLED_SUB] = { TLV_TYPE_TLV }, - [GSM48_IE_REDIR_BCD] = { TLV_TYPE_TLV }, - [GSM48_IE_REDIR_SUB] = { TLV_TYPE_TLV }, - [GSM48_IE_LOWL_COMPAT] = { TLV_TYPE_TLV }, - [GSM48_IE_HIGHL_COMPAT] = { TLV_TYPE_TLV }, - [GSM48_IE_USER_USER] = { TLV_TYPE_TLV }, - [GSM48_IE_SS_VERS] = { TLV_TYPE_TLV }, - [GSM48_IE_MORE_DATA] = { TLV_TYPE_T }, - [GSM48_IE_CLIR_SUPP] = { TLV_TYPE_T }, - [GSM48_IE_CLIR_INVOC] = { TLV_TYPE_T }, - [GSM48_IE_REV_C_SETUP] = { TLV_TYPE_T }, - [GSM48_IE_REPEAT_CIR] = { TLV_TYPE_T }, - [GSM48_IE_REPEAT_SEQ] = { TLV_TYPE_T }, - /* FIXME: more elements */ - }, -}; - -/* RR elements */ -const struct tlv_definition gsm48_rr_att_tlvdef = { - .def = { - /* NOTE: Don't add IE 17 = MOBILE_ID here, it already used. */ - [GSM48_IE_VGCS_TARGET] = { TLV_TYPE_TLV }, - [GSM48_IE_FRQSHORT_AFTER] = { TLV_TYPE_FIXED, 9 }, - [GSM48_IE_MUL_RATE_CFG] = { TLV_TYPE_TLV }, - [GSM48_IE_FREQ_L_AFTER] = { TLV_TYPE_TLV }, - [GSM48_IE_MSLOT_DESC] = { TLV_TYPE_TLV }, - [GSM48_IE_CHANMODE_2] = { TLV_TYPE_TV }, - [GSM48_IE_FRQSHORT_BEFORE] = { TLV_TYPE_FIXED, 9 }, - [GSM48_IE_CHANMODE_3] = { TLV_TYPE_TV }, - [GSM48_IE_CHANMODE_4] = { TLV_TYPE_TV }, - [GSM48_IE_CHANMODE_5] = { TLV_TYPE_TV }, - [GSM48_IE_CHANMODE_6] = { TLV_TYPE_TV }, - [GSM48_IE_CHANMODE_7] = { TLV_TYPE_TV }, - [GSM48_IE_CHANMODE_8] = { TLV_TYPE_TV }, - [GSM48_IE_FREQ_L_BEFORE] = { TLV_TYPE_TLV }, - [GSM48_IE_CH_DESC_1_BEFORE] = { TLV_TYPE_FIXED, 3 }, - [GSM48_IE_CH_DESC_2_BEFORE] = { TLV_TYPE_FIXED, 3 }, - [GSM48_IE_F_CH_SEQ_BEFORE] = { TLV_TYPE_FIXED, 9 }, - [GSM48_IE_CLASSMARK3] = { TLV_TYPE_TLV }, - [GSM48_IE_MA_BEFORE] = { TLV_TYPE_TLV }, - [GSM48_IE_RR_PACKET_UL] = { TLV_TYPE_TLV }, - [GSM48_IE_RR_PACKET_DL] = { TLV_TYPE_TLV }, - [GSM48_IE_CELL_CH_DESC] = { TLV_TYPE_FIXED, 16 }, - [GSM48_IE_CHANMODE_1] = { TLV_TYPE_TV }, - [GSM48_IE_CHDES_2_AFTER] = { TLV_TYPE_FIXED, 3 }, - [GSM48_IE_MODE_SEC_CH] = { TLV_TYPE_TV }, - [GSM48_IE_F_CH_SEQ_AFTER] = { TLV_TYPE_FIXED, 9 }, - [GSM48_IE_MA_AFTER] = { TLV_TYPE_TLV }, - [GSM48_IE_BA_RANGE] = { TLV_TYPE_TLV }, - [GSM48_IE_GROUP_CHDES] = { TLV_TYPE_TLV }, - [GSM48_IE_BA_LIST_PREF] = { TLV_TYPE_TLV }, - [GSM48_IE_MOB_OVSERV_DIF] = { TLV_TYPE_TLV }, - [GSM48_IE_REALTIME_DIFF] = { TLV_TYPE_TLV }, - [GSM48_IE_START_TIME] = { TLV_TYPE_FIXED, 2 }, - [GSM48_IE_TIMING_ADVANCE] = { TLV_TYPE_TV }, - [GSM48_IE_GROUP_CIP_SEQ] = { TLV_TYPE_SINGLE_TV }, - [GSM48_IE_CIP_MODE_SET] = { TLV_TYPE_SINGLE_TV }, - [GSM48_IE_GPRS_RESUMPT] = { TLV_TYPE_SINGLE_TV }, - [GSM48_IE_SYNC_IND] = { TLV_TYPE_SINGLE_TV }, - }, -}; - -/* MM elements */ -const struct tlv_definition gsm48_mm_att_tlvdef = { - .def = { - [GSM48_IE_MOBILE_ID] = { TLV_TYPE_TLV }, - [GSM48_IE_NAME_LONG] = { TLV_TYPE_TLV }, - [GSM48_IE_NAME_SHORT] = { TLV_TYPE_TLV }, - [GSM48_IE_UTC] = { TLV_TYPE_TV }, - [GSM48_IE_NET_TIME_TZ] = { TLV_TYPE_FIXED, 7 }, - [GSM48_IE_LSA_IDENT] = { TLV_TYPE_TLV }, - - [GSM48_IE_LOCATION_AREA] = { TLV_TYPE_FIXED, 5 }, - [GSM48_IE_PRIORITY_LEV] = { TLV_TYPE_SINGLE_TV }, - [GSM48_IE_FOLLOW_ON_PROC] = { TLV_TYPE_T }, - [GSM48_IE_CTS_PERMISSION] = { TLV_TYPE_T }, - }, -}; - -static const struct value_string rr_cause_names[] = { - { GSM48_RR_CAUSE_NORMAL, "Normal event" }, - { GSM48_RR_CAUSE_ABNORMAL_UNSPEC, "Abnormal release, unspecified" }, - { GSM48_RR_CAUSE_ABNORMAL_UNACCT, "Abnormal release, channel unacceptable" }, - { GSM48_RR_CAUSE_ABNORMAL_TIMER, "Abnormal release, timer expired" }, - { GSM48_RR_CAUSE_ABNORMAL_NOACT, "Abnormal release, no activity on radio path" }, - { GSM48_RR_CAUSE_PREMPTIVE_REL, "Preemptive release" }, - { GSM48_RR_CAUSE_HNDOVER_IMP, "Handover impossible, timing advance out of range" }, - { GSM48_RR_CAUSE_CHAN_MODE_UNACCT, "Channel mode unacceptable" }, - { GSM48_RR_CAUSE_FREQ_NOT_IMPL, "Frequency not implemented" }, - { GSM48_RR_CAUSE_CALL_CLEARED, "Call already cleared" }, - { GSM48_RR_CAUSE_SEMANT_INCORR, "Semantically incorrect message" }, - { GSM48_RR_CAUSE_INVALID_MAND_INF, "Invalid mandatory information" }, - { GSM48_RR_CAUSE_MSG_TYPE_N, "Message type non-existant or not implemented" }, - { GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT, "Message type not compatible with protocol state" }, - { GSM48_RR_CAUSE_COND_IE_ERROR, "Conditional IE error" }, - { GSM48_RR_CAUSE_NO_CELL_ALLOC_A, "No cell allocation available" }, - { GSM48_RR_CAUSE_PROT_ERROR_UNSPC, "Protocol error unspecified" }, - { 0, NULL }, -}; - -/* FIXME: convert to value_string */ -static const char *cc_state_names[32] = { - "NULL", - "INITIATED", - "MM_CONNECTION_PEND", - "MO_CALL_PROC", - "CALL_DELIVERED", - "illegal state 5", - "CALL_PRESENT", - "CALL_RECEIVED", - "CONNECT_REQUEST", - "MO_TERM_CALL_CONF", - "ACTIVE", - "DISCONNECT_REQ", - "DISCONNECT_IND", - "illegal state 13", - "illegal state 14", - "illegal state 15", - "illegal state 16", - "illegal state 17", - "illegal state 18", - "RELEASE_REQ", - "illegal state 20", - "illegal state 21", - "illegal state 22", - "illegal state 23", - "illegal state 24", - "illegal state 25", - "MO_ORIG_MODIFY", - "MO_TERM_MODIFY", - "CONNECT_IND", - "illegal state 29", - "illegal state 30", - "illegal state 31", -}; - -const char *gsm48_cc_state_name(uint8_t state) -{ - if (state < ARRAY_SIZE(cc_state_names)) - return cc_state_names[state]; - - return "invalid"; -} - -static const struct value_string cc_msg_names[] = { - { GSM48_MT_CC_ALERTING, "ALERTING" }, - { GSM48_MT_CC_CALL_PROC, "CALL_PROC" }, - { GSM48_MT_CC_PROGRESS, "PROGRESS" }, - { GSM48_MT_CC_ESTAB, "ESTAB" }, - { GSM48_MT_CC_SETUP, "SETUP" }, - { GSM48_MT_CC_ESTAB_CONF, "ESTAB_CONF" }, - { GSM48_MT_CC_CONNECT, "CONNECT" }, - { GSM48_MT_CC_CALL_CONF, "CALL_CONF" }, - { GSM48_MT_CC_START_CC, "START_CC" }, - { GSM48_MT_CC_RECALL, "RECALL" }, - { GSM48_MT_CC_EMERG_SETUP, "EMERG_SETUP" }, - { GSM48_MT_CC_CONNECT_ACK, "CONNECT_ACK" }, - { GSM48_MT_CC_USER_INFO, "USER_INFO" }, - { GSM48_MT_CC_MODIFY_REJECT, "MODIFY_REJECT" }, - { GSM48_MT_CC_MODIFY, "MODIFY" }, - { GSM48_MT_CC_HOLD, "HOLD" }, - { GSM48_MT_CC_HOLD_ACK, "HOLD_ACK" }, - { GSM48_MT_CC_HOLD_REJ, "HOLD_REJ" }, - { GSM48_MT_CC_RETR, "RETR" }, - { GSM48_MT_CC_RETR_ACK, "RETR_ACK" }, - { GSM48_MT_CC_RETR_REJ, "RETR_REJ" }, - { GSM48_MT_CC_MODIFY_COMPL, "MODIFY_COMPL" }, - { GSM48_MT_CC_DISCONNECT, "DISCONNECT" }, - { GSM48_MT_CC_RELEASE_COMPL, "RELEASE_COMPL" }, - { GSM48_MT_CC_RELEASE, "RELEASE" }, - { GSM48_MT_CC_STOP_DTMF, "STOP_DTMF" }, - { GSM48_MT_CC_STOP_DTMF_ACK, "STOP_DTMF_ACK" }, - { GSM48_MT_CC_STATUS_ENQ, "STATUS_ENQ" }, - { GSM48_MT_CC_START_DTMF, "START_DTMF" }, - { GSM48_MT_CC_START_DTMF_ACK, "START_DTMF_ACK" }, - { GSM48_MT_CC_START_DTMF_REJ, "START_DTMF_REJ" }, - { GSM48_MT_CC_CONG_CTRL, "CONG_CTRL" }, - { GSM48_MT_CC_FACILITY, "FACILITY" }, - { GSM48_MT_CC_STATUS, "STATUS" }, - { GSM48_MT_CC_NOTIFY, "NOTFIY" }, - { 0, NULL } -}; - -const char *gsm48_cc_msg_name(uint8_t msgtype) -{ - return get_value_string(cc_msg_names, msgtype); -} - -const char *rr_cause_name(uint8_t cause) -{ - return get_value_string(rr_cause_names, cause); -} - -static void to_bcd(uint8_t *bcd, uint16_t val) -{ - bcd[2] = val % 10; - val = val / 10; - bcd[1] = val % 10; - val = val / 10; - bcd[0] = val % 10; - val = val / 10; -} - -void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc, - uint16_t mnc, uint16_t lac) -{ - uint8_t bcd[3]; - - to_bcd(bcd, mcc); - lai48->digits[0] = bcd[0] | (bcd[1] << 4); - lai48->digits[1] = bcd[2]; - - to_bcd(bcd, mnc); - /* FIXME: do we need three-digit MNC? See Table 10.5.3 */ - if (mnc > 99) { - lai48->digits[1] |= bcd[2] << 4; - lai48->digits[2] = bcd[0] | (bcd[1] << 4); - } else { - lai48->digits[1] |= 0xf << 4; - lai48->digits[2] = bcd[1] | (bcd[2] << 4); - } - - lai48->lac = htons(lac); -} - -int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi) -{ - uint32_t *tptr = (uint32_t *) &buf[3]; - - buf[0] = GSM48_IE_MOBILE_ID; - buf[1] = GSM48_TMSI_LEN; - buf[2] = 0xf0 | GSM_MI_TYPE_TMSI; - *tptr = htonl(tmsi); - - return 7; -} - -int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi) -{ - unsigned int length = strlen(imsi), i, off = 0; - uint8_t odd = (length & 0x1) == 1; - - buf[0] = GSM48_IE_MOBILE_ID; - buf[2] = char2bcd(imsi[0]) << 4 | GSM_MI_TYPE_IMSI | (odd << 3); - - /* if the length is even we will fill half of the last octet */ - if (odd) - buf[1] = (length + 1) >> 1; - else - buf[1] = (length + 2) >> 1; - - for (i = 1; i < buf[1]; ++i) { - uint8_t lower, upper; - - lower = char2bcd(imsi[++off]); - if (!odd && off + 1 == length) - upper = 0x0f; - else - upper = char2bcd(imsi[++off]) & 0x0f; - - buf[2 + i] = (upper << 4) | lower; - } - - return 2 + buf[1]; -} - -/* Convert Mobile Identity (10.5.1.4) to string */ -int gsm48_mi_to_string(char *string, const int str_len, const uint8_t *mi, - const int mi_len) -{ - int i; - uint8_t mi_type; - char *str_cur = string; - uint32_t tmsi; - - mi_type = mi[0] & GSM_MI_TYPE_MASK; - - switch (mi_type) { - case GSM_MI_TYPE_NONE: - break; - case GSM_MI_TYPE_TMSI: - /* Table 10.5.4.3, reverse generate_mid_from_tmsi */ - if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) { - memcpy(&tmsi, &mi[1], 4); - tmsi = ntohl(tmsi); - return snprintf(string, str_len, "%u", tmsi); - } - break; - case GSM_MI_TYPE_IMSI: - case GSM_MI_TYPE_IMEI: - case GSM_MI_TYPE_IMEISV: - *str_cur++ = bcd2char(mi[0] >> 4); - - for (i = 1; i < mi_len; i++) { - if (str_cur + 2 >= string + str_len) - return str_cur - string; - *str_cur++ = bcd2char(mi[i] & 0xf); - /* skip last nibble in last input byte when GSM_EVEN */ - if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD)) - *str_cur++ = bcd2char(mi[i] >> 4); - } - break; - default: - break; - } - *str_cur++ = '\0'; - - return str_cur - string; -} - -void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf) -{ - raid->mcc = (buf[0] & 0xf) * 100; - raid->mcc += (buf[0] >> 4) * 10; - raid->mcc += (buf[1] & 0xf) * 1; - - /* I wonder who came up with the stupidity of encoding the MNC - * differently depending on how many digits its decimal number has! */ - if ((buf[1] >> 4) == 0xf) { - raid->mnc = (buf[2] & 0xf) * 10; - raid->mnc += (buf[2] >> 4) * 1; - } else { - raid->mnc = (buf[2] & 0xf) * 100; - raid->mnc += (buf[2] >> 4) * 10; - raid->mnc += (buf[1] >> 4) * 1; - } - - raid->lac = ntohs(*(uint16_t *)(buf + 3)); - raid->rac = buf[5]; -} - -int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid) -{ - uint16_t mcc = raid->mcc; - uint16_t mnc = raid->mnc; - - buf[0] = ((mcc / 100) % 10) | (((mcc / 10) % 10) << 4); - buf[1] = (mcc % 10); - - /* I wonder who came up with the stupidity of encoding the MNC - * differently depending on how many digits its decimal number has! */ - if (mnc < 100) { - buf[1] |= 0xf0; - buf[2] = ((mnc / 10) % 10) | ((mnc % 10) << 4); - } else { - buf[1] |= (mnc % 10) << 4; - buf[2] = ((mnc / 100) % 10) | (((mcc / 10) % 10) << 4); - } - - *(uint16_t *)(buf+3) = htons(raid->lac); - - buf[5] = raid->rac; - - return 6; -} diff --git a/src/gsm48_ie.c b/src/gsm48_ie.c deleted file mode 100644 index 0e270881..00000000 --- a/src/gsm48_ie.c +++ /dev/null @@ -1,1095 +0,0 @@ -/* GSM Mobile Radio Interface Layer 3 messages - * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ - -/* (C) 2008 by Harald Welte - * (C) 2009-2010 by Andreas Eversberg - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static const char bcd_num_digits[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '*', '#', 'a', 'b', 'c', '\0' -}; - -/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */ -int gsm48_decode_bcd_number(char *output, int output_len, - const uint8_t *bcd_lv, int h_len) -{ - uint8_t in_len = bcd_lv[0]; - int i; - - for (i = 1 + h_len; i <= in_len; i++) { - /* lower nibble */ - output_len--; - if (output_len <= 1) - break; - *output++ = bcd_num_digits[bcd_lv[i] & 0xf]; - - /* higher nibble */ - output_len--; - if (output_len <= 1) - break; - *output++ = bcd_num_digits[bcd_lv[i] >> 4]; - } - if (output_len >= 1) - *output++ = '\0'; - - return 0; -} - -/* convert a single ASCII character to call-control BCD */ -static int asc_to_bcd(const char asc) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bcd_num_digits); i++) { - if (bcd_num_digits[i] == asc) - return i; - } - return -EINVAL; -} - -/* convert a ASCII phone number to 'called/calling/connect party BCD number' */ -int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len, - int h_len, const char *input) -{ - int in_len = strlen(input); - int i; - uint8_t *bcd_cur = bcd_lv + 1 + h_len; - - /* two digits per byte, plus type byte */ - bcd_lv[0] = in_len/2 + h_len; - if (in_len % 2) - bcd_lv[0]++; - - if (bcd_lv[0] > max_len) - return -EIO; - - for (i = 0; i < in_len; i++) { - int rc = asc_to_bcd(input[i]); - if (rc < 0) - return rc; - if (i % 2 == 0) - *bcd_cur = rc; - else - *bcd_cur++ |= (rc << 4); - } - /* append padding nibble in case of odd length */ - if (i % 2) - *bcd_cur++ |= 0xf0; - - /* return how many bytes we used */ - return (bcd_cur - bcd_lv); -} - -/* decode 'bearer capability' */ -int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap, - const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - int i, s; - - if (in_len < 1) - return -EINVAL; - - bcap->speech_ver[0] = -1; /* end of list, of maximum 7 values */ - - /* octet 3 */ - bcap->transfer = lv[1] & 0x07; - bcap->mode = (lv[1] & 0x08) >> 3; - bcap->coding = (lv[1] & 0x10) >> 4; - bcap->radio = (lv[1] & 0x60) >> 5; - - if (bcap->transfer == GSM_MNCC_BCAP_SPEECH) { - i = 1; - s = 0; - while(!(lv[i] & 0x80)) { - i++; /* octet 3a etc */ - if (in_len < i) - return 0; - bcap->speech_ver[s++] = lv[i] & 0x0f; - bcap->speech_ver[s] = -1; /* end of list */ - if (i == 2) /* octet 3a */ - bcap->speech_ctm = (lv[i] & 0x20) >> 5; - if (s == 7) /* maximum speech versions + end of list */ - return 0; - } - } else { - i = 1; - while (!(lv[i] & 0x80)) { - i++; /* octet 3a etc */ - if (in_len < i) - return 0; - /* ignore them */ - } - /* FIXME: implement OCTET 4+ parsing */ - } - - return 0; -} - -/* encode 'bearer capability' */ -int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only, - const struct gsm_mncc_bearer_cap *bcap) -{ - uint8_t lv[32 + 1]; - int i = 1, s; - - lv[1] = bcap->transfer; - lv[1] |= bcap->mode << 3; - lv[1] |= bcap->coding << 4; - lv[1] |= bcap->radio << 5; - - if (bcap->transfer == GSM_MNCC_BCAP_SPEECH) { - for (s = 0; bcap->speech_ver[s] >= 0; s++) { - i++; /* octet 3a etc */ - lv[i] = bcap->speech_ver[s]; - if (i == 2) /* octet 3a */ - lv[i] |= bcap->speech_ctm << 5; - } - lv[i] |= 0x80; /* last IE of octet 3 etc */ - } else { - /* FIXME: implement OCTET 4+ encoding */ - } - - lv[0] = i; - if (lv_only) - msgb_lv_put(msg, lv[0], lv+1); - else - msgb_tlv_put(msg, GSM48_IE_BEARER_CAP, lv[0], lv+1); - - return 0; -} - -/* decode 'call control cap' */ -int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - - if (in_len < 1) - return -EINVAL; - - /* octet 3 */ - ccap->dtmf = lv[1] & 0x01; - ccap->pcp = (lv[1] & 0x02) >> 1; - - return 0; -} - -/* encode 'call control cap' */ -int gsm48_encode_cccap(struct msgb *msg, - const struct gsm_mncc_cccap *ccap) -{ - uint8_t lv[2]; - - lv[0] = 1; - lv[1] = 0; - if (ccap->dtmf) - lv [1] |= 0x01; - if (ccap->pcp) - lv [1] |= 0x02; - - msgb_tlv_put(msg, GSM48_IE_CC_CAP, lv[0], lv+1); - - return 0; -} - -/* decode 'called party BCD number' */ -int gsm48_decode_called(struct gsm_mncc_number *called, - const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - - if (in_len < 1) - return -EINVAL; - - /* octet 3 */ - called->plan = lv[1] & 0x0f; - called->type = (lv[1] & 0x70) >> 4; - - /* octet 4..N */ - gsm48_decode_bcd_number(called->number, sizeof(called->number), lv, 1); - - return 0; -} - -/* encode 'called party BCD number' */ -int gsm48_encode_called(struct msgb *msg, - const struct gsm_mncc_number *called) -{ - uint8_t lv[18]; - int ret; - - /* octet 3 */ - lv[1] = 0x80; /* no extension */ - lv[1] |= called->plan; - lv[1] |= called->type << 4; - - /* octet 4..N, octet 2 */ - ret = gsm48_encode_bcd_number(lv, sizeof(lv), 1, called->number); - if (ret < 0) - return ret; - - msgb_tlv_put(msg, GSM48_IE_CALLED_BCD, lv[0], lv+1); - - return 0; -} - -/* decode callerid of various IEs */ -int gsm48_decode_callerid(struct gsm_mncc_number *callerid, - const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - int i = 1; - - if (in_len < 1) - return -EINVAL; - - /* octet 3 */ - callerid->plan = lv[1] & 0x0f; - callerid->type = (lv[1] & 0x70) >> 4; - - /* octet 3a */ - if (!(lv[1] & 0x80)) { - callerid->screen = lv[2] & 0x03; - callerid->present = (lv[2] & 0x60) >> 5; - i = 2; - } - - /* octet 4..N */ - gsm48_decode_bcd_number(callerid->number, sizeof(callerid->number), lv, i); - - return 0; -} - -/* encode callerid of various IEs */ -int gsm48_encode_callerid(struct msgb *msg, int ie, int max_len, - const struct gsm_mncc_number *callerid) -{ - uint8_t lv[max_len - 1]; - int h_len = 1; - int ret; - - /* octet 3 */ - lv[1] = callerid->plan; - lv[1] |= callerid->type << 4; - - if (callerid->present || callerid->screen) { - /* octet 3a */ - lv[2] = callerid->screen; - lv[2] |= callerid->present << 5; - lv[2] |= 0x80; - h_len++; - } else - lv[1] |= 0x80; - - /* octet 4..N, octet 2 */ - ret = gsm48_encode_bcd_number(lv, sizeof(lv), h_len, callerid->number); - if (ret < 0) - return ret; - - msgb_tlv_put(msg, ie, lv[0], lv+1); - - return 0; -} - -/* decode 'cause' */ -int gsm48_decode_cause(struct gsm_mncc_cause *cause, - const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - int i; - - if (in_len < 2) - return -EINVAL; - - cause->diag_len = 0; - - /* octet 3 */ - cause->location = lv[1] & 0x0f; - cause->coding = (lv[1] & 0x60) >> 5; - - i = 1; - if (!(lv[i] & 0x80)) { - i++; /* octet 3a */ - if (in_len < i+1) - return 0; - cause->rec = 1; - cause->rec_val = lv[i] & 0x7f; - } - i++; - - /* octet 4 */ - cause->value = lv[i] & 0x7f; - i++; - - if (in_len < i) /* no diag */ - return 0; - - if (in_len - (i-1) > 32) /* maximum 32 octets */ - return 0; - - /* octet 5-N */ - memcpy(cause->diag, lv + i, in_len - (i-1)); - cause->diag_len = in_len - (i-1); - - return 0; -} - -/* encode 'cause' */ -int gsm48_encode_cause(struct msgb *msg, int lv_only, - const struct gsm_mncc_cause *cause) -{ - uint8_t lv[32+4]; - int i; - - if (cause->diag_len > 32) - return -EINVAL; - - /* octet 3 */ - lv[1] = cause->location; - lv[1] |= cause->coding << 5; - - i = 1; - if (cause->rec) { - i++; /* octet 3a */ - lv[i] = cause->rec_val; - } - lv[i] |= 0x80; /* end of octet 3 */ - - /* octet 4 */ - i++; - lv[i] = 0x80 | cause->value; - - /* octet 5-N */ - if (cause->diag_len) { - memcpy(lv + i, cause->diag, cause->diag_len); - i += cause->diag_len; - } - - lv[0] = i; - if (lv_only) - msgb_lv_put(msg, lv[0], lv+1); - else - msgb_tlv_put(msg, GSM48_IE_CAUSE, lv[0], lv+1); - - return 0; -} - -/* decode 'calling number' */ -int gsm48_decode_calling(struct gsm_mncc_number *calling, - const uint8_t *lv) -{ - return gsm48_decode_callerid(calling, lv); -} - -/* encode 'calling number' */ -int gsm48_encode_calling(struct msgb *msg, - const struct gsm_mncc_number *calling) -{ - return gsm48_encode_callerid(msg, GSM48_IE_CALLING_BCD, 14, calling); -} - -/* decode 'connected number' */ -int gsm48_decode_connected(struct gsm_mncc_number *connected, - const uint8_t *lv) -{ - return gsm48_decode_callerid(connected, lv); -} - -/* encode 'connected number' */ -int gsm48_encode_connected(struct msgb *msg, - const struct gsm_mncc_number *connected) -{ - return gsm48_encode_callerid(msg, GSM48_IE_CONN_BCD, 14, connected); -} - -/* decode 'redirecting number' */ -int gsm48_decode_redirecting(struct gsm_mncc_number *redirecting, - const uint8_t *lv) -{ - return gsm48_decode_callerid(redirecting, lv); -} - -/* encode 'redirecting number' */ -int gsm48_encode_redirecting(struct msgb *msg, - const struct gsm_mncc_number *redirecting) -{ - return gsm48_encode_callerid(msg, GSM48_IE_REDIR_BCD, 19, redirecting); -} - -/* decode 'facility' */ -int gsm48_decode_facility(struct gsm_mncc_facility *facility, - const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - - if (in_len < 1) - return -EINVAL; - - if (in_len > sizeof(facility->info)) - return -EINVAL; - - memcpy(facility->info, lv+1, in_len); - facility->len = in_len; - - return 0; -} - -/* encode 'facility' */ -int gsm48_encode_facility(struct msgb *msg, int lv_only, - const struct gsm_mncc_facility *facility) -{ - uint8_t lv[GSM_MAX_FACILITY + 1]; - - if (facility->len < 1 || facility->len > GSM_MAX_FACILITY) - return -EINVAL; - - memcpy(lv+1, facility->info, facility->len); - lv[0] = facility->len; - if (lv_only) - msgb_lv_put(msg, lv[0], lv+1); - else - msgb_tlv_put(msg, GSM48_IE_FACILITY, lv[0], lv+1); - - return 0; -} - -/* decode 'notify' */ -int gsm48_decode_notify(int *notify, const uint8_t *v) -{ - *notify = v[0] & 0x7f; - - return 0; -} - -/* encode 'notify' */ -int gsm48_encode_notify(struct msgb *msg, int notify) -{ - msgb_v_put(msg, notify | 0x80); - - return 0; -} - -/* decode 'signal' */ -int gsm48_decode_signal(int *signal, const uint8_t *v) -{ - *signal = v[0]; - - return 0; -} - -/* encode 'signal' */ -int gsm48_encode_signal(struct msgb *msg, int signal) -{ - msgb_tv_put(msg, GSM48_IE_SIGNAL, signal); - - return 0; -} - -/* decode 'keypad' */ -int gsm48_decode_keypad(int *keypad, const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - - if (in_len < 1) - return -EINVAL; - - *keypad = lv[1] & 0x7f; - - return 0; -} - -/* encode 'keypad' */ -int gsm48_encode_keypad(struct msgb *msg, int keypad) -{ - msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad); - - return 0; -} - -/* decode 'progress' */ -int gsm48_decode_progress(struct gsm_mncc_progress *progress, - const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - - if (in_len < 2) - return -EINVAL; - - progress->coding = (lv[1] & 0x60) >> 5; - progress->location = lv[1] & 0x0f; - progress->descr = lv[2] & 0x7f; - - return 0; -} - -/* encode 'progress' */ -int gsm48_encode_progress(struct msgb *msg, int lv_only, - const struct gsm_mncc_progress *p) -{ - uint8_t lv[3]; - - lv[0] = 2; - lv[1] = 0x80 | ((p->coding & 0x3) << 5) | (p->location & 0xf); - lv[2] = 0x80 | (p->descr & 0x7f); - if (lv_only) - msgb_lv_put(msg, lv[0], lv+1); - else - msgb_tlv_put(msg, GSM48_IE_PROGR_IND, lv[0], lv+1); - - return 0; -} - -/* decode 'user-user' */ -int gsm48_decode_useruser(struct gsm_mncc_useruser *uu, - const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - char *info = uu->info; - int info_len = sizeof(uu->info); - int i; - - if (in_len < 1) - return -EINVAL; - - uu->proto = lv[1]; - - for (i = 2; i <= in_len; i++) { - info_len--; - if (info_len <= 1) - break; - *info++ = lv[i]; - } - if (info_len >= 1) - *info++ = '\0'; - - return 0; -} - -/* encode 'useruser' */ -int gsm48_encode_useruser(struct msgb *msg, int lv_only, - const struct gsm_mncc_useruser *uu) -{ - uint8_t lv[GSM_MAX_USERUSER + 2]; - - if (strlen(uu->info) > GSM_MAX_USERUSER) - return -EINVAL; - - lv[0] = 1 + strlen(uu->info); - lv[1] = uu->proto; - memcpy(lv + 2, uu->info, strlen(uu->info)); - if (lv_only) - msgb_lv_put(msg, lv[0], lv+1); - else - msgb_tlv_put(msg, GSM48_IE_USER_USER, lv[0], lv+1); - - return 0; -} - -/* decode 'ss version' */ -int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv, - const uint8_t *lv) -{ - uint8_t in_len = lv[0]; - - if (in_len < 1 || in_len < sizeof(ssv->info)) - return -EINVAL; - - memcpy(ssv->info, lv + 1, in_len); - ssv->len = in_len; - - return 0; -} - -/* encode 'ss version' */ -int gsm48_encode_ssversion(struct msgb *msg, - const struct gsm_mncc_ssversion *ssv) -{ - uint8_t lv[GSM_MAX_SSVERSION + 1]; - - if (ssv->len > GSM_MAX_SSVERSION) - return -EINVAL; - - lv[0] = ssv->len; - memcpy(lv + 1, ssv->info, ssv->len); - msgb_tlv_put(msg, GSM48_IE_SS_VERS, lv[0], lv+1); - - return 0; -} - -/* decode 'more data' does not require a function, because it has no value */ - -/* encode 'more data' */ -int gsm48_encode_more(struct msgb *msg) -{ - uint8_t *ie; - - ie = msgb_put(msg, 1); - ie[0] = GSM48_IE_MORE_DATA; - - return 0; -} - -/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */ -int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd, - uint8_t len, uint8_t mask, uint8_t frqt) -{ - int i; - - /* NOTES: - * - * The Range format uses "SMOD" computation. - * e.g. "n SMOD m" equals "((n - 1) % m) + 1" - * A cascade of multiple SMOD computations is simpified: - * "(n SMOD m) SMOD o" equals "(((n - 1) % m) % o) + 1" - * - * The Range format uses 16 octets of data in SYSTEM INFORMATION. - * When used in dedicated messages, the length can be less. - * In this case the ranges are decoded for all frequencies that - * fit in the block of given length. - */ - - /* tabula rasa */ - for (i = 0; i < 1024; i++) - f[i].mask &= ~frqt; - - /* 00..XXX. */ - if ((cd[0] & 0xc0 & mask) == 0x00) { - /* Bit map 0 format */ - if (len < 16) - return -EINVAL; - for (i = 1; i <= 124; i++) - if ((cd[15 - ((i-1) >> 3)] & (1 << ((i-1) & 7)))) - f[i].mask |= frqt; - - return 0; - } - - /* 10..0XX. */ - if ((cd[0] & 0xc8 & mask) == 0x80) { - /* Range 1024 format */ - uint16_t w[17]; /* 1..16 */ - struct gsm48_range_1024 *r = (struct gsm48_range_1024 *)cd; - - if (len < 2) - return -EINVAL; - memset(w, 0, sizeof(w)); - if (r->f0) - f[0].mask |= frqt; - w[1] = (r->w1_hi << 8) | r->w1_lo; - if (len >= 4) - w[2] = (r->w2_hi << 1) | r->w2_lo; - if (len >= 5) - w[3] = (r->w3_hi << 2) | r->w3_lo; - if (len >= 6) - w[4] = (r->w4_hi << 2) | r->w4_lo; - if (len >= 7) - w[5] = (r->w5_hi << 2) | r->w5_lo; - if (len >= 8) - w[6] = (r->w6_hi << 2) | r->w6_lo; - if (len >= 9) - w[7] = (r->w7_hi << 2) | r->w7_lo; - if (len >= 10) - w[8] = (r->w8_hi << 1) | r->w8_lo; - if (len >= 10) - w[9] = r->w9; - if (len >= 11) - w[10] = r->w10; - if (len >= 12) - w[11] = (r->w11_hi << 6) | r->w11_lo; - if (len >= 13) - w[12] = (r->w12_hi << 5) | r->w12_lo; - if (len >= 14) - w[13] = (r->w13_hi << 4) | r->w13_lo; - if (len >= 15) - w[14] = (r->w14_hi << 3) | r->w14_lo; - if (len >= 16) - w[15] = (r->w15_hi << 2) | r->w15_lo; - if (len >= 16) - w[16] = r->w16; - if (w[1]) - f[w[1]].mask |= frqt; - if (w[2]) - f[((w[1] - 512 + w[2] - 1) % 1023) + 1].mask |= frqt; - if (w[3]) - f[((w[1] + w[3] - 1) % 1023) + 1].mask |= frqt; - if (w[4]) - f[((w[1] - 512 + ((w[2] - 256 + w[4] - 1) % 511)) % 1023) + 1].mask |= frqt; - if (w[5]) - f[((w[1] + ((w[3] - 256 - w[5] - 1) % 511)) % 1023) + 1].mask |= frqt; - if (w[6]) - f[((w[1] - 512 + ((w[2] + w[6] - 1) % 511)) % 1023) + 1].mask |= frqt; - if (w[7]) - f[((w[1] + ((w[3] + w[7] - 1) % 511)) % 1023) + 1].mask |= frqt; - if (w[8]) - f[((w[1] - 512 + ((w[2] - 256 + ((w[4] - 128 + w[8] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; - if (w[9]) - f[((w[1] + ((w[3] - 256 + ((w[5] - 128 + w[9] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; - if (w[10]) - f[((w[1] - 512 + ((w[2] + ((w[6] - 128 + w[10] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; - if (w[11]) - f[((w[1] + ((w[3] + ((w[7] - 128 + w[11] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; - if (w[12]) - f[((w[1] - 512 + ((w[2] - 256 + ((w[4] + w[12] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; - if (w[13]) - f[((w[1] + ((w[3] - 256 + ((w[5] + w[13] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; - if (w[14]) - f[((w[1] - 512 + ((w[2] + ((w[6] + w[14] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; - if (w[15]) - f[((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 255)) % 511)) % 1023) + 1].mask |= frqt; - if (w[16]) - f[((w[1] - 512 + ((w[2] - 256 + ((w[4] - 128 + ((w[8] - 64 + w[16] - 1) % 127)) % 255)) % 511)) % 1023) + 1].mask |= frqt; - - return 0; - } - /* 10..100. */ - if ((cd[0] & 0xce & mask) == 0x88) { - /* Range 512 format */ - uint16_t w[18]; /* 1..17 */ - struct gsm48_range_512 *r = (struct gsm48_range_512 *)cd; - - if (len < 4) - return -EINVAL; - memset(w, 0, sizeof(w)); - w[0] = (r->orig_arfcn_hi << 9) | (r->orig_arfcn_mid << 1) | r->orig_arfcn_lo; - w[1] = (r->w1_hi << 2) | r->w1_lo; - if (len >= 5) - w[2] = (r->w2_hi << 2) | r->w2_lo; - if (len >= 6) - w[3] = (r->w3_hi << 2) | r->w3_lo; - if (len >= 7) - w[4] = (r->w4_hi << 1) | r->w4_lo; - if (len >= 7) - w[5] = r->w5; - if (len >= 8) - w[6] = r->w6; - if (len >= 9) - w[7] = (r->w7_hi << 6) | r->w7_lo; - if (len >= 10) - w[8] = (r->w8_hi << 4) | r->w8_lo; - if (len >= 11) - w[9] = (r->w9_hi << 2) | r->w9_lo; - if (len >= 11) - w[10] = r->w10; - if (len >= 12) - w[11] = r->w11; - if (len >= 13) - w[12] = (r->w12_hi << 4) | r->w12_lo; - if (len >= 14) - w[13] = (r->w13_hi << 2) | r->w13_lo; - if (len >= 14) - w[14] = r->w14; - if (len >= 15) - w[15] = r->w15; - if (len >= 16) - w[16] = (r->w16_hi << 3) | r->w16_lo; - if (len >= 16) - w[17] = r->w17; - f[w[0]].mask |= frqt; - if (w[1]) - f[(w[0] + w[1]) % 1024].mask |= frqt; - if (w[2]) - f[(w[0] + ((w[1] - 256 + w[2] - 1) % 511) + 1) % 1024].mask |= frqt; - if (w[3]) - f[(w[0] + ((w[1] + w[3] - 1) % 511) + 1) % 1024].mask |= frqt; - if (w[4]) - f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + w[4] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[5]) - f[(w[0] + ((w[1] + ((w[3] - 128 + w[5] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[6]) - f[(w[0] + ((w[1] - 256 + ((w[2] + w[6] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[7]) - f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[8]) - f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] - 64 + w[8] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[9]) - f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] - 64 + w[9] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[10]) - f[(w[0] + ((w[1] - 256 + ((w[2] + ((w[6] - 64 + w[10] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[11]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 64 + w[11] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[12]) - f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] + w[12] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[13]) - f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] + w[13] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[14]) - f[(w[0] + ((w[1] - 256 + ((w[2] + ((w[6] + w[14] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[15]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[16]) - f[(w[0] + ((w[1] - 256 + ((w[2] - 128 + ((w[4] - 64 + ((w[8] - 32 + w[16] - 1) % 63)) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - if (w[17]) - f[(w[0] + ((w[1] + ((w[3] - 128 + ((w[5] - 64 + ((w[9] - 32 + w[17] - 1) % 63)) % 127)) % 255)) % 511) + 1) % 1024].mask |= frqt; - - return 0; - } - /* 10..101. */ - if ((cd[0] & 0xce & mask) == 0x8a) { - /* Range 256 format */ - uint16_t w[22]; /* 1..21 */ - struct gsm48_range_256 *r = (struct gsm48_range_256 *)cd; - - if (len < 4) - return -EINVAL; - memset(w, 0, sizeof(w)); - w[0] = (r->orig_arfcn_hi << 9) | (r->orig_arfcn_mid << 1) | r->orig_arfcn_lo; - w[1] = (r->w1_hi << 1) | r->w1_lo; - if (len >= 4) - w[2] = r->w2; - if (len >= 5) - w[3] = r->w3; - if (len >= 6) - w[4] = (r->w4_hi << 5) | r->w4_lo; - if (len >= 7) - w[5] = (r->w5_hi << 3) | r->w5_lo; - if (len >= 8) - w[6] = (r->w6_hi << 1) | r->w6_lo; - if (len >= 8) - w[7] = r->w7; - if (len >= 9) - w[8] = (r->w8_hi << 4) | r->w8_lo; - if (len >= 10) - w[9] = (r->w9_hi << 1) | r->w9_lo; - if (len >= 10) - w[10] = r->w10; - if (len >= 11) - w[11] = (r->w11_hi << 3) | r->w11_lo; - if (len >= 11) - w[12] = r->w12; - if (len >= 12) - w[13] = r->w13; - if (len >= 13) - w[14] = r->w15; - if (len >= 13) - w[15] = (r->w14_hi << 2) | r->w14_lo; - if (len >= 14) - w[16] = (r->w16_hi << 3) | r->w16_lo; - if (len >= 14) - w[17] = r->w17; - if (len >= 15) - w[18] = r->w19; - if (len >= 15) - w[19] = (r->w18_hi << 3) | r->w18_lo; - if (len >= 16) - w[20] = (r->w20_hi << 3) | r->w20_lo; - if (len >= 16) - w[21] = r->w21; - f[w[0]].mask |= frqt; - if (w[1]) - f[(w[0] + w[1]) % 1024].mask |= frqt; - if (w[2]) - f[(w[0] + ((w[1] - 128 + w[2] - 1) % 255) + 1) % 1024].mask |= frqt; - if (w[3]) - f[(w[0] + ((w[1] + w[3] - 1) % 255) + 1) % 1024].mask |= frqt; - if (w[4]) - f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + w[4] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[5]) - f[(w[0] + ((w[1] + ((w[3] - 64 + w[5] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[6]) - f[(w[0] + ((w[1] - 128 + ((w[2] + w[6] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[7]) - f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[8]) - f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] - 32 + w[8] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[9]) - f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] - 32 + w[9] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[10]) - f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] - 32 + w[10] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[11]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 32 + w[11] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[12]) - f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] + w[12] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[13]) - f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] + w[13] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[14]) - f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] + w[14] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[15]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[16]) - f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] - 32 + ((w[8] - 16 + w[16] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[17]) - f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] - 32 + ((w[9] - 16 + w[17] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[18]) - f[(w[0] + ((w[1] - 128 + ((w[2] + ((w[6] - 32 + ((w[10] - 16 + w[18] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[19]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 32 + ((w[11] - 16 + w[19] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[20]) - f[(w[0] + ((w[1] - 128 + ((w[2] - 64 + ((w[4] + ((w[12] - 16 + w[20] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - if (w[21]) - f[(w[0] + ((w[1] + ((w[3] - 64 + ((w[5] + ((w[13] - 16 + w[21] - 1) % 31)) % 63)) % 127)) % 255) + 1) % 1024].mask |= frqt; - - return 0; - } - /* 10..110. */ - if ((cd[0] & 0xce & mask) == 0x8c) { - /* Range 128 format */ - uint16_t w[29]; /* 1..28 */ - struct gsm48_range_128 *r = (struct gsm48_range_128 *)cd; - - if (len < 3) - return -EINVAL; - memset(w, 0, sizeof(w)); - w[0] = (r->orig_arfcn_hi << 9) | (r->orig_arfcn_mid << 1) | r->orig_arfcn_lo; - w[1] = r->w1; - if (len >= 4) - w[2] = r->w2; - if (len >= 5) - w[3] = (r->w3_hi << 4) | r->w3_lo; - if (len >= 6) - w[4] = (r->w4_hi << 1) | r->w4_lo; - if (len >= 6) - w[5] = r->w5; - if (len >= 7) - w[6] = (r->w6_hi << 3) | r->w6_lo; - if (len >= 7) - w[7] = r->w7; - if (len >= 8) - w[8] = r->w8; - if (len >= 8) - w[9] = r->w9; - if (len >= 9) - w[10] = r->w10; - if (len >= 9) - w[11] = r->w11; - if (len >= 10) - w[12] = r->w12; - if (len >= 10) - w[13] = r->w13; - if (len >= 11) - w[14] = r->w14; - if (len >= 11) - w[15] = r->w15; - if (len >= 12) - w[16] = r->w16; - if (len >= 12) - w[17] = r->w17; - if (len >= 13) - w[18] = (r->w18_hi << 1) | r->w18_lo; - if (len >= 13) - w[19] = r->w19; - if (len >= 13) - w[20] = r->w20; - if (len >= 14) - w[21] = (r->w21_hi << 2) | r->w21_lo; - if (len >= 14) - w[22] = r->w22; - if (len >= 14) - w[23] = r->w23; - if (len >= 15) - w[24] = r->w24; - if (len >= 15) - w[25] = r->w25; - if (len >= 16) - w[26] = (r->w26_hi << 1) | r->w26_lo; - if (len >= 16) - w[27] = r->w27; - if (len >= 16) - w[28] = r->w28; - f[w[0]].mask |= frqt; - if (w[1]) - f[(w[0] + w[1]) % 1024].mask |= frqt; - if (w[2]) - f[(w[0] + ((w[1] - 64 + w[2] - 1) % 127) + 1) % 1024].mask |= frqt; - if (w[3]) - f[(w[0] + ((w[1] + w[3] - 1) % 127) + 1) % 1024].mask |= frqt; - if (w[4]) - f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + w[4] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[5]) - f[(w[0] + ((w[1] + ((w[3] - 32 + w[5] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[6]) - f[(w[0] + ((w[1] - 64 + ((w[2] + w[6] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[7]) - f[(w[0] + ((w[1] + ((w[3] + w[7] - 1) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[8]) - f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + w[8] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[9]) - f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + w[9] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[10]) - f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + w[10] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[11]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + w[11] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[12]) - f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + w[12] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[13]) - f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] + w[13] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[14]) - f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] + w[14] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[15]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] + w[15] - 1) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[16]) - f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + ((w[8] - 8 + w[16] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[17]) - f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + ((w[9] - 8 + w[17] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[18]) - f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + ((w[10] - 8 + w[18] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[19]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + ((w[11] - 8 + w[19] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[20]) - f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + ((w[12] - 8 + w[20] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[21]) - f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] + ((w[13] - 8 + w[21] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[22]) - f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] + ((w[14] - 8 + w[22] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[23]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] + ((w[15] - 8 + w[23] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[24]) - f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] - 16 + ((w[8] + w[24] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[25]) - f[(w[0] + ((w[1] + ((w[3] - 32 + ((w[5] - 16 + ((w[9] + w[25] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[26]) - f[(w[0] + ((w[1] - 64 + ((w[2] + ((w[6] - 16 + ((w[10] + w[26] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[27]) - f[(w[0] + ((w[1] + ((w[3] + ((w[7] - 16 + ((w[11] + w[27] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - if (w[28]) - f[(w[0] + ((w[1] - 64 + ((w[2] - 32 + ((w[4] + ((w[12] + w[28] - 1) % 15)) % 31)) % 63)) % 127) + 1) % 1024].mask |= frqt; - - return 0; - } - /* 10..111. */ - if ((cd[0] & 0xce & mask) == 0x8e) { - /* Variable bitmap format (can be any length >= 3) */ - uint16_t orig = 0; - struct gsm48_var_bit *r = (struct gsm48_var_bit *)cd; - - if (len < 3) - return -EINVAL; - orig = (r->orig_arfcn_hi << 9) | (r->orig_arfcn_mid << 1) | r->orig_arfcn_lo; - f[orig].mask |= frqt; - for (i = 1; 2 + (i >> 3) < len; i++) - if ((cd[2 + (i >> 3)] & (0x80 >> (i & 7)))) - f[(orig + i) % 1024].mask |= frqt; - - return 0; - } - - return 0; -} diff --git a/src/gsm_utils.c b/src/gsm_utils.c deleted file mode 100644 index 31e3cd69..00000000 --- a/src/gsm_utils.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * (C) 2008 by Daniel Willmann - * (C) 2009 by Holger Hans Peter Freyther - * (C) 2009-2010 by Harald Welte - * (C) 2010 by Nico Golde - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -//#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "../config.h" - -/* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet - * Greek symbols at hex positions 0x10 and 0x12-0x1a - * left out as they can't be handled with a char and - * since most phones don't display or write these - * characters this would only needlessly make the code - * more complex -*/ -static unsigned char gsm_7bit_alphabet[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x0d, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, - 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x3c, 0x2f, 0x3e, 0x14, 0x11, 0xff, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x28, 0x40, 0x29, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xff, 0x01, 0xff, - 0x03, 0xff, 0x7b, 0x7d, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x7e, 0x5d, 0xff, 0x7c, 0xff, 0xff, 0xff, - 0xff, 0x5b, 0x0e, 0x1c, 0x09, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, - 0xff, 0xff, 0xff, 0xff, 0x5c, 0xff, 0x0b, 0xff, 0xff, 0xff, 0x5e, 0xff, 0xff, 0x1e, 0x7f, - 0xff, 0xff, 0xff, 0x7b, 0x0f, 0x1d, 0xff, 0x04, 0x05, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, - 0xff, 0x7d, 0x08, 0xff, 0xff, 0xff, 0x7c, 0xff, 0x0c, 0x06, 0xff, 0xff, 0x7e, 0xff, 0xff -}; - -/* GSM 03.38 6.2.1 Character lookup for decoding */ -static int gsm_septet_lookup(uint8_t ch) -{ - int i = 0; - for(; i < sizeof(gsm_7bit_alphabet); i++){ - if(gsm_7bit_alphabet[i] == ch) - return i; - } - return -1; -} - -/* GSM 03.38 6.2.1 Character unpacking */ -int gsm_7bit_decode(char *text, const uint8_t *user_data, uint8_t length) -{ - int i = 0; - int l = 0; - int septet_l = (length * 8) / 7; - uint8_t *rtext = calloc(septet_l, sizeof(uint8_t)); - uint8_t tmp; - - /* FIXME: We need to account for user data headers here */ - i += l; - for (; i < septet_l; i++){ - rtext[i] = - ((user_data[(i * 7 + 7) >> 3] << - (7 - ((i * 7 + 7) & 7))) | - (user_data[(i * 7) >> 3] >> - ((i * 7) & 7))) & 0x7f; - } - - for(i = 0; i < septet_l; i++){ - /* this is an extension character */ - if(rtext[i] == 0x1b && i + 1 < length){ - tmp = rtext[i+1]; - *(text++) = gsm_7bit_alphabet[0x7f + tmp]; - i++; - continue; - } - - *(text++) = gsm_septet_lookup(rtext[i]); - } - - *text = '\0'; - free(rtext); - - return i; -} - -/* GSM 03.38 6.2.1 Prepare character packing */ -static int gsm_septet_encode(uint8_t *result, const char *data) -{ - int i, y = 0; - uint8_t ch; - for(i = 0; i < strlen(data); i++){ - ch = data[i]; - switch(ch){ - /* fall-through for extension characters */ - case 0x0c: - case 0x5e: - case 0x7b: - case 0x7d: - case 0x5c: - case 0x5b: - case 0x7e: - case 0x5d: - case 0x7c: - result[y++] = 0x1b; - default: - result[y] = gsm_7bit_alphabet[ch]; - break; - } - y++; - } - - return y; -} - -/* GSM 03.38 6.2.1 Character packing */ -int gsm_7bit_encode(uint8_t *result, const char *data) -{ - int i,y,z = 0; - /* prepare for the worst case, every character expanding to two bytes */ - uint8_t *rdata = calloc(strlen(data) * 2, sizeof(uint8_t)); - uint8_t cb, nb; - int shift = 0; - - y = gsm_septet_encode(rdata, data); - - for(i = 0; i < y; i++) { - if(shift == 7 && i + 1 < y){ - shift = 0; - continue; - } - - cb = (rdata[i] & 0x7f) >> shift; - if(i + 1 < y){ - nb = (rdata[i + 1] & 0x7f) << (7 - shift); - cb = cb | nb; - } - - result[z++] = cb; - - shift++; - } - - free(rdata); - return z; -} - -/* determine power control level for given dBm value, as indicated - * by the tables in chapter 4.1.1 of GSM TS 05.05 */ -int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm) -{ - switch (band) { - case GSM_BAND_450: - case GSM_BAND_480: - case GSM_BAND_750: - case GSM_BAND_900: - case GSM_BAND_810: - case GSM_BAND_850: - if (dbm >= 39) - return 0; - else if (dbm < 5) - return 19; - else { - /* we are guaranteed to have (5 <= dbm < 39) */ - return 2 + ((39 - dbm) / 2); - } - break; - case GSM_BAND_1800: - if (dbm >= 36) - return 29; - else if (dbm >= 34) - return 30; - else if (dbm >= 32) - return 31; - else if (dbm == 31) - return 0; - else { - /* we are guaranteed to have (0 <= dbm < 31) */ - return (30 - dbm) / 2; - } - break; - case GSM_BAND_1900: - if (dbm >= 33) - return 30; - else if (dbm >= 32) - return 31; - else if (dbm == 31) - return 0; - else { - /* we are guaranteed to have (0 <= dbm < 31) */ - return (30 - dbm) / 2; - } - break; - } - return -EINVAL; -} - -int ms_pwr_dbm(enum gsm_band band, uint8_t lvl) -{ - lvl &= 0x1f; - - switch (band) { - case GSM_BAND_450: - case GSM_BAND_480: - case GSM_BAND_750: - case GSM_BAND_900: - case GSM_BAND_810: - case GSM_BAND_850: - if (lvl < 2) - return 39; - else if (lvl < 20) - return 39 - ((lvl - 2) * 2) ; - else - return 5; - break; - case GSM_BAND_1800: - if (lvl < 16) - return 30 - (lvl * 2); - else if (lvl < 29) - return 0; - else - return 36 - ((lvl - 29) * 2); - break; - case GSM_BAND_1900: - if (lvl < 16) - return 30 - (lvl * 2); - else if (lvl < 30) - return -EINVAL; - else - return 33 - (lvl - 30); - break; - } - return -EINVAL; -} - -/* According to TS 08.05 Chapter 8.1.4 */ -int rxlev2dbm(uint8_t rxlev) -{ - if (rxlev > 63) - rxlev = 63; - - return -110 + rxlev; -} - -/* According to TS 08.05 Chapter 8.1.4 */ -uint8_t dbm2rxlev(int dbm) -{ - int rxlev = dbm + 110; - - if (rxlev > 63) - rxlev = 63; - else if (rxlev < 0) - rxlev = 0; - - return rxlev; -} - -const char *gsm_band_name(enum gsm_band band) -{ - switch (band) { - case GSM_BAND_450: - return "GSM450"; - case GSM_BAND_480: - return "GSM480"; - case GSM_BAND_750: - return "GSM750"; - case GSM_BAND_810: - return "GSM810"; - case GSM_BAND_850: - return "GSM850"; - case GSM_BAND_900: - return "GSM900"; - case GSM_BAND_1800: - return "DCS1800"; - case GSM_BAND_1900: - return "PCS1900"; - } - return "invalid"; -} - -enum gsm_band gsm_band_parse(const char* mhz) -{ - while (*mhz && !isdigit(*mhz)) - mhz++; - - if (*mhz == '\0') - return -EINVAL; - - switch (strtol(mhz, NULL, 10)) { - case 450: - return GSM_BAND_450; - case 480: - return GSM_BAND_480; - case 750: - return GSM_BAND_750; - case 810: - return GSM_BAND_810; - case 850: - return GSM_BAND_850; - case 900: - return GSM_BAND_900; - case 1800: - return GSM_BAND_1800; - case 1900: - return GSM_BAND_1900; - default: - return -EINVAL; - } -} - - -#ifdef HAVE_EXECINFO_H -#include -void generate_backtrace() -{ - int i, nptrs; - void *buffer[100]; - char **strings; - - nptrs = backtrace(buffer, ARRAY_SIZE(buffer)); - printf("backtrace() returned %d addresses\n", nptrs); - - strings = backtrace_symbols(buffer, nptrs); - if (!strings) - return; - - for (i = 1; i < nptrs; i++) - printf("%s\n", strings[i]); - - free(strings); -} -#endif - -enum gsm_band gsm_arfcn2band(uint16_t arfcn) -{ - int is_pcs = arfcn & ARFCN_PCS; - - arfcn &= ~ARFCN_FLAG_MASK; - - if (is_pcs) - return GSM_BAND_1900; - else if (arfcn <= 124) - return GSM_BAND_900; - else if (arfcn >= 955 && arfcn <= 1023) - return GSM_BAND_900; - else if (arfcn >= 128 && arfcn <= 251) - return GSM_BAND_850; - else if (arfcn >= 512 && arfcn <= 885) - return GSM_BAND_1800; - else if (arfcn >= 259 && arfcn <= 293) - return GSM_BAND_450; - else if (arfcn >= 306 && arfcn <= 340) - return GSM_BAND_480; - else if (arfcn >= 350 && arfcn <= 425) - return GSM_BAND_810; - else if (arfcn >= 438 && arfcn <= 511) - return GSM_BAND_750; - else - return GSM_BAND_1800; -} - -/* Convert an ARFCN to the frequency in MHz * 10 */ -uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink) -{ - uint16_t freq10_ul; - uint16_t freq10_dl; - int is_pcs = arfcn & ARFCN_PCS; - - arfcn &= ~ARFCN_FLAG_MASK; - - if (is_pcs) { - /* DCS 1900 */ - arfcn &= ~ARFCN_PCS; - freq10_ul = 18502 + 2 * (arfcn-512); - freq10_dl = freq10_ul + 800; - } else if (arfcn <= 124) { - /* Primary GSM + ARFCN 0 of E-GSM */ - freq10_ul = 8900 + 2 * arfcn; - freq10_dl = freq10_ul + 450; - } else if (arfcn >= 955 && arfcn <= 1023) { - /* E-GSM and R-GSM */ - freq10_ul = 8900 + 2 * (arfcn - 1024); - freq10_dl = freq10_ul + 450; - } else if (arfcn >= 128 && arfcn <= 251) { - /* GSM 850 */ - freq10_ul = 8242 + 2 * (arfcn - 128); - freq10_dl = freq10_ul + 450; - } else if (arfcn >= 512 && arfcn <= 885) { - /* DCS 1800 */ - freq10_ul = 17102 + 2 * (arfcn - 512); - freq10_dl = freq10_ul + 950; - } else if (arfcn >= 259 && arfcn <= 293) { - /* GSM 450 */ - freq10_ul = 4506 + 2 * (arfcn - 259); - freq10_dl = freq10_ul + 100; - } else if (arfcn >= 306 && arfcn <= 340) { - /* GSM 480 */ - freq10_ul = 4790 + 2 * (arfcn - 306); - freq10_dl = freq10_ul + 100; - } else if (arfcn >= 350 && arfcn <= 425) { - /* GSM 810 */ - freq10_ul = 8060 + 2 * (arfcn - 350); - freq10_dl = freq10_ul + 450; - } else if (arfcn >= 438 && arfcn <= 511) { - /* GSM 750 */ - freq10_ul = 7472 + 2 * (arfcn - 438); - freq10_dl = freq10_ul + 300; - } else - return 0xffff; - - if (uplink) - return freq10_ul; - else - return freq10_dl; -} - -void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn) -{ - time->fn = fn; - time->t1 = time->fn / (26*51); - time->t2 = time->fn % 26; - time->t3 = time->fn % 51; - time->tc = (time->fn / 51) % 8; -} - -uint32_t gsm_gsmtime2fn(struct gsm_time *time) -{ - /* TS 05.02 Chapter 4.3.3 TDMA frame number */ - return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1)); -} - -/* TS 03.03 Chapter 2.6 */ -int gprs_tlli_type(uint32_t tlli) -{ - if ((tlli & 0xc0000000) == 0xc0000000) - return TLLI_LOCAL; - else if ((tlli & 0xc0000000) == 0x80000000) - return TLLI_FOREIGN; - else if ((tlli & 0xf8000000) == 0x78000000) - return TLLI_RANDOM; - else if ((tlli & 0xf8000000) == 0x70000000) - return TLLI_AUXILIARY; - - return TLLI_RESERVED; -} - -uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type) -{ - uint32_t tlli; - switch (type) { - case TLLI_LOCAL: - tlli = p_tmsi | 0xc0000000; - break; - case TLLI_FOREIGN: - tlli = (p_tmsi & 0x3fffffff) | 0x80000000; - break; - default: - tlli = 0; - break; - } - return tlli; -} diff --git a/src/panic.c b/src/panic.c index 5fb7b565..21e8fd56 100644 --- a/src/panic.c +++ b/src/panic.c @@ -22,6 +22,7 @@ #include #include +#include #include "../config.h" diff --git a/src/rsl.c b/src/rsl.c deleted file mode 100644 index 3bfeffb9..00000000 --- a/src/rsl.c +++ /dev/null @@ -1,371 +0,0 @@ -/* GSM Radio Signalling Link messages on the A-bis interface - * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */ - -/* (C) 2008-2010 by Harald Welte - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include - -#include -#include - -#define RSL_ALLOC_SIZE 200 -#define RSL_ALLOC_HEADROOM 56 - -void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type) -{ - dh->c.msg_discr = ABIS_RSL_MDISC_RLL; - dh->c.msg_type = msg_type; - dh->ie_chan = RSL_IE_CHAN_NR; - dh->ie_link_id = RSL_IE_LINK_IDENT; -} - -void rsl_init_cchan_hdr(struct abis_rsl_cchan_hdr *ch, uint8_t msg_type) -{ - ch->c.msg_discr = ABIS_RSL_MDISC_COM_CHAN; - ch->c.msg_type = msg_type; - ch->ie_chan = RSL_IE_CHAN_NR; -} - -const struct tlv_definition rsl_att_tlvdef = { - .def = { - [RSL_IE_CHAN_NR] = { TLV_TYPE_TV }, - [RSL_IE_LINK_IDENT] = { TLV_TYPE_TV }, - [RSL_IE_ACT_TYPE] = { TLV_TYPE_TV }, - [RSL_IE_BS_POWER] = { TLV_TYPE_TV }, - [RSL_IE_CHAN_IDENT] = { TLV_TYPE_TLV }, - [RSL_IE_CHAN_MODE] = { TLV_TYPE_TLV }, - [RSL_IE_ENCR_INFO] = { TLV_TYPE_TLV }, - [RSL_IE_FRAME_NUMBER] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_HANDO_REF] = { TLV_TYPE_TV }, - [RSL_IE_L1_INFO] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_L3_INFO] = { TLV_TYPE_TL16V }, - [RSL_IE_MS_IDENTITY] = { TLV_TYPE_TLV }, - [RSL_IE_MS_POWER] = { TLV_TYPE_TV }, - [RSL_IE_PAGING_GROUP] = { TLV_TYPE_TV }, - [RSL_IE_PAGING_LOAD] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_PYHS_CONTEXT] = { TLV_TYPE_TLV }, - [RSL_IE_ACCESS_DELAY] = { TLV_TYPE_TV }, - [RSL_IE_RACH_LOAD] = { TLV_TYPE_TLV }, - [RSL_IE_REQ_REFERENCE] = { TLV_TYPE_FIXED, 3 }, - [RSL_IE_RELEASE_MODE] = { TLV_TYPE_TV }, - [RSL_IE_RESOURCE_INFO] = { TLV_TYPE_TLV }, - [RSL_IE_RLM_CAUSE] = { TLV_TYPE_TLV }, - [RSL_IE_STARTNG_TIME] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_TIMING_ADVANCE] = { TLV_TYPE_TV }, - [RSL_IE_UPLINK_MEAS] = { TLV_TYPE_TLV }, - [RSL_IE_CAUSE] = { TLV_TYPE_TLV }, - [RSL_IE_MEAS_RES_NR] = { TLV_TYPE_TV }, - [RSL_IE_MSG_ID] = { TLV_TYPE_TV }, - [RSL_IE_SYSINFO_TYPE] = { TLV_TYPE_TV }, - [RSL_IE_MS_POWER_PARAM] = { TLV_TYPE_TLV }, - [RSL_IE_BS_POWER_PARAM] = { TLV_TYPE_TLV }, - [RSL_IE_PREPROC_PARAM] = { TLV_TYPE_TLV }, - [RSL_IE_PREPROC_MEAS] = { TLV_TYPE_TLV }, - [RSL_IE_IMM_ASS_INFO] = { TLV_TYPE_TLV }, - [RSL_IE_SMSCB_INFO] = { TLV_TYPE_FIXED, 23 }, - [RSL_IE_MS_TIMING_OFFSET] = { TLV_TYPE_TV }, - [RSL_IE_ERR_MSG] = { TLV_TYPE_TLV }, - [RSL_IE_FULL_BCCH_INFO] = { TLV_TYPE_TLV }, - [RSL_IE_CHAN_NEEDED] = { TLV_TYPE_TV }, - [RSL_IE_CB_CMD_TYPE] = { TLV_TYPE_TV }, - [RSL_IE_SMSCB_MSG] = { TLV_TYPE_TLV }, - [RSL_IE_FULL_IMM_ASS_INFO] = { TLV_TYPE_TLV }, - [RSL_IE_SACCH_INFO] = { TLV_TYPE_TLV }, - [RSL_IE_CBCH_LOAD_INFO] = { TLV_TYPE_TV }, - [RSL_IE_SMSCB_CHAN_INDICATOR] = { TLV_TYPE_TV }, - [RSL_IE_GROUP_CALL_REF] = { TLV_TYPE_TLV }, - [RSL_IE_CHAN_DESC] = { TLV_TYPE_TLV }, - [RSL_IE_NCH_DRX_INFO] = { TLV_TYPE_TLV }, - [RSL_IE_CMD_INDICATOR] = { TLV_TYPE_TLV }, - [RSL_IE_EMLPP_PRIO] = { TLV_TYPE_TV }, - [RSL_IE_UIC] = { TLV_TYPE_TLV }, - [RSL_IE_MAIN_CHAN_REF] = { TLV_TYPE_TV }, - [RSL_IE_MR_CONFIG] = { TLV_TYPE_TLV }, - [RSL_IE_MR_CONTROL] = { TLV_TYPE_TV }, - [RSL_IE_SUP_CODEC_TYPES] = { TLV_TYPE_TLV }, - [RSL_IE_CODEC_CONFIG] = { TLV_TYPE_TLV }, - [RSL_IE_RTD] = { TLV_TYPE_TV }, - [RSL_IE_TFO_STATUS] = { TLV_TYPE_TV }, - [RSL_IE_LLP_APDU] = { TLV_TYPE_TLV }, - [RSL_IE_SIEMENS_MRPCI] = { TLV_TYPE_TV }, - [RSL_IE_IPAC_PROXY_UDP] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_IPAC_BSCMPL_TOUT] = { TLV_TYPE_TV }, - [RSL_IE_IPAC_REMOTE_IP] = { TLV_TYPE_FIXED, 4 }, - [RSL_IE_IPAC_REMOTE_PORT] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_IPAC_RTP_PAYLOAD] = { TLV_TYPE_TV }, - [RSL_IE_IPAC_LOCAL_PORT] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_IPAC_SPEECH_MODE] = { TLV_TYPE_TV }, - [RSL_IE_IPAC_LOCAL_IP] = { TLV_TYPE_FIXED, 4 }, - [RSL_IE_IPAC_CONN_ID] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_IPAC_RTP_CSD_FMT] = { TLV_TYPE_TV }, - [RSL_IE_IPAC_RTP_JIT_BUF] = { TLV_TYPE_FIXED, 2 }, - [RSL_IE_IPAC_RTP_COMPR] = { TLV_TYPE_TV }, - [RSL_IE_IPAC_RTP_PAYLOAD2] = { TLV_TYPE_TV }, - [RSL_IE_IPAC_RTP_MPLEX] = { TLV_TYPE_FIXED, 8 }, - [RSL_IE_IPAC_RTP_MPLEX_ID] = { TLV_TYPE_TV }, - }, -}; - -/* encode channel number as per Section 9.3.1 */ -uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot) -{ - uint8_t ret; - - ret = (timeslot & 0x07) | type; - - switch (type) { - case RSL_CHAN_Lm_ACCHs: - subch &= 0x01; - break; - case RSL_CHAN_SDCCH4_ACCH: - subch &= 0x03; - break; - case RSL_CHAN_SDCCH8_ACCH: - subch &= 0x07; - break; - default: - /* no subchannels allowed */ - subch = 0x00; - break; - } - ret |= (subch << 3); - - return ret; -} - -int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot) -{ - *timeslot = chan_nr & 0x7; - - if ((chan_nr & 0xf8) == RSL_CHAN_Bm_ACCHs) { - *type = RSL_CHAN_Bm_ACCHs; - *subch = 0; - } else if ((chan_nr & 0xf0) == RSL_CHAN_Lm_ACCHs) { - *type = RSL_CHAN_Lm_ACCHs; - *subch = (chan_nr >> 3) & 0x1; - } else if ((chan_nr & 0xe0) == RSL_CHAN_SDCCH4_ACCH) { - *type = RSL_CHAN_SDCCH4_ACCH; - *subch = (chan_nr >> 3) & 0x3; - } else if ((chan_nr & 0xc0) == RSL_CHAN_SDCCH8_ACCH) { - *type = RSL_CHAN_SDCCH8_ACCH; - *subch = (chan_nr >> 3) & 0x7; - } else if ((chan_nr & 0xf8) == RSL_CHAN_BCCH) { - *type = RSL_CHAN_BCCH; - *subch = 0; - } else if ((chan_nr & 0xf8) == RSL_CHAN_RACH) { - *type = RSL_CHAN_RACH; - *subch = 0; - } else if ((chan_nr & 0xf8) == RSL_CHAN_PCH_AGCH) { - *type = RSL_CHAN_PCH_AGCH; - *subch = 0; - } else - return -EINVAL; - - return 0; -} - -const char *rsl_chan_nr_str(uint8_t chan_nr) -{ - static char str[20]; - int ts = chan_nr & 7; - uint8_t cbits = chan_nr >> 3; - - if (cbits == 0x01) - sprintf(str, "TCH/F on TS%d", ts); - else if ((cbits & 0x1e) == 0x02) - sprintf(str, "TCH/H(%u) on TS%d", cbits & 0x01, ts); - else if ((cbits & 0x1c) == 0x04) - sprintf(str, "SDCCH/4(%u) on TS%d", cbits & 0x03, ts); - else if ((cbits & 0x18) == 0x08) - sprintf(str, "SDCCH/8(%u) on TS%d", cbits & 0x07, ts); - else if (cbits == 0x10) - sprintf(str, "BCCH on TS%d", ts); - else if (cbits == 0x11) - sprintf(str, "RACH on TS%d", ts); - else if (cbits == 0x12) - sprintf(str, "PCH/AGCH on TS%d", ts); - else - sprintf(str, "UNKNOWN on TS%d", ts); - - return str; -} - -static const struct value_string rsl_err_vals[] = { - { RSL_ERR_RADIO_IF_FAIL, "Radio Interface Failure" }, - { RSL_ERR_RADIO_LINK_FAIL, "Radio Link Failure" }, - { RSL_ERR_HANDOVER_ACC_FAIL, "Handover Access Failure" }, - { RSL_ERR_TALKER_ACC_FAIL, "Talker Access Failure" }, - { RSL_ERR_OM_INTERVENTION, "O&M Intervention" }, - { RSL_ERR_NORMAL_UNSPEC, "Normal event, unspecified" }, - { RSL_ERR_T_MSRFPCI_EXP, "Siemens: T_MSRFPCI Expired" }, - { RSL_ERR_EQUIPMENT_FAIL, "Equipment Failure" }, - { RSL_ERR_RR_UNAVAIL, "Radio Resource not available" }, - { RSL_ERR_TERR_CH_FAIL, "Terrestrial Channel Failure" }, - { RSL_ERR_CCCH_OVERLOAD, "CCCH Overload" }, - { RSL_ERR_ACCH_OVERLOAD, "ACCH Overload" }, - { RSL_ERR_PROCESSOR_OVERLOAD, "Processor Overload" }, - { RSL_ERR_RES_UNAVAIL, "Resource not available, unspecified" }, - { RSL_ERR_TRANSC_UNAVAIL, "Transcoding not available" }, - { RSL_ERR_SERV_OPT_UNAVAIL, "Service or Option not available" }, - { RSL_ERR_ENCR_UNIMPL, "Encryption algorithm not implemented" }, - { RSL_ERR_SERV_OPT_UNIMPL, "Service or Option not implemented" }, - { RSL_ERR_RCH_ALR_ACTV_ALLOC, "Radio channel already activated" }, - { RSL_ERR_INVALID_MESSAGE, "Invalid Message, unspecified" }, - { RSL_ERR_MSG_DISCR, "Message Discriminator Error" }, - { RSL_ERR_MSG_TYPE, "Message Type Error" }, - { RSL_ERR_MSG_SEQ, "Message Sequence Error" }, - { RSL_ERR_IE_ERROR, "General IE error" }, - { RSL_ERR_MAND_IE_ERROR, "Mandatory IE error" }, - { RSL_ERR_OPT_IE_ERROR, "Optional IE error" }, - { RSL_ERR_IE_NONEXIST, "IE non-existent" }, - { RSL_ERR_IE_LENGTH, "IE length error" }, - { RSL_ERR_IE_CONTENT, "IE content error" }, - { RSL_ERR_PROTO, "Protocol error, unspecified" }, - { RSL_ERR_INTERWORKING, "Interworking error, unspecified" }, - { 0, NULL } -}; - -const char *rsl_err_name(uint8_t err) -{ - return get_value_string(rsl_err_vals, err); -} - -static const struct value_string rsl_rlm_cause_strs[] = { - { RLL_CAUSE_T200_EXPIRED, "Timer T200 expired (N200+1) times" }, - { RLL_CAUSE_REEST_REQ, "Re-establishment request" }, - { RLL_CAUSE_UNSOL_UA_RESP, "Unsolicited UA response" }, - { RLL_CAUSE_UNSOL_DM_RESP, "Unsolicited DM response" }, - { RLL_CAUSE_UNSOL_DM_RESP_MF, "Unsolicited DM response, multiple frame" }, - { RLL_CAUSE_UNSOL_SPRV_RESP, "Unsolicited supervisory response" }, - { RLL_CAUSE_SEQ_ERR, "Sequence Error" }, - { RLL_CAUSE_UFRM_INC_PARAM, "U-Frame with incorrect parameters" }, - { RLL_CAUSE_SFRM_INC_PARAM, "S-Frame with incorrect parameters" }, - { RLL_CAUSE_IFRM_INC_MBITS, "I-Frame with incorrect use of M bit" }, - { RLL_CAUSE_IFRM_INC_LEN, "I-Frame with incorrect length" }, - { RLL_CAUSE_FRM_UNIMPL, "Fraeme not implemented" }, - { RLL_CAUSE_SABM_MF, "SABM command, multiple frame established state" }, - { RLL_CAUSE_SABM_INFO_NOTALL, "SABM frame with information not allowed in this state" }, - { 0, NULL }, -}; - -const char *rsl_rlm_cause_name(uint8_t err) -{ - return get_value_string(rsl_rlm_cause_strs, err); -} - -/* Section 3.3.2.3 TS 05.02. I think this looks like a table */ -int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf) -{ - switch (ccch_conf) { - case RSL_BCCH_CCCH_CONF_1_NC: - return 1; - case RSL_BCCH_CCCH_CONF_1_C: - return 1; - case RSL_BCCH_CCCH_CONF_2_NC: - return 2; - case RSL_BCCH_CCCH_CONF_3_NC: - return 3; - case RSL_BCCH_CCCH_CONF_4_NC: - return 4; - default: - return -1; - } -} - -/* Section 3.3.2.3 TS 05.02 */ -int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf) -{ - switch (ccch_conf) { - case RSL_BCCH_CCCH_CONF_1_NC: - return 0; - case RSL_BCCH_CCCH_CONF_1_C: - return 1; - case RSL_BCCH_CCCH_CONF_2_NC: - return 0; - case RSL_BCCH_CCCH_CONF_3_NC: - return 0; - case RSL_BCCH_CCCH_CONF_4_NC: - return 0; - default: - return -1; - } -} - -/* Push a RSL RLL header */ -void rsl_rll_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr, - uint8_t link_id, int transparent) -{ - struct abis_rsl_rll_hdr *rh; - - rh = (struct abis_rsl_rll_hdr *) msgb_push(msg, sizeof(*rh)); - rsl_init_rll_hdr(rh, msg_type); - if (transparent) - rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP; - rh->chan_nr = chan_nr; - rh->link_id = link_id; - - /* set the l2 header pointer */ - msg->l2h = (uint8_t *)rh; -} - -/* Push a RSL RLL header with L3_INFO IE */ -void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr, - uint8_t link_id, int transparent) -{ - uint8_t l3_len = msg->tail - (uint8_t *)msgb_l3(msg); - - /* construct a RSLms RLL message (DATA INDICATION, UNIT DATA - * INDICATION) and send it off via RSLms */ - - /* Push the L3 IE tag and lengh */ - msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len); - - /* Then push the RSL header */ - rsl_rll_push_hdr(msg, msg_type, chan_nr, link_id, transparent); -} - -struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr, - uint8_t link_id, int transparent) -{ - struct abis_rsl_rll_hdr *rh; - struct msgb *msg; - - msg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM, - RSL_ALLOC_HEADROOM, "rsl_rll_simple"); - - if (!msg) - return NULL; - - /* put the RSL header */ - rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh)); - rsl_init_rll_hdr(rh, msg_type); - if (transparent) - rh->c.msg_discr |= ABIS_RSL_MDISC_TRANSP; - rh->chan_nr = chan_nr; - rh->link_id = link_id; - - /* set the l2 header pointer */ - msg->l2h = (uint8_t *)rh; - - return msg; -} diff --git a/src/rxlev_stat.c b/src/rxlev_stat.c deleted file mode 100644 index b474aaa8..00000000 --- a/src/rxlev_stat.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Rx Level statistics */ - -/* (C) 2010 by Harald Welte - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val) -{ - unsigned int i; - - for (i = n; i < bv->data_len*8; i++) { - if (bitvec_get_bit_pos(bv, i) == val) - return i; - } - - return -1; -} - -void rxlev_stat_input(struct rxlev_stats *st, uint16_t arfcn, uint8_t rxlev) -{ - struct bitvec bv; - - if (rxlev >= NUM_RXLEVS) - rxlev = NUM_RXLEVS-1; - - bv.data_len = NUM_ARFCNS/8; - bv.data = st->rxlev_buckets[rxlev]; - - bitvec_set_bit_pos(&bv, arfcn, ONE); -} - -/* get the next ARFCN that has the specified Rxlev */ -int16_t rxlev_stat_get_next(const struct rxlev_stats *st, uint8_t rxlev, int16_t arfcn) -{ - struct bitvec bv; - - if (rxlev >= NUM_RXLEVS) - rxlev = NUM_RXLEVS-1; - - bv.data_len = NUM_ARFCNS/8; - - if (arfcn < 0) - arfcn = -1; - - bv.data = (uint8_t *) st->rxlev_buckets[rxlev]; - - return bitvec_find_bit_pos(&bv, arfcn+1, ONE); -} - -void rxlev_stat_reset(struct rxlev_stats *st) -{ - memset(st, 0, sizeof(*st)); -} - -void rxlev_stat_dump(const struct rxlev_stats *st) -{ - int i; - - for (i = NUM_RXLEVS-1; i >= 0; i--) { - int16_t arfcn = -1; - - printf("ARFCN with RxLev %u: ", i); - while ((arfcn = rxlev_stat_get_next(st, i, arfcn)) >= 0) { - printf("%u ", arfcn); - } - printf("\n"); - } -} diff --git a/src/tlv_parser.c b/src/tlv_parser.c deleted file mode 100644 index bbef7a9a..00000000 --- a/src/tlv_parser.c +++ /dev/null @@ -1,179 +0,0 @@ -#include -#include -#include -#include - -struct tlv_definition tvlv_att_def; - -int tlv_dump(struct tlv_parsed *dec) -{ - int i; - - for (i = 0; i <= 0xff; i++) { - if (!dec->lv[i].val) - continue; - printf("T=%02x L=%d\n", i, dec->lv[i].len); - } - return 0; -} - -/* o_tag: output: tag found - * o_len: output: length of the data - * o_val: output: pointer to the data - * def: input: a structure defining the valid TLV tags / configurations - * buf: input: the input data buffer to be parsed - * buf_len: input: the length of the input data buffer - * - * Also, returns the number of bytes consumed by the TLV entry - */ -int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val, - const struct tlv_definition *def, - const uint8_t *buf, int buf_len) -{ - uint8_t tag; - int len; - - tag = *buf; - *o_tag = tag; - - /* single octet TV IE */ - if (def->def[tag & 0xf0].type == TLV_TYPE_SINGLE_TV) { - *o_tag = tag & 0xf0; - *o_val = buf; - *o_len = 1; - return 1; - } - - /* FIXME: use tables for knwon IEI */ - switch (def->def[tag].type) { - case TLV_TYPE_T: - /* GSM TS 04.07 11.2.4: Type 1 TV or Type 2 T */ - *o_val = buf; - *o_len = 0; - len = 1; - break; - case TLV_TYPE_TV: - *o_val = buf+1; - *o_len = 1; - len = 2; - break; - case TLV_TYPE_FIXED: - *o_val = buf+1; - *o_len = def->def[tag].fixed_len; - len = def->def[tag].fixed_len + 1; - break; - case TLV_TYPE_TLV: - /* GSM TS 04.07 11.2.4: Type 4 TLV */ - if (buf + 1 > buf + buf_len) - return -1; - *o_val = buf+2; - *o_len = *(buf+1); - len = *o_len + 2; - if (len > buf_len) - return -2; - break; - case TLV_TYPE_TvLV: - if (*(buf+1) & 0x80) { - /* like TLV, but without highest bit of len */ - if (buf + 1 > buf + buf_len) - return -1; - *o_val = buf+2; - *o_len = *(buf+1) & 0x7f; - len = *o_len + 2; - if (len > buf_len) - return -2; - break; - } - /* like TL16V, fallthrough */ - case TLV_TYPE_TL16V: - if (2 > buf_len) - return -1; - *o_val = buf+3; - *o_len = *(buf+1) << 8 | *(buf+2); - len = *o_len + 3; - if (len > buf_len) - return -2; - break; - default: - return -3; - } - - return len; -} - -/* dec: output: a caller-allocated pointer to a struct tlv_parsed, - * def: input: a structure defining the valid TLV tags / configurations - * buf: input: the input data buffer to be parsed - * buf_len: input: the length of the input data buffer - * lv_tag: input: an initial LV tag at the start of the buffer - * lv_tag2: input: a second initial LV tag following lv_tag - */ -int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def, - const uint8_t *buf, int buf_len, uint8_t lv_tag, - uint8_t lv_tag2) -{ - int ofs = 0, num_parsed = 0; - uint16_t len; - - memset(dec, 0, sizeof(*dec)); - - if (lv_tag) { - if (ofs > buf_len) - return -1; - dec->lv[lv_tag].val = &buf[ofs+1]; - dec->lv[lv_tag].len = buf[ofs]; - len = dec->lv[lv_tag].len + 1; - if (ofs + len > buf_len) - return -2; - num_parsed++; - ofs += len; - } - if (lv_tag2) { - if (ofs > buf_len) - return -1; - dec->lv[lv_tag2].val = &buf[ofs+1]; - dec->lv[lv_tag2].len = buf[ofs]; - len = dec->lv[lv_tag2].len + 1; - if (ofs + len > buf_len) - return -2; - num_parsed++; - ofs += len; - } - - while (ofs < buf_len) { - int rv; - uint8_t tag; - const uint8_t *val; - - rv = tlv_parse_one(&tag, &len, &val, def, - &buf[ofs], buf_len-ofs); - if (rv < 0) - return rv; - dec->lv[tag].val = val; - dec->lv[tag].len = len; - ofs += rv; - num_parsed++; - } - //tlv_dump(dec); - return num_parsed; -} - -/* take a master (src) tlvdev and fill up all empty slots in 'dst' */ -void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dst->def); i++) { - if (src->def[i].type == TLV_TYPE_NONE) - continue; - if (dst->def[i].type == TLV_TYPE_NONE) - dst->def[i] = src->def[i]; - } -} - -static __attribute__((constructor)) void on_dso_load_tlv(void) -{ - int i; - for (i = 0; i < ARRAY_SIZE(tvlv_att_def.def); i++) - tvlv_att_def.def[i].type = TLV_TYPE_TvLV; -} diff --git a/tests/sms/Makefile.am b/tests/sms/Makefile.am index a8f1ff6a..fa4e387f 100644 --- a/tests/sms/Makefile.am +++ b/tests/sms/Makefile.am @@ -2,4 +2,4 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include noinst_PROGRAMS = sms_test sms_test_SOURCES = sms_test.c -sms_test_LDADD = $(top_builddir)/src/libosmocore.la +sms_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la diff --git a/tests/smscb/Makefile.am b/tests/smscb/Makefile.am index 1d0e5384..9a6fb4fd 100644 --- a/tests/smscb/Makefile.am +++ b/tests/smscb/Makefile.am @@ -2,4 +2,4 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include noinst_PROGRAMS = smscb_test smscb_test_SOURCES = smscb_test.c -smscb_test_LDADD = $(top_builddir)/src/libosmocore.la +smscb_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la diff --git a/tests/ussd/Makefile.am b/tests/ussd/Makefile.am index d29506cc..ef9aa492 100644 --- a/tests/ussd/Makefile.am +++ b/tests/ussd/Makefile.am @@ -2,4 +2,4 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include noinst_PROGRAMS = ussd_test ussd_test_SOURCES = ussd_test.c -ussd_test_LDADD = $(top_builddir)/src/libosmocore.la +ussd_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la -- cgit v1.2.3 From 834193484439acd6056a891e9b2df5992a370088 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 22 Mar 2011 16:36:13 +0100 Subject: include: reorganize headers file to include/osmocom/[gsm|core] This patch moves all GSM-specific definitions to include/osmocom/gsm. Moreover, the headers in include/osmocore/ have been moved to include/osmocom/core. This has been proposed by Harald Welte and Sylvain Munaunt. Tested with `make distcheck'. Signed-off-by: Pablo Neira Ayuso --- configure.in | 5 +- include/Makefile.am | 2 +- include/osmocom/Makefile.am | 4 +- include/osmocom/core/Makefile.am | 12 + include/osmocom/core/backtrace.h | 6 + include/osmocom/core/bits.h | 45 ++ include/osmocom/core/bitvec.h | 75 ++ include/osmocom/core/crc16.h | 34 + include/osmocom/core/gsmtap.h | 89 +++ include/osmocom/core/gsmtap_util.h | 21 + include/osmocom/core/linuxlist.h | 360 +++++++++ include/osmocom/core/logging.h | 154 ++++ include/osmocom/core/msgb.h | 197 +++++ include/osmocom/core/msgfile.h | 49 ++ include/osmocom/core/panic.h | 11 + include/osmocom/core/plugin.h | 6 + include/osmocom/core/process.h | 6 + include/osmocom/core/rate_ctr.h | 81 ++ include/osmocom/core/select.h | 22 + include/osmocom/core/signal.h | 15 + include/osmocom/core/statistics.h | 31 + include/osmocom/core/talloc.h | 192 +++++ include/osmocom/core/timer.h | 72 ++ include/osmocom/core/utils.h | 30 + include/osmocom/core/write_queue.h | 46 ++ include/osmocom/crypt/gprs_cipher.h | 2 +- include/osmocom/gsm/Makefile.am | 6 + include/osmocom/gsm/comp128.h | 22 + include/osmocom/gsm/gsm0480.h | 26 + include/osmocom/gsm/gsm0808.h | 46 ++ include/osmocom/gsm/gsm48.h | 36 + include/osmocom/gsm/gsm48_ie.h | 117 +++ include/osmocom/gsm/gsm_utils.h | 117 +++ include/osmocom/gsm/mncc.h | 71 ++ include/osmocom/gsm/protocol/Makefile.am | 6 + include/osmocom/gsm/protocol/gsm_03_41.h | 51 ++ include/osmocom/gsm/protocol/gsm_04_08.h | 1262 ++++++++++++++++++++++++++++++ include/osmocom/gsm/protocol/gsm_04_11.h | 188 +++++ include/osmocom/gsm/protocol/gsm_04_12.h | 31 + include/osmocom/gsm/protocol/gsm_04_80.h | 126 +++ include/osmocom/gsm/protocol/gsm_08_08.h | 303 +++++++ include/osmocom/gsm/protocol/gsm_08_58.h | 546 +++++++++++++ include/osmocom/gsm/protocol/gsm_12_21.h | 713 +++++++++++++++++ include/osmocom/gsm/rsl.h | 41 + include/osmocom/gsm/rxlev_stat.h | 22 + include/osmocom/gsm/tlv.h | 260 ++++++ include/osmocom/vty/telnet_interface.h | 4 +- include/osmocore/Makefile.am | 14 - include/osmocore/backtrace.h | 6 - include/osmocore/bits.h | 45 -- include/osmocore/bitvec.h | 75 -- include/osmocore/comp128.h | 22 - include/osmocore/crc16.h | 34 - include/osmocore/gsm0480.h | 26 - include/osmocore/gsm0808.h | 46 -- include/osmocore/gsm48.h | 36 - include/osmocore/gsm48_ie.h | 117 --- include/osmocore/gsm_utils.h | 117 --- include/osmocore/gsmtap.h | 89 --- include/osmocore/gsmtap_util.h | 21 - include/osmocore/linuxlist.h | 360 --------- include/osmocore/logging.h | 154 ---- include/osmocore/mncc.h | 71 -- include/osmocore/msgb.h | 197 ----- include/osmocore/msgfile.h | 49 -- include/osmocore/panic.h | 11 - include/osmocore/plugin.h | 6 - include/osmocore/process.h | 6 - include/osmocore/protocol/Makefile.am | 6 - include/osmocore/protocol/gsm_03_41.h | 51 -- include/osmocore/protocol/gsm_04_08.h | 1262 ------------------------------ include/osmocore/protocol/gsm_04_11.h | 188 ----- include/osmocore/protocol/gsm_04_12.h | 31 - include/osmocore/protocol/gsm_04_80.h | 126 --- include/osmocore/protocol/gsm_08_08.h | 303 ------- include/osmocore/protocol/gsm_08_58.h | 546 ------------- include/osmocore/protocol/gsm_12_21.h | 713 ----------------- include/osmocore/rate_ctr.h | 81 -- include/osmocore/rsl.h | 41 - include/osmocore/rxlev_stat.h | 22 - include/osmocore/select.h | 22 - include/osmocore/signal.h | 15 - include/osmocore/statistics.h | 31 - include/osmocore/talloc.h | 192 ----- include/osmocore/timer.h | 72 -- include/osmocore/tlv.h | 260 ------ include/osmocore/utils.h | 30 - include/osmocore/write_queue.h | 46 -- src/backtrace.c | 2 +- src/bits.c | 2 +- src/bitvec.c | 2 +- src/crc16.c | 2 +- src/gsm/gprs_cipher_core.c | 6 +- src/gsm/gsm0480.c | 10 +- src/gsm/gsm0808.c | 6 +- src/gsm/gsm48.c | 8 +- src/gsm/gsm48_ie.c | 12 +- src/gsm/gsm_utils.c | 6 +- src/gsm/rsl.c | 4 +- src/gsm/rxlev_stat.c | 4 +- src/gsm/tlv_parser.c | 4 +- src/gsmtap_util.c | 14 +- src/logging.c | 6 +- src/logging_syslog.c | 6 +- src/msgb.c | 4 +- src/msgfile.c | 4 +- src/panic.c | 6 +- src/plugin.c | 2 +- src/rate_ctr.c | 10 +- src/select.c | 6 +- src/signal.c | 6 +- src/statistics.c | 6 +- src/talloc.c | 2 +- src/timer.c | 2 +- src/utils.c | 2 +- src/vty/buffer.c | 2 +- src/vty/command.c | 2 +- src/vty/logging_vty.c | 6 +- src/vty/telnet_interface.c | 6 +- src/vty/utils.c | 8 +- src/vty/vector.c | 2 +- src/vty/vty.c | 2 +- src/write_queue.c | 2 +- tests/msgfile/msgfile_test.c | 2 +- tests/sms/sms_test.c | 6 +- tests/smscb/smscb_test.c | 2 +- tests/timer/timer_test.c | 4 +- tests/ussd/ussd_test.c | 2 +- 128 files changed, 5648 insertions(+), 5643 deletions(-) create mode 100644 include/osmocom/core/Makefile.am create mode 100644 include/osmocom/core/backtrace.h create mode 100644 include/osmocom/core/bits.h create mode 100644 include/osmocom/core/bitvec.h create mode 100644 include/osmocom/core/crc16.h create mode 100644 include/osmocom/core/gsmtap.h create mode 100644 include/osmocom/core/gsmtap_util.h create mode 100644 include/osmocom/core/linuxlist.h create mode 100644 include/osmocom/core/logging.h create mode 100644 include/osmocom/core/msgb.h create mode 100644 include/osmocom/core/msgfile.h create mode 100644 include/osmocom/core/panic.h create mode 100644 include/osmocom/core/plugin.h create mode 100644 include/osmocom/core/process.h create mode 100644 include/osmocom/core/rate_ctr.h create mode 100644 include/osmocom/core/select.h create mode 100644 include/osmocom/core/signal.h create mode 100644 include/osmocom/core/statistics.h create mode 100644 include/osmocom/core/talloc.h create mode 100644 include/osmocom/core/timer.h create mode 100644 include/osmocom/core/utils.h create mode 100644 include/osmocom/core/write_queue.h create mode 100644 include/osmocom/gsm/Makefile.am create mode 100644 include/osmocom/gsm/comp128.h create mode 100644 include/osmocom/gsm/gsm0480.h create mode 100644 include/osmocom/gsm/gsm0808.h create mode 100644 include/osmocom/gsm/gsm48.h create mode 100644 include/osmocom/gsm/gsm48_ie.h create mode 100644 include/osmocom/gsm/gsm_utils.h create mode 100644 include/osmocom/gsm/mncc.h create mode 100644 include/osmocom/gsm/protocol/Makefile.am create mode 100644 include/osmocom/gsm/protocol/gsm_03_41.h create mode 100644 include/osmocom/gsm/protocol/gsm_04_08.h create mode 100644 include/osmocom/gsm/protocol/gsm_04_11.h create mode 100644 include/osmocom/gsm/protocol/gsm_04_12.h create mode 100644 include/osmocom/gsm/protocol/gsm_04_80.h create mode 100644 include/osmocom/gsm/protocol/gsm_08_08.h create mode 100644 include/osmocom/gsm/protocol/gsm_08_58.h create mode 100644 include/osmocom/gsm/protocol/gsm_12_21.h create mode 100644 include/osmocom/gsm/rsl.h create mode 100644 include/osmocom/gsm/rxlev_stat.h create mode 100644 include/osmocom/gsm/tlv.h delete mode 100644 include/osmocore/Makefile.am delete mode 100644 include/osmocore/backtrace.h delete mode 100644 include/osmocore/bits.h delete mode 100644 include/osmocore/bitvec.h delete mode 100644 include/osmocore/comp128.h delete mode 100644 include/osmocore/crc16.h delete mode 100644 include/osmocore/gsm0480.h delete mode 100644 include/osmocore/gsm0808.h delete mode 100644 include/osmocore/gsm48.h delete mode 100644 include/osmocore/gsm48_ie.h delete mode 100644 include/osmocore/gsm_utils.h delete mode 100644 include/osmocore/gsmtap.h delete mode 100644 include/osmocore/gsmtap_util.h delete mode 100644 include/osmocore/linuxlist.h delete mode 100644 include/osmocore/logging.h delete mode 100644 include/osmocore/mncc.h delete mode 100644 include/osmocore/msgb.h delete mode 100644 include/osmocore/msgfile.h delete mode 100644 include/osmocore/panic.h delete mode 100644 include/osmocore/plugin.h delete mode 100644 include/osmocore/process.h delete mode 100644 include/osmocore/protocol/Makefile.am delete mode 100644 include/osmocore/protocol/gsm_03_41.h delete mode 100644 include/osmocore/protocol/gsm_04_08.h delete mode 100644 include/osmocore/protocol/gsm_04_11.h delete mode 100644 include/osmocore/protocol/gsm_04_12.h delete mode 100644 include/osmocore/protocol/gsm_04_80.h delete mode 100644 include/osmocore/protocol/gsm_08_08.h delete mode 100644 include/osmocore/protocol/gsm_08_58.h delete mode 100644 include/osmocore/protocol/gsm_12_21.h delete mode 100644 include/osmocore/rate_ctr.h delete mode 100644 include/osmocore/rsl.h delete mode 100644 include/osmocore/rxlev_stat.h delete mode 100644 include/osmocore/select.h delete mode 100644 include/osmocore/signal.h delete mode 100644 include/osmocore/statistics.h delete mode 100644 include/osmocore/talloc.h delete mode 100644 include/osmocore/timer.h delete mode 100644 include/osmocore/tlv.h delete mode 100644 include/osmocore/utils.h delete mode 100644 include/osmocore/write_queue.h diff --git a/configure.in b/configure.in index b572bf4c..ead18f07 100644 --- a/configure.in +++ b/configure.in @@ -106,8 +106,9 @@ AC_OUTPUT( include/osmocom/vty/Makefile include/osmocom/codec/Makefile include/osmocom/crypt/Makefile - include/osmocore/Makefile - include/osmocore/protocol/Makefile + include/osmocom/gsm/Makefile + include/osmocom/gsm/protocol/Makefile + include/osmocom/core/Makefile include/Makefile src/Makefile src/vty/Makefile diff --git a/include/Makefile.am b/include/Makefile.am index 185c6968..3578a80e 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1 +1 @@ -SUBDIRS = osmocom osmocore +SUBDIRS = osmocom diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am index ec548fbd..21f4f2d0 100644 --- a/include/osmocom/Makefile.am +++ b/include/osmocom/Makefile.am @@ -1,5 +1,5 @@ if ENABLE_VTY -SUBDIRS = vty codec crypt +SUBDIRS = vty codec crypt gsm core else -SUBDIRS = codec crypt +SUBDIRS = codec crypt gsm core endif diff --git a/include/osmocom/core/Makefile.am b/include/osmocom/core/Makefile.am new file mode 100644 index 00000000..6109f478 --- /dev/null +++ b/include/osmocom/core/Makefile.am @@ -0,0 +1,12 @@ +osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \ + bitvec.h statistics.h utils.h \ + gsmtap.h write_queue.h \ + logging.h rate_ctr.h gsmtap_util.h \ + plugin.h crc16.h panic.h process.h msgfile.h \ + backtrace.h + +if ENABLE_TALLOC +osmocore_HEADERS += talloc.h +endif + +osmocoredir = $(includedir)/osmocom/core diff --git a/include/osmocom/core/backtrace.h b/include/osmocom/core/backtrace.h new file mode 100644 index 00000000..bbbb2c28 --- /dev/null +++ b/include/osmocom/core/backtrace.h @@ -0,0 +1,6 @@ +#ifndef _OSMO_BACKTRACE_H_ +#define _OSMO_BACKTRACE_H_ + +void generate_backtrace(); + +#endif diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h new file mode 100644 index 00000000..8d4a0789 --- /dev/null +++ b/include/osmocom/core/bits.h @@ -0,0 +1,45 @@ +#ifndef _OSMO_BITS_H +#define _OSMO_BITS_H + +#include + +typedef uint8_t sbit_t; /* soft bit (-127...127) */ +typedef uint8_t ubit_t; /* unpacked bit (0 or 1) */ +typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */ + +/* + NOTE on the endianess of pbit_t: + Bits in a pbit_t are ordered MSB first, i.e. 0x80 is the first bit. + Bit i in a pbit_t array is array[i/8] & (1<<(7-i%8)) +*/ + +/* determine how many bytes we would need for 'num_bits' packed bits */ +static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits) +{ + unsigned int pbit_bytesize = num_bits / 8; + + if (num_bits % 8) + pbit_bytesize++; + + return pbit_bytesize; +} + +/* convert unpacked bits to packed bits, return length in bytes */ +int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits); + +/* convert packed bits to unpacked bits, return length in bytes */ +int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits); + +/* convert unpacked bits to packed bits (extended options but slower), + * return length in bytes (max written ofs of output buffer + 1) */ +int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs, + const ubit_t *in, unsigned int in_ofs, + unsigned int num_bits, int lsb_mode); + +/* convert packed bits to unpacked bits (extended options but slower), + * return length in bytes (max written ofs of output buffer + 1) */ +int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs, + const pbit_t *in, unsigned int in_ofs, + unsigned int num_bits, int lsb_mode); + +#endif diff --git a/include/osmocom/core/bitvec.h b/include/osmocom/core/bitvec.h new file mode 100644 index 00000000..42977fb2 --- /dev/null +++ b/include/osmocom/core/bitvec.h @@ -0,0 +1,75 @@ +#ifndef _BITVEC_H +#define _BITVEC_H + +/* bit vector utility routines */ + +/* (C) 2009 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + + +/* In GSM mac blocks, every bit can be 0 or 1, or L or H. L/H are + * defined relative to the 0x2b padding pattern */ +enum bit_value { + ZERO = 0, + ONE = 1, + L = 2, + H = 3, +}; + +struct bitvec { + unsigned int cur_bit; /* curser to the next unused bit */ + unsigned int data_len; /* length of data array in bytes */ + uint8_t *data; /* pointer to data array */ +}; + +/* check if the bit is 0 or 1 for a given position inside a bitvec */ +enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr); + +/* check if the bit is L or H for a given position inside a bitvec */ +enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv, + unsigned int bitnr); + +/* get the Nth set bit inside the bit vector */ +unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n); + +/* Set a bit at given position */ +int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum, + enum bit_value bit); + +/* Set the next bit in the vector */ +int bitvec_set_bit(struct bitvec *bv, enum bit_value bit); + +/* get the next bit (low/high) inside a bitvec */ +int bitvec_get_bit_high(struct bitvec *bv); + +/* Set multiple bits at the current position */ +int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count); + +/* Add an unsigned integer (of length count bits) to current position */ +int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count); + +/* get multiple bits (based on numeric value) from current pos */ +int bitvec_get_uint(struct bitvec *bv, int num_bits); + + +/* Pad the bit vector up to a certain bit position */ +int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit); + +#endif /* _BITVEC_H */ diff --git a/include/osmocom/core/crc16.h b/include/osmocom/core/crc16.h new file mode 100644 index 00000000..7a512490 --- /dev/null +++ b/include/osmocom/core/crc16.h @@ -0,0 +1,34 @@ +/* + * This was copied from the linux kernel and adjusted for our types. + */ +/* + * crc16.h - CRC-16 routine + * + * Implements the standard CRC-16: + * Width 16 + * Poly 0x8005 (x^16 + x^15 + x^2 + 1) + * Init 0 + * + * Copyright (c) 2005 Ben Gardner + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#ifndef __CRC16_H +#define __CRC16_H + +#include + +#include + +extern uint16_t const crc16_table[256]; + +extern uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len); + +static inline uint16_t crc16_byte(uint16_t crc, const uint8_t data) +{ + return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff]; +} + +#endif /* __CRC16_H */ diff --git a/include/osmocom/core/gsmtap.h b/include/osmocom/core/gsmtap.h new file mode 100644 index 00000000..236b25ac --- /dev/null +++ b/include/osmocom/core/gsmtap.h @@ -0,0 +1,89 @@ +#ifndef _GSMTAP_H +#define _GSMTAP_H + +/* gsmtap header, pseudo-header in front of the actua GSM payload */ + +/* GSMTAP is a generic header format for GSM protocol captures, + * it uses the IANA-assigned UDP port number 4729 and carries + * payload in various formats of GSM interfaces such as Um MAC + * blocks or Um bursts. + * + * Example programs generating GSMTAP data are airprobe + * (http://airprobe.org/) or OsmocomBB (http://bb.osmocom.org/) + */ + +#include + +#define GSMTAP_VERSION 0x02 + +#define GSMTAP_TYPE_UM 0x01 +#define GSMTAP_TYPE_ABIS 0x02 +#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */ +#define GSMTAP_TYPE_SIM 0x04 +#define GSMTAP_TYPE_TETRA_I1 0x05 /* tetra air interface */ +#define GSMTAP_TYPE_TETRA_I1_BURST 0x06 /* tetra air interface */ + +/* sub-types for TYPE_UM_BURST */ +#define GSMTAP_BURST_UNKNOWN 0x00 +#define GSMTAP_BURST_FCCH 0x01 +#define GSMTAP_BURST_PARTIAL_SCH 0x02 +#define GSMTAP_BURST_SCH 0x03 +#define GSMTAP_BURST_CTS_SCH 0x04 +#define GSMTAP_BURST_COMPACT_SCH 0x05 +#define GSMTAP_BURST_NORMAL 0x06 +#define GSMTAP_BURST_DUMMY 0x07 +#define GSMTAP_BURST_ACCESS 0x08 +#define GSMTAP_BURST_NONE 0x09 + +/* sub-types for TYPE_UM */ +#define GSMTAP_CHANNEL_UNKNOWN 0x00 +#define GSMTAP_CHANNEL_BCCH 0x01 +#define GSMTAP_CHANNEL_CCCH 0x02 +#define GSMTAP_CHANNEL_RACH 0x03 +#define GSMTAP_CHANNEL_AGCH 0x04 +#define GSMTAP_CHANNEL_PCH 0x05 +#define GSMTAP_CHANNEL_SDCCH 0x06 +#define GSMTAP_CHANNEL_SDCCH4 0x07 +#define GSMTAP_CHANNEL_SDCCH8 0x08 +#define GSMTAP_CHANNEL_TCH_F 0x09 +#define GSMTAP_CHANNEL_TCH_H 0x0a +#define GSMTAP_CHANNEL_ACCH 0x80 + +/* sub-types for TYPE_TETRA_AIR */ +#define GSMTAP_TETRA_BSCH 0x01 +#define GSMTAP_TETRA_AACH 0x02 +#define GSMTAP_TETRA_SCH_HU 0x03 +#define GSMTAP_TETRA_SCH_HD 0x04 +#define GSMTAP_TETRA_SCH_F 0x05 +#define GSMTAP_TETRA_BNCH 0x06 +#define GSMTAP_TETRA_STCH 0x07 +#define GSMTAP_TETRA_TCH_F 0x08 + +/* flags for the ARFCN */ +#define GSMTAP_ARFCN_F_PCS 0x8000 +#define GSMTAP_ARFCN_F_UPLINK 0x4000 +#define GSMTAP_ARFCN_MASK 0x3fff + +/* IANA-assigned well-known UDP port for GSMTAP messages */ +#define GSMTAP_UDP_PORT 4729 + +struct gsmtap_hdr { + uint8_t version; /* version, set to 0x01 currently */ + uint8_t hdr_len; /* length in number of 32bit words */ + uint8_t type; /* see GSMTAP_TYPE_* */ + uint8_t timeslot; /* timeslot (0..7 on Um) */ + + uint16_t arfcn; /* ARFCN (frequency) */ + int8_t signal_dbm; /* signal level in dBm */ + int8_t snr_db; /* signal/noise ratio in dB */ + + uint32_t frame_number; /* GSM Frame Number (FN) */ + + uint8_t sub_type; /* Type of burst/channel, see above */ + uint8_t antenna_nr; /* Antenna Number */ + uint8_t sub_slot; /* sub-slot within timeslot */ + uint8_t res; /* reserved for future use (RFU) */ + +} __attribute__((packed)); + +#endif /* _GSMTAP_H */ diff --git a/include/osmocom/core/gsmtap_util.h b/include/osmocom/core/gsmtap_util.h new file mode 100644 index 00000000..96449443 --- /dev/null +++ b/include/osmocom/core/gsmtap_util.h @@ -0,0 +1,21 @@ +#ifndef _GSMTAP_UTIL_H +#define _GSMTAP_UTIL_H + +#include + +/* convert RSL channel number to GSMTAP channel type */ +uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id); + +/* receive a message from L1/L2 and put it in GSMTAP */ +struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, + uint8_t ss, uint32_t fn, int8_t signal_dbm, + uint8_t snr, const uint8_t *data, unsigned int len); + +/* receive a message from L1/L2 and put it in GSMTAP */ +int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss, + uint32_t fn, int8_t signal_dbm, uint8_t snr, + const uint8_t *data, unsigned int len); + +int gsmtap_init(uint32_t dst_ip); + +#endif /* _GSMTAP_UTIL_H */ diff --git a/include/osmocom/core/linuxlist.h b/include/osmocom/core/linuxlist.h new file mode 100644 index 00000000..fb99c5ec --- /dev/null +++ b/include/osmocom/core/linuxlist.h @@ -0,0 +1,360 @@ +#ifndef _LINUX_LLIST_H +#define _LINUX_LLIST_H + +#include + +#ifndef inline +#define inline __inline__ +#endif + +static inline void prefetch(const void *x) {;} + +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (typeof( ((type *)0)->member ) *)(ptr); \ + (type *)( (char *)__mptr - offsetof(type, member) );}) + + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized llist entries. + */ +#define LLIST_POISON1 ((void *) 0x00100100) +#define LLIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked llist implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole llists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct llist_head { + struct llist_head *next, *prev; +}; + +#define LLIST_HEAD_INIT(name) { &(name), &(name) } + +#define LLIST_HEAD(name) \ + struct llist_head name = LLIST_HEAD_INIT(name) + +#define INIT_LLIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal llist manipulation where we know + * the prev/next entries already! + */ +static inline void __llist_add(struct llist_head *_new, + struct llist_head *prev, + struct llist_head *next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +/** + * llist_add - add a new entry + * @new: new entry to be added + * @head: llist head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void llist_add(struct llist_head *_new, struct llist_head *head) +{ + __llist_add(_new, head, head->next); +} + +/** + * llist_add_tail - add a new entry + * @new: new entry to be added + * @head: llist head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head) +{ + __llist_add(_new, head->prev, head); +} + +/* + * Delete a llist entry by making the prev/next entries + * point to each other. + * + * This is only for internal llist manipulation where we know + * the prev/next entries already! + */ +static inline void __llist_del(struct llist_head * prev, struct llist_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * llist_del - deletes entry from llist. + * @entry: the element to delete from the llist. + * Note: llist_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void llist_del(struct llist_head *entry) +{ + __llist_del(entry->prev, entry->next); + entry->next = (struct llist_head *)LLIST_POISON1; + entry->prev = (struct llist_head *)LLIST_POISON2; +} + +/** + * llist_del_init - deletes entry from llist and reinitialize it. + * @entry: the element to delete from the llist. + */ +static inline void llist_del_init(struct llist_head *entry) +{ + __llist_del(entry->prev, entry->next); + INIT_LLIST_HEAD(entry); +} + +/** + * llist_move - delete from one llist and add as another's head + * @llist: the entry to move + * @head: the head that will precede our entry + */ +static inline void llist_move(struct llist_head *llist, struct llist_head *head) +{ + __llist_del(llist->prev, llist->next); + llist_add(llist, head); +} + +/** + * llist_move_tail - delete from one llist and add as another's tail + * @llist: the entry to move + * @head: the head that will follow our entry + */ +static inline void llist_move_tail(struct llist_head *llist, + struct llist_head *head) +{ + __llist_del(llist->prev, llist->next); + llist_add_tail(llist, head); +} + +/** + * llist_empty - tests whether a llist is empty + * @head: the llist to test. + */ +static inline int llist_empty(const struct llist_head *head) +{ + return head->next == head; +} + +static inline void __llist_splice(struct llist_head *llist, + struct llist_head *head) +{ + struct llist_head *first = llist->next; + struct llist_head *last = llist->prev; + struct llist_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * llist_splice - join two llists + * @llist: the new llist to add. + * @head: the place to add it in the first llist. + */ +static inline void llist_splice(struct llist_head *llist, struct llist_head *head) +{ + if (!llist_empty(llist)) + __llist_splice(llist, head); +} + +/** + * llist_splice_init - join two llists and reinitialise the emptied llist. + * @llist: the new llist to add. + * @head: the place to add it in the first llist. + * + * The llist at @llist is reinitialised + */ +static inline void llist_splice_init(struct llist_head *llist, + struct llist_head *head) +{ + if (!llist_empty(llist)) { + __llist_splice(llist, head); + INIT_LLIST_HEAD(llist); + } +} + +/** + * llist_entry - get the struct for this entry + * @ptr: the &struct llist_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the llist_struct within the struct. + */ +#define llist_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * llist_for_each - iterate over a llist + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + */ +#define llist_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __llist_for_each - iterate over a llist + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + * + * This variant differs from llist_for_each() in that it's the + * simplest possible llist iteration code, no prefetching is done. + * Use this for code that knows the llist to be very short (empty + * or 1 entry) most of the time. + */ +#define __llist_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * llist_for_each_prev - iterate over a llist backwards + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + */ +#define llist_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * llist_for_each_safe - iterate over a llist safe against removal of llist entry + * @pos: the &struct llist_head to use as a loop counter. + * @n: another &struct llist_head to use as temporary storage + * @head: the head for your llist. + */ +#define llist_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * llist_for_each_entry - iterate over llist of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry(pos, head, member) \ + for (pos = llist_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = llist_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * llist_for_each_entry_reverse - iterate backwards over llist of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry_reverse(pos, head, member) \ + for (pos = llist_entry((head)->prev, typeof(*pos), member), \ + prefetch(pos->member.prev); \ + &pos->member != (head); \ + pos = llist_entry(pos->member.prev, typeof(*pos), member), \ + prefetch(pos->member.prev)) + +/** + * llist_for_each_entry_continue - iterate over llist of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry_continue(pos, head, member) \ + for (pos = llist_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = llist_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry_safe(pos, n, head, member) \ + for (pos = llist_entry((head)->next, typeof(*pos), member), \ + n = llist_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = llist_entry(n->member.next, typeof(*n), member)) + +/** + * llist_for_each_rcu - iterate over an rcu-protected llist + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + */ +#define llist_for_each_rcu(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) + +#define __llist_for_each_rcu(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;})) + +/** + * llist_for_each_safe_rcu - iterate over an rcu-protected llist safe + * against removal of llist entry + * @pos: the &struct llist_head to use as a loop counter. + * @n: another &struct llist_head to use as temporary storage + * @head: the head for your llist. + */ +#define llist_for_each_safe_rcu(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) + +/** + * llist_for_each_entry_rcu - iterate over rcu llist of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry_rcu(pos, head, member) \ + for (pos = llist_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = llist_entry(pos->member.next, typeof(*pos), member), \ + ({ smp_read_barrier_depends(); 0;}), \ + prefetch(pos->member.next)) + + +/** + * llist_for_each_continue_rcu - iterate over an rcu-protected llist + * continuing after existing point. + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + */ +#define llist_for_each_continue_rcu(pos, head) \ + for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ + (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) + + +#endif diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h new file mode 100644 index 00000000..db029402 --- /dev/null +++ b/include/osmocom/core/logging.h @@ -0,0 +1,154 @@ +#ifndef _OSMOCORE_LOGGING_H +#define _OSMOCORE_LOGGING_H + +#include +#include +#include + +#define LOG_MAX_CATEGORY 32 +#define LOG_MAX_CTX 8 +#define LOG_MAX_FILTERS 8 + +#define DEBUG + +#ifdef DEBUG +#define DEBUGP(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 0, fmt, ## args) +#define DEBUGPC(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 1, fmt, ## args) +#else +#define DEBUGP(xss, fmt, args...) +#define DEBUGPC(ss, fmt, args...) +#endif + + +void logp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); + +/* new logging interface */ +#define LOGP(ss, level, fmt, args...) \ + logp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) +#define LOGPC(ss, level, fmt, args...) \ + logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) + +/* different levels */ +#define LOGL_DEBUG 1 /* debugging information */ +#define LOGL_INFO 3 +#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ +#define LOGL_ERROR 7 /* error condition, requires user action */ +#define LOGL_FATAL 8 /* fatal, program aborted */ + +#define LOG_FILTER_ALL 0x0001 + +struct log_category { + uint8_t loglevel; + uint8_t enabled; +}; + +struct log_info_cat { + const char *name; + const char *color; + const char *description; + uint8_t loglevel; + uint8_t enabled; +}; + +/* log context information, passed to filter */ +struct log_context { + void *ctx[LOG_MAX_CTX+1]; +}; + +struct log_target; + +typedef int log_filter(const struct log_context *ctx, + struct log_target *target); + +struct log_info { + /* filter callback function */ + log_filter *filter_fn; + + /* per-category information */ + const struct log_info_cat *cat; + unsigned int num_cat; +}; + +enum log_target_type { + LOG_TGT_TYPE_VTY, + LOG_TGT_TYPE_SYSLOG, + LOG_TGT_TYPE_FILE, + LOG_TGT_TYPE_STDERR, +}; + +struct log_target { + struct llist_head entry; + + int filter_map; + void *filter_data[LOG_MAX_FILTERS+1]; + + struct log_category categories[LOG_MAX_CATEGORY+1]; + uint8_t loglevel; + int use_color:1; + int print_timestamp:1; + + enum log_target_type type; + + union { + struct { + FILE *out; + const char *fname; + } tgt_file; + + struct { + int priority; + int facility; + } tgt_syslog; + + struct { + void *vty; + } tgt_vty; + }; + + void (*output) (struct log_target *target, unsigned int level, + const char *string); +}; + +/* use the above macros */ +void logp2(unsigned int subsys, unsigned int level, char *file, + int line, int cont, const char *format, ...) + __attribute__ ((format (printf, 6, 7))); +void log_init(const struct log_info *cat); + +/* context management */ +void log_reset_context(void); +int log_set_context(uint8_t ctx, void *value); + +/* filter on the targets */ +void log_set_all_filter(struct log_target *target, int); + +void log_set_use_color(struct log_target *target, int); +void log_set_print_timestamp(struct log_target *target, int); +void log_set_log_level(struct log_target *target, int log_level); +void log_parse_category_mask(struct log_target *target, const char* mask); +int log_parse_level(const char *lvl); +const char *log_level_str(unsigned int lvl); +int log_parse_category(const char *category); +void log_set_category_filter(struct log_target *target, int category, + int enable, int level); + +/* management of the targets */ +struct log_target *log_target_create(void); +void log_target_destroy(struct log_target *target); +struct log_target *log_target_create_stderr(void); +struct log_target *log_target_create_file(const char *fname); +struct log_target *log_target_create_syslog(const char *ident, int option, + int facility); +int log_target_file_reopen(struct log_target *tgt); + +void log_add_target(struct log_target *target); +void log_del_target(struct log_target *target); + +/* Generate command string for VTY use */ +const char *log_vty_command_string(const struct log_info *info); +const char *log_vty_command_description(const struct log_info *info); + +struct log_target *log_target_find(int type, const char *fname); +extern struct llist_head osmo_log_target_list; + +#endif /* _OSMOCORE_LOGGING_H */ diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h new file mode 100644 index 00000000..57b5d7f4 --- /dev/null +++ b/include/osmocom/core/msgb.h @@ -0,0 +1,197 @@ +#ifndef _MSGB_H +#define _MSGB_H + +/* (C) 2008 by Harald Welte + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include + +#define MSGB_DEBUG + +struct msgb { + struct llist_head list; + + /* Part of which TRX logical channel we were received / transmitted */ + /* FIXME: move them into the control buffer */ + struct gsm_bts_trx *trx; + struct gsm_lchan *lchan; + + /* the Layer1 header (if any) */ + unsigned char *l1h; + /* the A-bis layer 2 header: OML, RSL(RLL), NS */ + unsigned char *l2h; + /* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */ + unsigned char *l3h; + /* the layer 4 header */ + unsigned char *l4h; + + /* the 'control buffer', large enough to contain 5 pointers */ + unsigned long cb[5]; + + uint16_t data_len; + uint16_t len; + + unsigned char *head; + unsigned char *tail; + unsigned char *data; + unsigned char _data[0]; +}; + +extern struct msgb *msgb_alloc(uint16_t size, const char *name); +extern void msgb_free(struct msgb *m); +extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg); +extern struct msgb *msgb_dequeue(struct llist_head *queue); +extern void msgb_reset(struct msgb *m); + +#ifdef MSGB_DEBUG +#include +#define MSGB_ABORT(msg, fmt, args ...) do { \ + osmo_panic("msgb(%p): " fmt, msg, ## args); \ + } while(0) +#else +#define MSGB_ABORT(msg, fmt, args ...) +#endif + +#define msgb_l1(m) ((void *)(m->l1h)) +#define msgb_l2(m) ((void *)(m->l2h)) +#define msgb_l3(m) ((void *)(m->l3h)) +#define msgb_sms(m) ((void *)(m->l4h)) + +static inline unsigned int msgb_l1len(const struct msgb *msgb) +{ + return msgb->tail - (uint8_t *)msgb_l1(msgb); +} + +static inline unsigned int msgb_l2len(const struct msgb *msgb) +{ + return msgb->tail - (uint8_t *)msgb_l2(msgb); +} + +static inline unsigned int msgb_l3len(const struct msgb *msgb) +{ + return msgb->tail - (uint8_t *)msgb_l3(msgb); +} + +static inline unsigned int msgb_headlen(const struct msgb *msgb) +{ + return msgb->len - msgb->data_len; +} + +static inline int msgb_tailroom(const struct msgb *msgb) +{ + return (msgb->head + msgb->data_len) - msgb->tail; +} + +static inline int msgb_headroom(const struct msgb *msgb) +{ + return (msgb->data - msgb->head); +} + +static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len) +{ + unsigned char *tmp = msgb->tail; + if (msgb_tailroom(msgb) < (int) len) + MSGB_ABORT(msgb, "Not enough tailroom msgb_push (%u < %u)\n", + msgb_tailroom(msgb), len); + msgb->tail += len; + msgb->len += len; + return tmp; +} +static inline void msgb_put_u8(struct msgb *msgb, uint8_t word) +{ + uint8_t *space = msgb_put(msgb, 1); + space[0] = word & 0xFF; +} +static inline void msgb_put_u16(struct msgb *msgb, uint16_t word) +{ + uint8_t *space = msgb_put(msgb, 2); + space[0] = word >> 8 & 0xFF; + space[1] = word & 0xFF; +} +static inline void msgb_put_u32(struct msgb *msgb, uint32_t word) +{ + uint8_t *space = msgb_put(msgb, 4); + space[0] = word >> 24 & 0xFF; + space[1] = word >> 16 & 0xFF; + space[2] = word >> 8 & 0xFF; + space[3] = word & 0xFF; +} +static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len) +{ + unsigned char *tmp = msgb->data; + msgb->data += len; + msgb->len -= len; + return tmp; +} +static inline uint8_t msgb_get_u8(struct msgb *msgb) +{ + uint8_t *space = msgb_get(msgb, 1); + return space[0]; +} +static inline uint16_t msgb_get_u16(struct msgb *msgb) +{ + uint8_t *space = msgb_get(msgb, 2); + return space[0] << 8 | space[1]; +} +static inline uint32_t msgb_get_u32(struct msgb *msgb) +{ + uint8_t *space = msgb_get(msgb, 4); + return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3]; +} +static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len) +{ + if (msgb_headroom(msgb) < (int) len) + MSGB_ABORT(msgb, "Not enough headroom msgb_push (%u < %u)\n", + msgb_headroom(msgb), len); + msgb->data -= len; + msgb->len += len; + return msgb->data; +} +static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len) +{ + msgb->len -= len; + return msgb->data += len; +} + +/* increase the headroom of an empty msgb, reducing the tailroom */ +static inline void msgb_reserve(struct msgb *msg, int len) +{ + msg->data += len; + msg->tail += len; +} + +static inline struct msgb *msgb_alloc_headroom(int size, int headroom, + const char *name) +{ + static_assert(size > headroom, headroom_bigger); + + struct msgb *msg = msgb_alloc(size, name); + if (msg) + msgb_reserve(msg, headroom); + return msg; +} + +/* non inline functions to ease binding */ +uint8_t *msgb_data(const struct msgb *msg); +uint16_t msgb_length(const struct msgb *msg); + + +#endif /* _MSGB_H */ diff --git a/include/osmocom/core/msgfile.h b/include/osmocom/core/msgfile.h new file mode 100644 index 00000000..92caa9fc --- /dev/null +++ b/include/osmocom/core/msgfile.h @@ -0,0 +1,49 @@ +/* + * (C) 2010 by Holger Hans Peter Freyther + * (C) 2010 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef MSG_FILE_H +#define MSG_FILE_H + +#include "linuxlist.h" + +/** + * One message in the list. + */ +struct msg_entry { + struct llist_head list; + + /* number for everyone to use */ + int nr; + + /* data from the file */ + char *mcc; + char *mnc; + char *option; + char *text; +}; + +struct msg_entries { + struct llist_head entry; +}; + +struct msg_entries *msg_entry_parse(void *ctx, const char *filename); + +#endif diff --git a/include/osmocom/core/panic.h b/include/osmocom/core/panic.h new file mode 100644 index 00000000..c5a83778 --- /dev/null +++ b/include/osmocom/core/panic.h @@ -0,0 +1,11 @@ +#ifndef OSMOCORE_PANIC_H +#define OSMOCORE_PANIC_H + +#include + +typedef void (*osmo_panic_handler_t)(const char *fmt, va_list args); + +void osmo_panic(const char *fmt, ...); +void osmo_set_panic_handler(osmo_panic_handler_t h); + +#endif diff --git a/include/osmocom/core/plugin.h b/include/osmocom/core/plugin.h new file mode 100644 index 00000000..98f9b56d --- /dev/null +++ b/include/osmocom/core/plugin.h @@ -0,0 +1,6 @@ +#ifndef _OSMO_PLUGIN_H +#define _OSMO_PLUGIN_H + +int plugin_load_all(const char *directory); + +#endif diff --git a/include/osmocom/core/process.h b/include/osmocom/core/process.h new file mode 100644 index 00000000..2d663828 --- /dev/null +++ b/include/osmocom/core/process.h @@ -0,0 +1,6 @@ +#ifndef _OSMO_PROCESS_H +#define _OSMO_PROCESS_H + +int osmo_daemonize(void); + +#endif diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h new file mode 100644 index 00000000..dba573d9 --- /dev/null +++ b/include/osmocom/core/rate_ctr.h @@ -0,0 +1,81 @@ +#ifndef _RATE_CTR_H +#define _RATE_CTR_H + +#include + +#include + +#define RATE_CTR_INTV_NUM 4 + +enum rate_ctr_intv { + RATE_CTR_INTV_SEC, + RATE_CTR_INTV_MIN, + RATE_CTR_INTV_HOUR, + RATE_CTR_INTV_DAY, +}; + +/* for each of the intervals, we keep the following values */ +struct rate_ctr_per_intv { + uint64_t last; + uint64_t rate; +}; + +/* for each actual value, we keep the following data */ +struct rate_ctr { + uint64_t current; + struct rate_ctr_per_intv intv[RATE_CTR_INTV_NUM]; +}; + +struct rate_ctr_desc { + const char *name; + const char *description; +}; + +/* Describe a counter group class */ +struct rate_ctr_group_desc { + /* The prefix to the name of all counters in this group */ + const char *group_name_prefix; + /* The human-readable description of the group */ + const char *group_description; + /* The number of counters in this group */ + const unsigned int num_ctr; + /* Pointer to array of counter names */ + const struct rate_ctr_desc *ctr_desc; +}; + +/* One instance of a counter group class */ +struct rate_ctr_group { + /* Linked list of all counter groups in the system */ + struct llist_head list; + /* Pointer to the counter group class */ + const struct rate_ctr_group_desc *desc; + /* The index of this ctr_group within its class */ + unsigned int idx; + /* Actual counter structures below */ + struct rate_ctr ctr[0]; +}; + +/* Allocate a new group of counters according to description */ +struct rate_ctr_group *rate_ctr_group_alloc(void *ctx, + const struct rate_ctr_group_desc *desc, + unsigned int idx); + +/* Free the memory for the specified group of counters */ +void rate_ctr_group_free(struct rate_ctr_group *grp); + +/* Add a number to the counter */ +void rate_ctr_add(struct rate_ctr *ctr, int inc); + +/* Increment the counter by 1 */ +static inline void rate_ctr_inc(struct rate_ctr *ctr) +{ + rate_ctr_add(ctr, 1); +} + +/* Initialize the counter module */ +int rate_ctr_init(void *tall_ctx); + +struct vty; +void vty_out_rate_ctr_group(struct vty *vty, const char *prefix, + struct rate_ctr_group *ctrg); +#endif /* RATE_CTR_H */ diff --git a/include/osmocom/core/select.h b/include/osmocom/core/select.h new file mode 100644 index 00000000..5ca21c3e --- /dev/null +++ b/include/osmocom/core/select.h @@ -0,0 +1,22 @@ +#ifndef _BSC_SELECT_H +#define _BSC_SELECT_H + +#include + +#define BSC_FD_READ 0x0001 +#define BSC_FD_WRITE 0x0002 +#define BSC_FD_EXCEPT 0x0004 + +struct bsc_fd { + struct llist_head list; + int fd; + unsigned int when; + int (*cb)(struct bsc_fd *fd, unsigned int what); + void *data; + unsigned int priv_nr; +}; + +int bsc_register_fd(struct bsc_fd *fd); +void bsc_unregister_fd(struct bsc_fd *fd); +int bsc_select_main(int polling); +#endif /* _BSC_SELECT_H */ diff --git a/include/osmocom/core/signal.h b/include/osmocom/core/signal.h new file mode 100644 index 00000000..02d83d2e --- /dev/null +++ b/include/osmocom/core/signal.h @@ -0,0 +1,15 @@ +#ifndef OSMOCORE_SIGNAL_H +#define OSMOCORE_SIGNAL_H + +typedef int signal_cbfn(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data); + + +/* Management */ +int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data); +void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data); + +/* Dispatch */ +void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data); + +#endif /* OSMOCORE_SIGNAL_H */ diff --git a/include/osmocom/core/statistics.h b/include/osmocom/core/statistics.h new file mode 100644 index 00000000..1d56054a --- /dev/null +++ b/include/osmocom/core/statistics.h @@ -0,0 +1,31 @@ +#ifndef _STATISTICS_H +#define _STATISTICS_H + +struct counter { + struct llist_head list; + const char *name; + const char *description; + unsigned long value; +}; + +static inline void counter_inc(struct counter *ctr) +{ + ctr->value++; +} + +static inline unsigned long counter_get(struct counter *ctr) +{ + return ctr->value; +} + +static inline void counter_reset(struct counter *ctr) +{ + ctr->value = 0; +} + +struct counter *counter_alloc(const char *name); +void counter_free(struct counter *ctr); + +int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data); + +#endif /* _STATISTICS_H */ diff --git a/include/osmocom/core/talloc.h b/include/osmocom/core/talloc.h new file mode 100644 index 00000000..f7f7643b --- /dev/null +++ b/include/osmocom/core/talloc.h @@ -0,0 +1,192 @@ +#ifndef _TALLOC_H_ +#define _TALLOC_H_ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + + Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Stefan Metzmacher 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +#include +#include +#include + +#define HAVE_VA_COPY + +/* this is only needed for compatibility with the old talloc */ +typedef void TALLOC_CTX; + +/* + this uses a little trick to allow __LINE__ to be stringified +*/ +#ifndef __location__ +#define __TALLOC_STRING_LINE1__(s) #s +#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s) +#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__) +#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__ +#endif + +#ifndef TALLOC_DEPRECATED +#define TALLOC_DEPRECATED 0 +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/* try to make talloc_set_destructor() and talloc_steal() type safe, + if we have a recent gcc */ +#if (__GNUC__ >= 3) +#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) +#define talloc_set_destructor(ptr, function) \ + do { \ + int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ + _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ + } while(0) +/* this extremely strange macro is to avoid some braindamaged warning + stupidity in gcc 4.1.x */ +#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; }) +#else +#define talloc_set_destructor(ptr, function) \ + _talloc_set_destructor((ptr), (int (*)(void *))(function)) +#define _TALLOC_TYPEOF(ptr) void * +#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)) +#endif + +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) +#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr)) + +/* useful macros for creating type checked pointers */ +#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) +#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) + +#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) + +#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) + +#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) +#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) +#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) +#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) + +#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) +#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) + +#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) + +#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) +#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) +#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) + +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) + +#if TALLOC_DEPRECATED +#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) +#define talloc_p(ctx, type) talloc(ctx, type) +#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) +#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) +#define talloc_destroy(ctx) talloc_free(ctx) +#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a)) +#endif + +#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) + +/* The following definitions come from talloc.c */ +void *_talloc(const void *context, size_t size); +void *talloc_pool(const void *context, size_t size); +void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); +int talloc_increase_ref_count(const void *ptr); +size_t talloc_reference_count(const void *ptr); +void *_talloc_reference(const void *context, const void *ptr); +int talloc_unlink(const void *context, void *ptr); +const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void talloc_set_name_const(const void *ptr, const char *name); +void *talloc_named(const void *context, size_t size, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +void *talloc_named_const(const void *context, size_t size, const char *name); +const char *talloc_get_name(const void *ptr); +void *talloc_check_name(const void *ptr, const char *name); +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); +void *talloc_parent(const void *ptr); +const char *talloc_parent_name(const void *ptr); +void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +int talloc_free(void *ptr); +void talloc_free_children(void *ptr); +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); +void *_talloc_steal(const void *new_ctx, const void *ptr); +void *_talloc_move(const void *new_ctx, const void *pptr); +size_t talloc_total_size(const void *ptr); +size_t talloc_total_blocks(const void *ptr); +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data); +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); +void talloc_report_full(const void *ptr, FILE *f); +void talloc_report(const void *ptr, FILE *f); +void talloc_enable_null_tracking(void); +void talloc_disable_null_tracking(void); +void talloc_enable_leak_report(void); +void talloc_enable_leak_report_full(void); +void *_talloc_zero(const void *ctx, size_t size, const char *name); +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +void *talloc_realloc_fn(const void *context, void *ptr, size_t size); +void *talloc_autofree_context(void); +size_t talloc_get_size(const void *ctx); +void *talloc_find_parent_byname(const void *ctx, const char *name); +void talloc_show_parents(const void *context, FILE *file); +int talloc_is_parent(const void *context, const void *ptr); + +char *talloc_strdup(const void *t, const char *p); +char *talloc_strdup_append(char *s, const char *a); +char *talloc_strdup_append_buffer(char *s, const char *a); + +char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_strndup_append(char *s, const char *a, size_t n); +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); + +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); + +#endif diff --git a/include/osmocom/core/timer.h b/include/osmocom/core/timer.h new file mode 100644 index 00000000..19664781 --- /dev/null +++ b/include/osmocom/core/timer.h @@ -0,0 +1,72 @@ +/* + * (C) 2008, 2009 by Holger Hans Peter Freyther + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef TIMER_H +#define TIMER_H + +#include + +#include + +/** + * Timer management: + * - Create a struct timer_list + * - Fill out timeout and use add_timer or + * use schedule_timer to schedule a timer in + * x seconds and microseconds from now... + * - Use del_timer to remove the timer + * + * Internally: + * - We hook into select.c to give a timeval of the + * nearest timer. On already passed timers we give + * it a 0 to immediately fire after the select + * - update_timers will call the callbacks and remove + * the timers. + * + */ +struct timer_list { + struct llist_head entry; + struct timeval timeout; + unsigned int active : 1; + unsigned int handled : 1; + unsigned int in_list : 1; + + void (*cb)(void*); + void *data; +}; + +/** + * timer management + */ +void bsc_add_timer(struct timer_list *timer); +void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds); +void bsc_del_timer(struct timer_list *timer); +int bsc_timer_pending(struct timer_list *timer); + + +/** + * internal timer list management + */ +struct timeval *bsc_nearest_timer(); +void bsc_prepare_timers(); +int bsc_update_timers(); +int bsc_timer_check(void); + +#endif diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h new file mode 100644 index 00000000..0cdf03b8 --- /dev/null +++ b/include/osmocom/core/utils.h @@ -0,0 +1,30 @@ +#ifndef OSMOCORE_UTIL_H +#define OSMOCORE_UTIL_H + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#include + +struct value_string { + unsigned int value; + const char *str; +}; + +const char *get_value_string(const struct value_string *vs, uint32_t val); +int get_string_value(const struct value_string *vs, const char *str); + +char bcd2char(uint8_t bcd); +/* only works for numbers in ascci */ +uint8_t char2bcd(char c); + +int hexparse(const char *str, uint8_t *b, int max_len); +char *hexdump(const unsigned char *buf, int len); +char *hexdump_nospc(const unsigned char *buf, int len); +char *ubit_dump(const uint8_t *bits, unsigned int len); + +#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; + +void osmo_str2lower(char *out, const char *in); +void osmo_str2upper(char *out, const char *in); + +#endif diff --git a/include/osmocom/core/write_queue.h b/include/osmocom/core/write_queue.h new file mode 100644 index 00000000..ef244c32 --- /dev/null +++ b/include/osmocom/core/write_queue.h @@ -0,0 +1,46 @@ +/* Generic write queue implementation */ +/* + * (C) 2010 by Holger Hans Peter Freyther + * (C) 2010 by On-Waves + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef write_queue_h +#define write_queue_h + +#include "select.h" +#include "msgb.h" + +struct write_queue { + struct bsc_fd bfd; + unsigned int max_length; + unsigned int current_length; + + struct llist_head msg_queue; + + int (*read_cb)(struct bsc_fd *fd); + int (*write_cb)(struct bsc_fd *fd, struct msgb *msg); + int (*except_cb)(struct bsc_fd *fd); +}; + +void write_queue_init(struct write_queue *queue, int max_length); +void write_queue_clear(struct write_queue *queue); +int write_queue_enqueue(struct write_queue *queue, struct msgb *data); +int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what); + +#endif diff --git a/include/osmocom/crypt/gprs_cipher.h b/include/osmocom/crypt/gprs_cipher.h index 3e514ec7..30510711 100644 --- a/include/osmocom/crypt/gprs_cipher.h +++ b/include/osmocom/crypt/gprs_cipher.h @@ -1,7 +1,7 @@ #ifndef _GPRS_CIPHER_H #define _GPRS_CIPHER_H -#include +#include #define GSM0464_CIPH_MAX_BLOCK 1523 diff --git a/include/osmocom/gsm/Makefile.am b/include/osmocom/gsm/Makefile.am new file mode 100644 index 00000000..8685fc9a --- /dev/null +++ b/include/osmocom/gsm/Makefile.am @@ -0,0 +1,6 @@ +osmogsm_HEADERS = comp128.h gsm0808.h gsm48_ie.h mncc.h rxlev_stat.h \ + gsm0480.h gsm48.h gsm_utils.h rsl.h tlv.h + +SUBDIRS = protocol + +osmogsmdir = $(includedir)/osmocom/gsm diff --git a/include/osmocom/gsm/comp128.h b/include/osmocom/gsm/comp128.h new file mode 100644 index 00000000..c37808f0 --- /dev/null +++ b/include/osmocom/gsm/comp128.h @@ -0,0 +1,22 @@ +/* + * COMP128 header + * + * See comp128.c for details + */ + +#ifndef __COMP128_H__ +#define __COMP128_H__ + +#include + +/* + * Performs the COMP128 algorithm (used as A3/A8) + * ki : uint8_t [16] + * srand : uint8_t [16] + * sres : uint8_t [4] + * kc : uint8_t [8] + */ +void comp128(uint8_t *ki, uint8_t *srand, uint8_t *sres, uint8_t *kc); + +#endif /* __COMP128_H__ */ + diff --git a/include/osmocom/gsm/gsm0480.h b/include/osmocom/gsm/gsm0480.h new file mode 100644 index 00000000..d6626d60 --- /dev/null +++ b/include/osmocom/gsm/gsm0480.h @@ -0,0 +1,26 @@ +#ifndef gsm0480_h +#define gsm0480_h + +#include +#include +#include + +#define MAX_LEN_USSD_STRING 31 + +struct ussd_request { + char text[MAX_LEN_USSD_STRING + 1]; + uint8_t transaction_id; + uint8_t invoke_id; +}; + +int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len, + struct ussd_request *request); + +struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text); +struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text); +struct msgb *gsm0480_create_notifySS(const char *text); + +int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id); +int gsm0480_wrap_facility(struct msgb *msg); + +#endif diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h new file mode 100644 index 00000000..1d853775 --- /dev/null +++ b/include/osmocom/gsm/gsm0808.h @@ -0,0 +1,46 @@ +/* (C) 2009,2010 by Holger Hans Peter Freyther + * (C) 2009,2010 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef OSMOCORE_GSM0808_H +#define OSMOCORE_GSM0808_H + +#include "tlv.h" + +struct msgb; + +struct msgb *gsm0808_create_layer3(struct msgb *msg, uint16_t netcode, uint16_t countrycode, int lac, uint16_t ci); +struct msgb *gsm0808_create_reset(void); +struct msgb *gsm0808_create_clear_command(uint8_t reason); +struct msgb *gsm0808_create_clear_complete(void); +struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id); +struct msgb *gsm0808_create_cipher_reject(uint8_t cause); +struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark, uint8_t length); +struct msgb *gsm0808_create_sapi_reject(uint8_t link_id); +struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause, + uint8_t chosen_channel, uint8_t encr_alg_id, + uint8_t speech_mode); +struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause); +struct msgb *gsm0808_create_clear_rqst(uint8_t cause); + +struct msgb *gsm0808_create_dtap(struct msgb *msg, uint8_t link_id); +void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id); + +const struct tlv_definition *gsm0808_att_tlvdef(); + +#endif diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h new file mode 100644 index 00000000..1e9403bc --- /dev/null +++ b/include/osmocom/gsm/gsm48.h @@ -0,0 +1,36 @@ +#ifndef _OSMOCORE_GSM48_H +#define _OSMOCORE_GSM48_H + +#include +#include +#include + +/* A parsed GPRS routing area */ +struct gprs_ra_id { + uint16_t mnc; + uint16_t mcc; + uint16_t lac; + uint8_t rac; +}; + +extern const struct tlv_definition gsm48_att_tlvdef; +extern const struct tlv_definition gsm48_rr_att_tlvdef; +extern const struct tlv_definition gsm48_mm_att_tlvdef; +const char *gsm48_cc_state_name(uint8_t state); +const char *gsm48_cc_msg_name(uint8_t msgtype); +const char *rr_cause_name(uint8_t cause); + +void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc, + uint16_t mnc, uint16_t lac); +int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi); +int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi); + +/* Convert Mobile Identity (10.5.1.4) to string */ +int gsm48_mi_to_string(char *string, const int str_len, + const uint8_t *mi, const int mi_len); + +/* Parse Routeing Area Identifier */ +void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf); +int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid); + +#endif diff --git a/include/osmocom/gsm/gsm48_ie.h b/include/osmocom/gsm/gsm48_ie.h new file mode 100644 index 00000000..f4fce25c --- /dev/null +++ b/include/osmocom/gsm/gsm48_ie.h @@ -0,0 +1,117 @@ +#ifndef _OSMOCORE_GSM48_IE_H +#define _OSMOCORE_GSM48_IE_H + +#include +#include +#include + +#include +#include +#include +#include + +/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */ +int gsm48_decode_bcd_number(char *output, int output_len, + const uint8_t *bcd_lv, int h_len); + +/* convert a ASCII phone number to 'called/calling/connect party BCD number' */ +int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len, + int h_len, const char *input); +/* decode 'bearer capability' */ +int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap, + const uint8_t *lv); +/* encode 'bearer capability' */ +int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only, + const struct gsm_mncc_bearer_cap *bcap); +/* decode 'call control cap' */ +int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv); +/* encode 'call control cap' */ +int gsm48_encode_cccap(struct msgb *msg, + const struct gsm_mncc_cccap *ccap); +/* decode 'called party BCD number' */ +int gsm48_decode_called(struct gsm_mncc_number *called, + const uint8_t *lv); +/* encode 'called party BCD number' */ +int gsm48_encode_called(struct msgb *msg, + const struct gsm_mncc_number *called); +/* decode callerid of various IEs */ +int gsm48_decode_callerid(struct gsm_mncc_number *callerid, + const uint8_t *lv); +/* encode callerid of various IEs */ +int gsm48_encode_callerid(struct msgb *msg, int ie, int max_len, + const struct gsm_mncc_number *callerid); +/* decode 'cause' */ +int gsm48_decode_cause(struct gsm_mncc_cause *cause, + const uint8_t *lv); +/* encode 'cause' */ +int gsm48_encode_cause(struct msgb *msg, int lv_only, + const struct gsm_mncc_cause *cause); +/* decode 'calling number' */ +int gsm48_decode_calling(struct gsm_mncc_number *calling, + const uint8_t *lv); +/* encode 'calling number' */ +int gsm48_encode_calling(struct msgb *msg, + const struct gsm_mncc_number *calling); +/* decode 'connected number' */ +int gsm48_decode_connected(struct gsm_mncc_number *connected, + const uint8_t *lv); +/* encode 'connected number' */ +int gsm48_encode_connected(struct msgb *msg, + const struct gsm_mncc_number *connected); +/* decode 'redirecting number' */ +int gsm48_decode_redirecting(struct gsm_mncc_number *redirecting, + const uint8_t *lv); +/* encode 'redirecting number' */ +int gsm48_encode_redirecting(struct msgb *msg, + const struct gsm_mncc_number *redirecting); +/* decode 'facility' */ +int gsm48_decode_facility(struct gsm_mncc_facility *facility, + const uint8_t *lv); +/* encode 'facility' */ +int gsm48_encode_facility(struct msgb *msg, int lv_only, + const struct gsm_mncc_facility *facility); +/* decode 'notify' */ +int gsm48_decode_notify(int *notify, const uint8_t *v); +/* encode 'notify' */ +int gsm48_encode_notify(struct msgb *msg, int notify); +/* decode 'signal' */ +int gsm48_decode_signal(int *signal, const uint8_t *v); +/* encode 'signal' */ +int gsm48_encode_signal(struct msgb *msg, int signal); +/* decode 'keypad' */ +int gsm48_decode_keypad(int *keypad, const uint8_t *lv); +/* encode 'keypad' */ +int gsm48_encode_keypad(struct msgb *msg, int keypad); +/* decode 'progress' */ +int gsm48_decode_progress(struct gsm_mncc_progress *progress, + const uint8_t *lv); +/* encode 'progress' */ +int gsm48_encode_progress(struct msgb *msg, int lv_only, + const struct gsm_mncc_progress *p); +/* decode 'user-user' */ +int gsm48_decode_useruser(struct gsm_mncc_useruser *uu, + const uint8_t *lv); +/* encode 'useruser' */ +int gsm48_encode_useruser(struct msgb *msg, int lv_only, + const struct gsm_mncc_useruser *uu); +/* decode 'ss version' */ +int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv, + const uint8_t *lv); +/* encode 'ss version' */ +int gsm48_encode_ssversion(struct msgb *msg, + const struct gsm_mncc_ssversion *ssv); +/* decode 'more data' does not require a function, because it has no value */ +/* encode 'more data' */ +int gsm48_encode_more(struct msgb *msg); + +/* structure of one frequency */ +struct gsm_sysinfo_freq { + /* if the frequency included in the sysinfo */ + uint8_t mask; +}; + +/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */ +int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd, + uint8_t len, uint8_t mask, uint8_t frqt); + +#endif diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h new file mode 100644 index 00000000..19adb70a --- /dev/null +++ b/include/osmocom/gsm/gsm_utils.h @@ -0,0 +1,117 @@ +/* GSM utility functions, e.g. coding and decoding */ +/* + * (C) 2008 by Daniel Willmann + * (C) 2009 by Holger Hans Peter Freyther + * (C) 2009-2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef GSM_UTILS_H +#define GSM_UTILS_H + +#include + +#define ADD_MODULO(sum, delta, modulo) do { \ + if ((sum += delta) >= modulo) \ + sum -= modulo; \ + } while (0) + +#define GSM_MAX_FN (26*51*2048) + +struct gsm_time { + uint32_t fn; /* FN count */ + uint16_t t1; /* FN div (26*51) */ + uint8_t t2; /* FN modulo 26 */ + uint8_t t3; /* FN modulo 51 */ + uint8_t tc; +}; + +enum gsm_band { + GSM_BAND_850 = 1, + GSM_BAND_900 = 2, + GSM_BAND_1800 = 4, + GSM_BAND_1900 = 8, + GSM_BAND_450 = 0x10, + GSM_BAND_480 = 0x20, + GSM_BAND_750 = 0x40, + GSM_BAND_810 = 0x80, +}; + +const char *gsm_band_name(enum gsm_band band); +enum gsm_band gsm_band_parse(const char *mhz); + +int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length); +int gsm_7bit_encode(uint8_t *result, const char *data); + +int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm); +int ms_pwr_dbm(enum gsm_band band, uint8_t lvl); + +/* According to TS 08.05 Chapter 8.1.4 */ +int rxlev2dbm(uint8_t rxlev); +uint8_t dbm2rxlev(int dbm); + +/* According to GSM 04.08 Chapter 10.5.1.6 */ +static inline int ms_cm2_a5n_support(uint8_t *cm2, int n) { + switch (n) { + case 0: return 1; + case 1: return (cm2[0] & (1<<3)) ? 0 : 1; + case 2: return (cm2[2] & (1<<0)) ? 1 : 0; + case 3: return (cm2[2] & (1<<1)) ? 1 : 0; + default: + return 0; + } +} + +/* According to GSM 04.08 Chapter 10.5.2.29 */ +static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; } +static inline int rach_max_trans_raw2val(int raw) { + const int tbl[4] = { 1, 2, 4, 7 }; + return tbl[raw & 3]; +} + +#define ARFCN_PCS 0x8000 +#define ARFCN_UPLINK 0x4000 +#define ARFCN_FLAG_MASK 0xf000 /* Reserve the upper 5 bits for flags */ + +enum gsm_band gsm_arfcn2band(uint16_t arfcn); + +/* Convert an ARFCN to the frequency in MHz * 10 */ +uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink); + +/* Convert from frame number to GSM time */ +void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn); + +/* Convert from GSM time to frame number */ +uint32_t gsm_gsmtime2fn(struct gsm_time *time); + +/* GSM TS 03.03 Chapter 2.6 */ +enum gprs_tlli_type { + TLLI_LOCAL, + TLLI_FOREIGN, + TLLI_RANDOM, + TLLI_AUXILIARY, + TLLI_RESERVED, +}; + +/* TS 03.03 Chapter 2.6 */ +int gprs_tlli_type(uint32_t tlli); + +uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type); + +#endif diff --git a/include/osmocom/gsm/mncc.h b/include/osmocom/gsm/mncc.h new file mode 100644 index 00000000..a094bb9b --- /dev/null +++ b/include/osmocom/gsm/mncc.h @@ -0,0 +1,71 @@ +#ifndef _OSMOCORE_MNCC_H +#define _OSMOCORE_MNCC_H + +#define GSM_MAX_FACILITY 128 +#define GSM_MAX_SSVERSION 128 +#define GSM_MAX_USERUSER 128 + +/* Expanded fields from GSM TS 04.08, Table 10.5.102 */ +struct gsm_mncc_bearer_cap { + int transfer; /* Information Transfer Capability */ + int mode; /* Transfer Mode */ + int coding; /* Coding Standard */ + int radio; /* Radio Channel Requirement */ + int speech_ctm; /* CTM text telephony indication */ + int speech_ver[8]; /* Speech version indication */ +}; + +struct gsm_mncc_number { + int type; + int plan; + int present; + int screen; + char number[33]; +}; + +struct gsm_mncc_cause { + int location; + int coding; + int rec; + int rec_val; + int value; + int diag_len; + char diag[32]; +}; + +struct gsm_mncc_useruser { + int proto; + char info[GSM_MAX_USERUSER + 1]; /* + termination char */ +}; + +struct gsm_mncc_progress { + int coding; + int location; + int descr; +}; + +struct gsm_mncc_facility { + int len; + char info[GSM_MAX_FACILITY]; +}; + +struct gsm_mncc_ssversion { + int len; + char info[GSM_MAX_SSVERSION]; +}; + +struct gsm_mncc_cccap { + int dtmf; + int pcp; +}; + +enum { + GSM_MNCC_BCAP_SPEECH = 0, + GSM_MNCC_BCAP_UNR_DIG = 1, + GSM_MNCC_BCAP_AUDIO = 2, + GSM_MNCC_BCAP_FAX_G3 = 3, + GSM_MNCC_BCAP_OTHER_ITC = 5, + GSM_MNCC_BCAP_RESERVED = 7, +}; + +#endif diff --git a/include/osmocom/gsm/protocol/Makefile.am b/include/osmocom/gsm/protocol/Makefile.am new file mode 100644 index 00000000..8483f10a --- /dev/null +++ b/include/osmocom/gsm/protocol/Makefile.am @@ -0,0 +1,6 @@ +osmogsm_proto_HEADERS = gsm_03_41.h \ + gsm_04_08.h gsm_04_11.h gsm_04_12.h gsm_04_80.h \ + gsm_08_08.h gsm_08_58.h \ + gsm_12_21.h + +osmogsm_protodir = $(includedir)/osmocom/gsm/protocol diff --git a/include/osmocom/gsm/protocol/gsm_03_41.h b/include/osmocom/gsm/protocol/gsm_03_41.h new file mode 100644 index 00000000..54365cbc --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_03_41.h @@ -0,0 +1,51 @@ +#ifndef PROTO_GSM_03_41_H +#define PROTO_GSM_03_41_H + +#include + +/* GSM TS 03.41 definitions also TS 23.041*/ + +/* Chapter 9.3.2 */ +struct gsm341_ms_message { + struct { + uint8_t code_hi:6; + uint8_t gs:2; + uint8_t update:4; + uint8_t code_lo:4; + } serial; + uint16_t msg_id; + struct { + uint8_t language:4; + uint8_t group:4; + } dcs; + struct { + uint8_t total:4; + uint8_t current:4; + } page; + uint8_t data[0]; +} __attribute__((packed)); + +/* Chapter 9.4.1.3 */ +struct gsm341_etws_message { + struct { + uint8_t code_hi:4; + uint8_t popup:1; + uint8_t alert:1; + uint8_t gs:2; + uint8_t update:4; + uint8_t code_lo:4; + } serial; + uint16_t msg_id; + uint16_t warning_type; + uint8_t data[0]; +} __attribute__((packed)); + +#define GSM341_MSG_CODE(ms) ((ms)->serial.code_lo | ((ms)->serial.code_hi << 4)) + +/* Section 9.3.2.1 - Geographical Scope */ +#define GSM341_GS_CELL_WIDE_IMMED 0 +#define GSM341_GS_PLMN_WIDE 1 +#define GSM341_GS_LA_WIDE 2 +#define GSM341_GS_CELL_WIDE 3 + +#endif /* PROTO_GSM_03_41_H */ diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h new file mode 100644 index 00000000..3ad7dfdc --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_04_08.h @@ -0,0 +1,1262 @@ +#ifndef PROTO_GSM_04_08_H +#define PROTO_GSM_04_08_H + +#include + +/* GSM TS 04.08 definitions */ +struct gsm_lchan; + +/* Chapter 10.5.1.5 */ +struct gsm48_classmark1 { + uint8_t pwr_lev:3, + a5_1:1, + es_ind:1, + rev_lev:2, + spare:1; +} __attribute__ ((packed)); + +/* Chapter 10.5.1.6 */ +struct gsm48_classmark2 { + uint8_t pwr_lev:3, + a5_1:1, + es_ind:1, + rev_lev:2, + spare:1; + uint8_t fc:1, + vgcs:1, + vbs:1, + sm_cap:1, + ss_scr:2, + ps_cap:1, + spare2:1; + uint8_t a5_2:1, + a5_3:1, + cmsp:1, + solsa:1, + spare3:1, + lcsva_cap:1, + spare4:1, + cm3:1; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.1b.3 */ +struct gsm48_range_1024 { + uint8_t w1_hi:2, + f0:1, + form_id:5; + uint8_t w1_lo; + uint8_t w2_hi; + uint8_t w3_hi:7, + w2_lo:1; + uint8_t w4_hi:6, + w3_lo:2; + uint8_t w5_hi:6, + w4_lo:2; + uint8_t w6_hi:6, + w5_lo:2; + uint8_t w7_hi:6, + w6_lo:2; + uint8_t w8_hi:6, + w7_lo:2; + uint8_t w9:7, + w8_lo:1; + uint8_t w11_hi:1, + w10:7; + uint8_t w12_hi:2, + w11_lo:6; + uint8_t w13_hi:3, + w12_lo:5; + uint8_t w14_hi:4, + w13_lo:4; + uint8_t w15_hi:5, + w14_lo:3; + uint8_t w16:6, + w15_lo:2; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.1b.4 */ +struct gsm48_range_512 { + uint8_t orig_arfcn_hi:1, + form_id:7; + uint8_t orig_arfcn_mid; + uint8_t w1_hi:7, + orig_arfcn_lo:1; + uint8_t w2_hi:6, + w1_lo:2; + uint8_t w3_hi:6, + w2_lo:2; + uint8_t w4_hi:6, + w3_lo:2; + uint8_t w5:7, + w4_lo:1; + uint8_t w7_hi:1, + w6:7; + uint8_t w8_hi:2, + w7_lo:6; + uint8_t w9_hi:4, + w8_lo:4; + uint8_t w10:6, + w9_lo:2; + uint8_t w12_hi:2, + w11:6; + uint8_t w13_hi:4, + w12_lo:4; + uint8_t w14:6, + w13_lo:2; + uint8_t w16_hi:2, + w15:6; + uint8_t w17:5, + w16_lo:3; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.1b.5 */ +struct gsm48_range_256 { + uint8_t orig_arfcn_hi:1, + form_id:7; + uint8_t orig_arfcn_mid; + uint8_t w1_hi:7, + orig_arfcn_lo:1; + uint8_t w2:7, + w1_lo:1; + uint8_t w4_hi:1, + w3:7; + uint8_t w5_hi:3, + w4_lo:5; + uint8_t w6_hi:5, + w5_lo:3; + uint8_t w8_hi:1, + w7:6, + w6_lo:1; + uint8_t w9_hi:4, + w8_lo:4; + uint8_t w11_hi:2, + w10:5, + w9_lo:1; + uint8_t w12:5, + w11_lo:3; + uint8_t w14_hi:3, + w13:5; + uint8_t w16_hi:1, + w15:5, + w14_lo:2; + uint8_t w18_hi:1, + w17:4, + w16_lo:3; + uint8_t w20_hi:1, + w19:4, + w18_lo:3; + uint8_t spare:1, + w21:4, + w20_lo:3; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.1b.6 */ +struct gsm48_range_128 { + uint8_t orig_arfcn_hi:1, + form_id:7; + uint8_t orig_arfcn_mid; + uint8_t w1:7, + orig_arfcn_lo:1; + uint8_t w3_hi:2, + w2:6; + uint8_t w4_hi:4, + w3_lo:4; + uint8_t w6_hi:2, + w5:5, + w4_lo:1; + uint8_t w7:5, + w6_lo:3; + uint8_t w9:4, + w8:4; + uint8_t w11:4, + w10:4; + uint8_t w13:4, + w12:4; + uint8_t w15:4, + w14:4; + uint8_t w18_hi:2, + w17:3, + w16:3; + uint8_t w21_hi:1, + w20:3, + w19:3, + w18_lo:1; + uint8_t w23:3, + w22:3, + w21_lo:2; + uint8_t w26_hi:2, + w25:3, + w24:3; + uint8_t spare:1, + w28:3, + w27:3, + w26_lo:1; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.1b.7 */ +struct gsm48_var_bit { + uint8_t orig_arfcn_hi:1, + form_id:7; + uint8_t orig_arfcn_mid; + uint8_t rrfcn1_7:7, + orig_arfcn_lo:1; + uint8_t rrfcn8_111[13]; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.5 */ +struct gsm48_chan_desc { + uint8_t chan_nr; + union { + struct { + uint8_t maio_high:4, + h:1, + tsc:3; + uint8_t hsn:6, + maio_low:2; + } h1; + struct { + uint8_t arfcn_high:2, + spare:2, + h:1, + tsc:3; + uint8_t arfcn_low; + } h0; + }; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.20 */ +struct gsm48_meas_res { + uint8_t rxlev_full:6, + dtx_used:1, + ba_used:1; + uint8_t rxlev_sub:6, + meas_valid:1, + spare:1; + uint8_t no_nc_n_hi:1, + rxqual_sub:3, + rxqual_full:3, + spare2:1; + uint8_t rxlev_nc1:6, + no_nc_n_lo:2; + uint8_t bsic_nc1_hi:3, + bcch_f_nc1:5; + uint8_t rxlev_nc2_hi:5, + bsic_nc1_lo:3; + uint8_t bsic_nc2_hi:2, + bcch_f_nc2:5, + rxlev_nc2_lo:1; + uint8_t rxlev_nc3_hi:4, + bsic_nc2_lo:4; + uint8_t bsic_nc3_hi:1, + bcch_f_nc3:5, + rxlev_nc3_lo:2; + uint8_t rxlev_nc4_hi:3, + bsic_nc3_lo:5; + uint8_t bcch_f_nc4:5, + rxlev_nc4_lo:3; + uint8_t rxlev_nc5_hi:2, + bsic_nc4:6; + uint8_t bcch_f_nc5_hi:4, + rxlev_nc5_lo:4; + uint8_t rxlev_nc6_hi:1, + bsic_nc5:6, + bcch_f_nc5_lo:1; + uint8_t bcch_f_nc6_hi:3, + rxlev_nc6_lo:5; + uint8_t bsic_nc6:6, + bcch_f_nc6_lo:2; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.21aa */ +struct gsm48_multi_rate_conf { + uint8_t smod : 2, + spare: 1, + icmi : 1, + nscb : 1, + ver : 3; + uint8_t m4_75 : 1, + m5_15 : 1, + m5_90 : 1, + m6_70 : 1, + m7_40 : 1, + m7_95 : 1, + m10_2 : 1, + m12_2 : 1; +} __attribute__((packed)); + +/* Chapter 10.5.2.28(a) */ +struct gsm48_power_cmd { + uint8_t power_level:5, + spare:2, + atc:1; +} __attribute__((packed)); + +/* Chapter 10.5.2.29 */ +struct gsm48_rach_control { + uint8_t re :1, + cell_bar :1, + tx_integer :4, + max_trans :2; + uint8_t t2; + uint8_t t3; +} __attribute__ ((packed)); + + +/* Chapter 10.5.2.30 */ +struct gsm48_req_ref { + uint8_t ra; + uint8_t t3_high:3, + t1:5; + uint8_t t2:5, + t3_low:3; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.38 */ +struct gsm48_start_time { + uint8_t t3_high:3, + t1:5; + uint8_t t2:5, + t3_low:3; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.39 */ +struct gsm48_sync_ind { + uint8_t si:2, + rot:1, + nci:1, + sync_ie:4; +} __attribute__((packed)); + +/* + * Chapter 9.1.5/9.1.6 + * + * For 9.1.6 the chan_desc has the meaning of 10.5.2.5a + */ +struct gsm48_chan_mode_modify { + struct gsm48_chan_desc chan_desc; + uint8_t mode; +} __attribute__ ((packed)); + +enum gsm48_chan_mode { + GSM48_CMODE_SIGN = 0x00, + GSM48_CMODE_SPEECH_V1 = 0x01, + GSM48_CMODE_SPEECH_EFR = 0x21, + GSM48_CMODE_SPEECH_AMR = 0x41, + GSM48_CMODE_DATA_14k5 = 0x0f, + GSM48_CMODE_DATA_12k0 = 0x03, + GSM48_CMODE_DATA_6k0 = 0x0b, + GSM48_CMODE_DATA_3k6 = 0x23, +}; + +/* Chapter 9.1.2 */ +struct gsm48_ass_cmd { + /* Semantic is from 10.5.2.5a */ + struct gsm48_chan_desc chan_desc; + uint8_t power_command; + uint8_t data[0]; +} __attribute__((packed)); + +/* Chapter 9.1.13 */ +struct gsm48_frq_redef { + /* Semantic is from 10.5.2.5a */ + struct gsm48_chan_desc chan_desc; + uint8_t mob_alloc_len; + uint8_t mob_alloc[0]; +} __attribute__((packed)); + +/* Chapter 10.5.2.2 */ +struct gsm48_cell_desc { + uint8_t bcc:3, + ncc:3, + arfcn_hi:2; + uint8_t arfcn_lo; +} __attribute__((packed)); + +/* Chapter 9.1.15 */ +struct gsm48_ho_cmd { + struct gsm48_cell_desc cell_desc; + struct gsm48_chan_desc chan_desc; + uint8_t ho_ref; + uint8_t power_command; + uint8_t data[0]; +} __attribute__((packed)); + +/* Chapter 9.1.18 */ +struct gsm48_imm_ass { + uint8_t l2_plen; + uint8_t proto_discr; + uint8_t msg_type; + uint8_t page_mode; + struct gsm48_chan_desc chan_desc; + struct gsm48_req_ref req_ref; + uint8_t timing_advance; + uint8_t mob_alloc_len; + uint8_t mob_alloc[0]; +} __attribute__ ((packed)); + +/* Chapter 9.1.25 */ +struct gsm48_pag_resp { + uint8_t spare:4, + key_seq:4; + uint32_t classmark2; + uint8_t mi_len; + uint8_t mi[0]; +} __attribute__ ((packed)); + +/* Chapter 10.5.1.3 */ +struct gsm48_loc_area_id { + uint8_t digits[3]; /* BCD! */ + uint16_t lac; +} __attribute__ ((packed)); + +/* Section 9.2.2 */ +struct gsm48_auth_req { + uint8_t key_seq:4, + spare:4; + uint8_t rand[16]; +} __attribute__ ((packed)); + +/* Section 9.2.3 */ +struct gsm48_auth_resp { + uint8_t sres[4]; +} __attribute__ ((packed)); + +/* Section 9.2.15 */ +struct gsm48_loc_upd_req { + uint8_t type:4, + key_seq:4; + struct gsm48_loc_area_id lai; + struct gsm48_classmark1 classmark1; + uint8_t mi_len; + uint8_t mi[0]; +} __attribute__ ((packed)); + +/* Section 10.1 */ +struct gsm48_hdr { + uint8_t proto_discr; + uint8_t msg_type; + uint8_t data[0]; +} __attribute__ ((packed)); + +/* Section 9.1.3x System information Type header */ +struct gsm48_system_information_type_header { + uint8_t l2_plen; + uint8_t rr_protocol_discriminator :4, + skip_indicator:4; + uint8_t system_information; +} __attribute__ ((packed)); + +/* Section 10.5.2.4 Cell Selection Parameters */ +struct gsm48_cell_sel_par { + uint8_t ms_txpwr_max_ccch:5, /* GSM 05.08 MS-TXPWR-MAX-CCCH */ + cell_resel_hyst:3; /* GSM 05.08 CELL-RESELECT-HYSTERESIS */ + uint8_t rxlev_acc_min:6, /* GSM 05.08 RXLEV-ACCESS-MIN */ + neci:1, + acs:1; +} __attribute__ ((packed)); + +/* Section 10.5.2.11 Control Channel Description , Figure 10.5.33 */ +struct gsm48_control_channel_descr { + uint8_t ccch_conf :3, + bs_ag_blks_res :3, + att :1, + spare1 :1; + uint8_t bs_pa_mfrms : 3, + spare2 :5; + uint8_t t3212; +} __attribute__ ((packed)); + +struct gsm48_cell_options { + uint8_t radio_link_timeout:4, + dtx:2, + pwrc:1, + spare:1; +} __attribute__ ((packed)); + +/* Section 9.2.9 CM service request */ +struct gsm48_service_request { + uint8_t cm_service_type : 4, + cipher_key_seq : 4; + /* length + 3 bytes */ + uint32_t classmark; + uint8_t mi_len; + uint8_t mi[0]; + /* optional priority level */ +} __attribute__ ((packed)); + +/* Section 9.1.31 System information Type 1 */ +struct gsm48_system_information_type_1 { + struct gsm48_system_information_type_header header; + uint8_t cell_channel_description[16]; + struct gsm48_rach_control rach_control; + uint8_t rest_octets[0]; /* NCH position on the CCCH */ +} __attribute__ ((packed)); + +/* Section 9.1.32 System information Type 2 */ +struct gsm48_system_information_type_2 { + struct gsm48_system_information_type_header header; + uint8_t bcch_frequency_list[16]; + uint8_t ncc_permitted; + struct gsm48_rach_control rach_control; +} __attribute__ ((packed)); + +/* Section 9.1.33 System information Type 2bis */ +struct gsm48_system_information_type_2bis { + struct gsm48_system_information_type_header header; + uint8_t bcch_frequency_list[16]; + struct gsm48_rach_control rach_control; + uint8_t rest_octets[0]; +} __attribute__ ((packed)); + +/* Section 9.1.34 System information Type 2ter */ +struct gsm48_system_information_type_2ter { + struct gsm48_system_information_type_header header; + uint8_t ext_bcch_frequency_list[16]; + uint8_t rest_octets[0]; +} __attribute__ ((packed)); + +/* Section 9.1.35 System information Type 3 */ +struct gsm48_system_information_type_3 { + struct gsm48_system_information_type_header header; + uint16_t cell_identity; + struct gsm48_loc_area_id lai; + struct gsm48_control_channel_descr control_channel_desc; + struct gsm48_cell_options cell_options; + struct gsm48_cell_sel_par cell_sel_par; + struct gsm48_rach_control rach_control; + uint8_t rest_octets[0]; +} __attribute__ ((packed)); + +/* Section 9.1.36 System information Type 4 */ +struct gsm48_system_information_type_4 { + struct gsm48_system_information_type_header header; + struct gsm48_loc_area_id lai; + struct gsm48_cell_sel_par cell_sel_par; + struct gsm48_rach_control rach_control; + /* optional CBCH conditional CBCH... followed by + mandantory SI 4 Reset Octets + */ + uint8_t data[0]; +} __attribute__ ((packed)); + +/* Section 9.1.37 System information Type 5 */ +struct gsm48_system_information_type_5 { + uint8_t rr_protocol_discriminator :4, + skip_indicator:4; + uint8_t system_information; + uint8_t bcch_frequency_list[16]; +} __attribute__ ((packed)); + +/* Section 9.1.38 System information Type 5bis */ +struct gsm48_system_information_type_5bis { + uint8_t rr_protocol_discriminator :4, + skip_indicator:4; + uint8_t system_information; + uint8_t bcch_frequency_list[16]; +} __attribute__ ((packed)); + +/* Section 9.1.39 System information Type 5ter */ +struct gsm48_system_information_type_5ter { + uint8_t rr_protocol_discriminator :4, + skip_indicator:4; + uint8_t system_information; + uint8_t bcch_frequency_list[16]; +} __attribute__ ((packed)); + +/* Section 9.1.40 System information Type 6 */ +struct gsm48_system_information_type_6 { + uint8_t rr_protocol_discriminator :4, + skip_indicator:4; + uint8_t system_information; + uint16_t cell_identity; + struct gsm48_loc_area_id lai; + struct gsm48_cell_options cell_options; + uint8_t ncc_permitted; + uint8_t rest_octets[0]; +} __attribute__ ((packed)); + +/* Section 9.1.43a System Information type 13 */ +struct gsm48_system_information_type_13 { + struct gsm48_system_information_type_header header; + uint8_t rest_octets[0]; +} __attribute__ ((packed)); + +/* Section 9.2.12 IMSI Detach Indication */ +struct gsm48_imsi_detach_ind { + struct gsm48_classmark1 classmark1; + uint8_t mi_len; + uint8_t mi[0]; +} __attribute__ ((packed)); + +/* Section 9.1.1 */ +struct gsm48_add_ass { + /* Semantic is from 10.5.2.5 */ + struct gsm48_chan_desc chan_desc; + uint8_t data[0]; +} __attribute__((packed)); + +/* Section 9.1.3 */ +struct gsm48_ass_cpl { + uint8_t rr_cause; +} __attribute__((packed)); + +/* Section 9.1.4 */ +struct gsm48_ass_fail { + uint8_t rr_cause; +} __attribute__((packed)); + +/* Section 9.1.3 */ +struct gsm48_ho_cpl { + uint8_t rr_cause; + uint8_t data[0]; +} __attribute__((packed)); + +/* Section 9.1.4 */ +struct gsm48_ho_fail { + uint8_t rr_cause; +} __attribute__((packed)); + +/* Section 9.1.7 */ +struct gsm48_chan_rel { + uint8_t rr_cause; + uint8_t data[0]; +} __attribute__((packed)); + +/* Section 9.1.9 */ +struct gsm48_cip_mode_cmd { + uint8_t sc:1, + alg_id:3, + cr:1, + spare:3; +} __attribute__((packed)); + +/* Section 9.1.11 */ +struct gsm48_cm_change { + uint8_t cm2_len; + struct gsm48_classmark2 cm2; + uint8_t data[0]; +} __attribute__((packed)); + +/* Section 9.1.19 */ +struct gsm48_imm_ass_ext { + uint8_t l2_plen; + uint8_t proto_discr; + uint8_t msg_type; + uint8_t page_mode; + struct gsm48_chan_desc chan_desc1; + struct gsm48_req_ref req_ref1; + uint8_t timing_advance1; + struct gsm48_chan_desc chan_desc2; + struct gsm48_req_ref req_ref2; + uint8_t timing_advance2; + uint8_t mob_alloc_len; + uint8_t mob_alloc[0]; +} __attribute__ ((packed)); + +/* Section 9.1.20 */ +struct gsm48_imm_ass_rej { + uint8_t l2_plen; + uint8_t proto_discr; + uint8_t msg_type; + uint8_t page_mode; + struct gsm48_req_ref req_ref1; + uint8_t wait_ind1; + struct gsm48_req_ref req_ref2; + uint8_t wait_ind2; + struct gsm48_req_ref req_ref3; + uint8_t wait_ind3; + struct gsm48_req_ref req_ref4; + uint8_t wait_ind4; + uint8_t rest[0]; +} __attribute__ ((packed)); + +/* Section 9.1.22 */ +struct gsm48_paging1 { + uint8_t l2_plen; + uint8_t proto_discr; + uint8_t msg_type; + uint8_t pag_mode:2, + spare:2, + cneed1:2, + cneed2:2; + uint8_t data[0]; +} __attribute__((packed)); + +/* Section 9.1.23 */ +struct gsm48_paging2 { + uint8_t l2_plen; + uint8_t proto_discr; + uint8_t msg_type; + uint8_t pag_mode:2, + spare:2, + cneed1:2, + cneed2:2; + uint32_t tmsi1; + uint32_t tmsi2; + uint8_t data[0]; +} __attribute__((packed)); + +/* Section 9.1.24 */ +struct gsm48_paging3 { + uint8_t l2_plen; + uint8_t proto_discr; + uint8_t msg_type; + uint8_t pag_mode:2, + spare:2, + cneed1:2, + cneed2:2; + uint32_t tmsi1; + uint32_t tmsi2; + uint32_t tmsi3; + uint32_t tmsi4; + uint8_t cneed3:2, + cneed4:2, + spare2:4; + uint8_t rest[0]; +} __attribute__((packed)); + +/* Section 9.1.25 */ +struct gsm48_pag_rsp { + uint8_t key_seq:3, + spare:5; + uint8_t cm2_len; + struct gsm48_classmark2 cm2; + uint8_t data[0]; +} __attribute__((packed)); + +/* Section 9.1.29 */ +struct gsm48_rr_status { + uint8_t rr_cause; +} __attribute__((packed)); + +/* Section 10.2 + GSM 04.07 12.2.3.1.1 */ +#define GSM48_PDISC_GROUP_CC 0x00 +#define GSM48_PDISC_BCAST_CC 0x01 +#define GSM48_PDISC_PDSS1 0x02 +#define GSM48_PDISC_CC 0x03 +#define GSM48_PDISC_PDSS2 0x04 +#define GSM48_PDISC_MM 0x05 +#define GSM48_PDISC_RR 0x06 +#define GSM48_PDISC_MM_GPRS 0x08 +#define GSM48_PDISC_SMS 0x09 +#define GSM48_PDISC_SM_GPRS 0x0a +#define GSM48_PDISC_NC_SS 0x0b +#define GSM48_PDISC_LOC 0x0c +#define GSM48_PDISC_MASK 0x0f +#define GSM48_PDISC_USSD 0x11 + +/* Section 10.4 */ +#define GSM48_MT_RR_INIT_REQ 0x3c +#define GSM48_MT_RR_ADD_ASS 0x3b +#define GSM48_MT_RR_IMM_ASS 0x3f +#define GSM48_MT_RR_IMM_ASS_EXT 0x39 +#define GSM48_MT_RR_IMM_ASS_REJ 0x3a + +#define GSM48_MT_RR_CIPH_M_CMD 0x35 +#define GSM48_MT_RR_CIPH_M_COMPL 0x32 + +#define GSM48_MT_RR_CFG_CHG_CMD 0x30 +#define GSM48_MT_RR_CFG_CHG_ACK 0x31 +#define GSM48_MT_RR_CFG_CHG_REJ 0x33 + +#define GSM48_MT_RR_ASS_CMD 0x2e +#define GSM48_MT_RR_ASS_COMPL 0x29 +#define GSM48_MT_RR_ASS_FAIL 0x2f +#define GSM48_MT_RR_HANDO_CMD 0x2b +#define GSM48_MT_RR_HANDO_COMPL 0x2c +#define GSM48_MT_RR_HANDO_FAIL 0x28 +#define GSM48_MT_RR_HANDO_INFO 0x2d + +#define GSM48_MT_RR_CELL_CHG_ORDER 0x08 +#define GSM48_MT_RR_PDCH_ASS_CMD 0x23 + +#define GSM48_MT_RR_CHAN_REL 0x0d +#define GSM48_MT_RR_PART_REL 0x0a +#define GSM48_MT_RR_PART_REL_COMP 0x0f + +#define GSM48_MT_RR_PAG_REQ_1 0x21 +#define GSM48_MT_RR_PAG_REQ_2 0x22 +#define GSM48_MT_RR_PAG_REQ_3 0x24 +#define GSM48_MT_RR_PAG_RESP 0x27 +#define GSM48_MT_RR_NOTIF_NCH 0x20 +#define GSM48_MT_RR_NOTIF_FACCH 0x25 +#define GSM48_MT_RR_NOTIF_RESP 0x26 + +#define GSM48_MT_RR_SYSINFO_8 0x18 +#define GSM48_MT_RR_SYSINFO_1 0x19 +#define GSM48_MT_RR_SYSINFO_2 0x1a +#define GSM48_MT_RR_SYSINFO_3 0x1b +#define GSM48_MT_RR_SYSINFO_4 0x1c +#define GSM48_MT_RR_SYSINFO_5 0x1d +#define GSM48_MT_RR_SYSINFO_6 0x1e +#define GSM48_MT_RR_SYSINFO_7 0x1f + +#define GSM48_MT_RR_SYSINFO_2bis 0x02 +#define GSM48_MT_RR_SYSINFO_2ter 0x03 +#define GSM48_MT_RR_SYSINFO_5bis 0x05 +#define GSM48_MT_RR_SYSINFO_5ter 0x06 +#define GSM48_MT_RR_SYSINFO_9 0x04 +#define GSM48_MT_RR_SYSINFO_13 0x00 + +#define GSM48_MT_RR_SYSINFO_16 0x3d +#define GSM48_MT_RR_SYSINFO_17 0x3e + +#define GSM48_MT_RR_CHAN_MODE_MODIF 0x10 +#define GSM48_MT_RR_STATUS 0x12 +#define GSM48_MT_RR_CHAN_MODE_MODIF_ACK 0x17 +#define GSM48_MT_RR_FREQ_REDEF 0x14 +#define GSM48_MT_RR_MEAS_REP 0x15 +#define GSM48_MT_RR_CLSM_CHG 0x16 +#define GSM48_MT_RR_CLSM_ENQ 0x13 +#define GSM48_MT_RR_EXT_MEAS_REP 0x36 +#define GSM48_MT_RR_EXT_MEAS_REP_ORD 0x37 +#define GSM48_MT_RR_GPRS_SUSP_REQ 0x34 + +#define GSM48_MT_RR_VGCS_UPL_GRANT 0x08 +#define GSM48_MT_RR_UPLINK_RELEASE 0x0e +#define GSM48_MT_RR_UPLINK_FREE 0x0c +#define GSM48_MT_RR_UPLINK_BUSY 0x2a +#define GSM48_MT_RR_TALKER_IND 0x11 + +#define GSM48_MT_RR_APP_INFO 0x38 + +/* Table 10.2/3GPP TS 04.08 */ +#define GSM48_MT_MM_IMSI_DETACH_IND 0x01 +#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02 +#define GSM48_MT_MM_LOC_UPD_REJECT 0x04 +#define GSM48_MT_MM_LOC_UPD_REQUEST 0x08 + +#define GSM48_MT_MM_AUTH_REJ 0x11 +#define GSM48_MT_MM_AUTH_REQ 0x12 +#define GSM48_MT_MM_AUTH_RESP 0x14 +#define GSM48_MT_MM_ID_REQ 0x18 +#define GSM48_MT_MM_ID_RESP 0x19 +#define GSM48_MT_MM_TMSI_REALL_CMD 0x1a +#define GSM48_MT_MM_TMSI_REALL_COMPL 0x1b + +#define GSM48_MT_MM_CM_SERV_ACC 0x21 +#define GSM48_MT_MM_CM_SERV_REJ 0x22 +#define GSM48_MT_MM_CM_SERV_ABORT 0x23 +#define GSM48_MT_MM_CM_SERV_REQ 0x24 +#define GSM48_MT_MM_CM_SERV_PROMPT 0x25 +#define GSM48_MT_MM_CM_REEST_REQ 0x28 +#define GSM48_MT_MM_ABORT 0x29 + +#define GSM48_MT_MM_NULL 0x30 +#define GSM48_MT_MM_STATUS 0x31 +#define GSM48_MT_MM_INFO 0x32 + +/* Table 10.3/3GPP TS 04.08 */ +#define GSM48_MT_CC_ALERTING 0x01 +#define GSM48_MT_CC_CALL_CONF 0x08 +#define GSM48_MT_CC_CALL_PROC 0x02 +#define GSM48_MT_CC_CONNECT 0x07 +#define GSM48_MT_CC_CONNECT_ACK 0x0f +#define GSM48_MT_CC_EMERG_SETUP 0x0e +#define GSM48_MT_CC_PROGRESS 0x03 +#define GSM48_MT_CC_ESTAB 0x04 +#define GSM48_MT_CC_ESTAB_CONF 0x06 +#define GSM48_MT_CC_RECALL 0x0b +#define GSM48_MT_CC_START_CC 0x09 +#define GSM48_MT_CC_SETUP 0x05 + +#define GSM48_MT_CC_MODIFY 0x17 +#define GSM48_MT_CC_MODIFY_COMPL 0x1f +#define GSM48_MT_CC_MODIFY_REJECT 0x13 +#define GSM48_MT_CC_USER_INFO 0x10 +#define GSM48_MT_CC_HOLD 0x18 +#define GSM48_MT_CC_HOLD_ACK 0x19 +#define GSM48_MT_CC_HOLD_REJ 0x1a +#define GSM48_MT_CC_RETR 0x1c +#define GSM48_MT_CC_RETR_ACK 0x1d +#define GSM48_MT_CC_RETR_REJ 0x1e + +#define GSM48_MT_CC_DISCONNECT 0x25 +#define GSM48_MT_CC_RELEASE 0x2d +#define GSM48_MT_CC_RELEASE_COMPL 0x2a + +#define GSM48_MT_CC_CONG_CTRL 0x39 +#define GSM48_MT_CC_NOTIFY 0x3e +#define GSM48_MT_CC_STATUS 0x3d +#define GSM48_MT_CC_STATUS_ENQ 0x34 +#define GSM48_MT_CC_START_DTMF 0x35 +#define GSM48_MT_CC_STOP_DTMF 0x31 +#define GSM48_MT_CC_STOP_DTMF_ACK 0x32 +#define GSM48_MT_CC_START_DTMF_ACK 0x36 +#define GSM48_MT_CC_START_DTMF_REJ 0x37 +#define GSM48_MT_CC_FACILITY 0x3a + +/* FIXME: Table 10.4 / 10.4a (GPRS) */ + +/* Section 10.5.3.3 CM service type */ +#define GSM48_CMSERV_MO_CALL_PACKET 1 +#define GSM48_CMSERV_EMERGENCY 2 +#define GSM48_CMSERV_SMS 4 +#define GSM48_CMSERV_SUP_SERV 8 +#define GSM48_CMSERV_VGCS 9 +#define GSM48_CMSERV_VBS 10 +#define GSM48_CMSERV_LOC_SERV 11 + +/* Section 10.5.2.26, Table 10.5.64 */ +#define GSM48_PM_MASK 0x03 +#define GSM48_PM_NORMAL 0x00 +#define GSM48_PM_EXTENDED 0x01 +#define GSM48_PM_REORG 0x02 +#define GSM48_PM_SAME 0x03 + +/* Chapter 10.5.3.5 / Table 10.5.93 */ +#define GSM48_LUPD_NORMAL 0x0 +#define GSM48_LUPD_PERIODIC 0x1 +#define GSM48_LUPD_IMSI_ATT 0x2 +#define GSM48_LUPD_RESERVED 0x3 + +/* Table 10.5.4 */ +#define GSM_MI_TYPE_MASK 0x07 +#define GSM_MI_TYPE_NONE 0x00 +#define GSM_MI_TYPE_IMSI 0x01 +#define GSM_MI_TYPE_IMEI 0x02 +#define GSM_MI_TYPE_IMEISV 0x03 +#define GSM_MI_TYPE_TMSI 0x04 +#define GSM_MI_ODD 0x08 + +#define GSM48_IE_MOBILE_ID 0x17 /* 10.5.1.4 */ +#define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */ +#define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */ +#define GSM48_IE_UTC 0x46 /* 10.5.3.8 */ +#define GSM48_IE_NET_TIME_TZ 0x47 /* 10.5.3.9 */ +#define GSM48_IE_LSA_IDENT 0x48 /* 10.5.3.11 */ + +#define GSM48_IE_BEARER_CAP 0x04 /* 10.5.4.5 */ +#define GSM48_IE_CAUSE 0x08 /* 10.5.4.11 */ +#define GSM48_IE_CC_CAP 0x15 /* 10.5.4.5a */ +#define GSM48_IE_ALERT 0x19 /* 10.5.4.26 */ +#define GSM48_IE_FACILITY 0x1c /* 10.5.4.15 */ +#define GSM48_IE_PROGR_IND 0x1e /* 10.5.4.21 */ +#define GSM48_IE_AUX_STATUS 0x24 /* 10.5.4.4 */ +#define GSM48_IE_NOTIFY 0x27 /* 10.5.4.20 */ +#define GSM48_IE_KPD_FACILITY 0x2c /* 10.5.4.17 */ +#define GSM48_IE_SIGNAL 0x34 /* 10.5.4.23 */ +#define GSM48_IE_CONN_BCD 0x4c /* 10.5.4.13 */ +#define GSM48_IE_CONN_SUB 0x4d /* 10.5.4.14 */ +#define GSM48_IE_CALLING_BCD 0x5c /* 10.5.4.9 */ +#define GSM48_IE_CALLING_SUB 0x5d /* 10.5.4.10 */ +#define GSM48_IE_CALLED_BCD 0x5e /* 10.5.4.7 */ +#define GSM48_IE_CALLED_SUB 0x6d /* 10.5.4.8 */ +#define GSM48_IE_REDIR_BCD 0x74 /* 10.5.4.21a */ +#define GSM48_IE_REDIR_SUB 0x75 /* 10.5.4.21b */ +#define GSM48_IE_LOWL_COMPAT 0x7c /* 10.5.4.18 */ +#define GSM48_IE_HIGHL_COMPAT 0x7d /* 10.5.4.16 */ +#define GSM48_IE_USER_USER 0x7e /* 10.5.4.25 */ +#define GSM48_IE_SS_VERS 0x7f /* 10.5.4.24 */ +#define GSM48_IE_MORE_DATA 0xa0 /* 10.5.4.19 */ +#define GSM48_IE_CLIR_SUPP 0xa1 /* 10.5.4.11a */ +#define GSM48_IE_CLIR_INVOC 0xa2 /* 10.5.4.11b */ +#define GSM48_IE_REV_C_SETUP 0xa3 /* 10.5.4.22a */ +#define GSM48_IE_REPEAT_CIR 0xd1 /* 10.5.4.22 */ +#define GSM48_IE_REPEAT_SEQ 0xd3 /* 10.5.4.22 */ + +/* Section 10.5.4.11 / Table 10.5.122 */ +#define GSM48_CAUSE_CS_GSM 0x60 + +/* Section 9.1.2 / Table 9.3 */ +/* RR elements */ +#define GSM48_IE_VGCS_TARGET 0x01 +//#define GSM48_IE_VGCS_T_MODE_I 0x01 +#define GSM48_IE_FRQSHORT_AFTER 0x02 +#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */ +#define GSM48_IE_FREQ_L_AFTER 0x05 +#define GSM48_IE_MSLOT_DESC 0x10 +#define GSM48_IE_CHANMODE_2 0x11 +#define GSM48_IE_FRQSHORT_BEFORE 0x12 +//#define GSM48_IE_FRQSHORT_BEFOR 0x12 +#define GSM48_IE_CHANMODE_3 0x13 +#define GSM48_IE_CHANMODE_4 0x14 +#define GSM48_IE_CHANMODE_5 0x15 +#define GSM48_IE_CHANMODE_6 0x16 +#define GSM48_IE_CHANMODE_7 0x17 +#define GSM48_IE_CHANMODE_8 0x18 +#define GSM48_IE_CHANDESC_2 0x64 +#define GSM48_IE_MA_AFTER 0x72 +#define GSM48_IE_START_TIME 0x7c +#define GSM48_IE_FREQ_L_BEFORE 0x19 +//#define GSM48_IE_FRQLIST_BEFORE 0x19 +#define GSM48_IE_CH_DESC_1_BEFORE 0x1c +//#define GSM48_IE_CHDES_1_BEFORE 0x1c +#define GSM48_IE_CH_DESC_2_BEFORE 0x1d +//#define GSM48_IE_CHDES_2_BEFORE 0x1d +#define GSM48_IE_F_CH_SEQ_BEFORE 0x1e +//#define GSM48_IE_FRQSEQ_BEFORE 0x1e +#define GSM48_IE_CLASSMARK3 0x20 +#define GSM48_IE_MA_BEFORE 0x21 +#define GSM48_IE_RR_PACKET_UL 0x22 +#define GSM48_IE_RR_PACKET_DL 0x23 +#define GSM48_IE_CELL_CH_DESC 0x62 +#define GSM48_IE_CHANMODE_1 0x63 +#define GSM48_IE_CHDES_2_AFTER 0x64 +#define GSM48_IE_MODE_SEC_CH 0x66 +#define GSM48_IE_F_CH_SEQ_AFTER 0x69 +#define GSM48_IE_MA_AFTER 0x72 +#define GSM48_IE_BA_RANGE 0x73 +#define GSM48_IE_GROUP_CHDES 0x74 +#define GSM48_IE_BA_LIST_PREF 0x75 +#define GSM48_IE_MOB_OVSERV_DIF 0x77 +#define GSM48_IE_REALTIME_DIFF 0x7b +#define GSM48_IE_START_TIME 0x7c +#define GSM48_IE_TIMING_ADVANCE 0x7d +#define GSM48_IE_GROUP_CIP_SEQ 0x80 +#define GSM48_IE_CIP_MODE_SET 0x90 +#define GSM48_IE_GPRS_RESUMPT 0xc0 +#define GSM48_IE_SYNC_IND 0xd0 +/* System Information 4 (types are equal IEs above) */ +#define GSM48_IE_CBCH_CHAN_DESC 0x64 +#define GSM48_IE_CBCH_MOB_AL 0x72 + +/* Additional MM elements */ +#define GSM48_IE_LOCATION_AREA 0x13 +#define GSM48_IE_PRIORITY_LEV 0x80 +#define GSM48_IE_FOLLOW_ON_PROC 0xa1 +#define GSM48_IE_CTS_PERMISSION 0xa2 + +/* Section 10.5.4.23 / Table 10.5.130 */ +enum gsm48_signal_val { + GSM48_SIGNAL_DIALTONE = 0x00, + GSM48_SIGNAL_RINGBACK = 0x01, + GSM48_SIGNAL_INTERCEPT = 0x02, + GSM48_SIGNAL_NET_CONG = 0x03, + GSM48_SIGNAL_BUSY = 0x04, + GSM48_SIGNAL_CONFIRM = 0x05, + GSM48_SIGNAL_ANSWER = 0x06, + GSM48_SIGNAL_CALL_WAIT = 0x07, + GSM48_SIGNAL_OFF_HOOK = 0x08, + GSM48_SIGNAL_OFF = 0x3f, + GSM48_SIGNAL_ALERT_OFF = 0x4f, +}; + +enum gsm48_cause_loc { + GSM48_CAUSE_LOC_USER = 0x00, + GSM48_CAUSE_LOC_PRN_S_LU = 0x01, + GSM48_CAUSE_LOC_PUN_S_LU = 0x02, + GSM48_CAUSE_LOC_TRANS_NET = 0x03, + GSM48_CAUSE_LOC_PUN_S_RU = 0x04, + GSM48_CAUSE_LOC_PRN_S_RU = 0x05, + /* not defined */ + GSM48_CAUSE_LOC_INN_NET = 0x07, + GSM48_CAUSE_LOC_NET_BEYOND = 0x0a, +}; + +/* Section 10.5.2.31 RR Cause / Table 10.5.70 */ +enum gsm48_rr_cause { + GSM48_RR_CAUSE_NORMAL = 0x00, + GSM48_RR_CAUSE_ABNORMAL_UNSPEC = 0x01, + GSM48_RR_CAUSE_ABNORMAL_UNACCT = 0x02, + GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03, + GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04, + GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05, + GSM48_RR_CAUSE_HNDOVER_IMP = 0x06, + GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x07, + GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x08, + GSM48_RR_CAUSE_CALL_CLEARED = 0x41, + GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f, + GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60, + GSM48_RR_CAUSE_MSG_TYPE_N = 0x61, + GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT= 0x62, + GSM48_RR_CAUSE_COND_IE_ERROR = 0x64, + GSM48_RR_CAUSE_NO_CELL_ALLOC_A = 0x65, + GSM48_RR_CAUSE_PROT_ERROR_UNSPC = 0x6f, +}; + +/* Section 10.5.4.11 CC Cause / Table 10.5.123 */ +enum gsm48_cc_cause { + GSM48_CC_CAUSE_UNASSIGNED_NR = 1, + GSM48_CC_CAUSE_NO_ROUTE = 3, + GSM48_CC_CAUSE_CHAN_UNACCEPT = 6, + GSM48_CC_CAUSE_OP_DET_BARRING = 8, + GSM48_CC_CAUSE_NORM_CALL_CLEAR = 16, + GSM48_CC_CAUSE_USER_BUSY = 17, + GSM48_CC_CAUSE_USER_NOTRESPOND = 18, + GSM48_CC_CAUSE_USER_ALERTING_NA = 19, + GSM48_CC_CAUSE_CALL_REJECTED = 21, + GSM48_CC_CAUSE_NUMBER_CHANGED = 22, + GSM48_CC_CAUSE_PRE_EMPTION = 25, + GSM48_CC_CAUSE_NONSE_USER_CLR = 26, + GSM48_CC_CAUSE_DEST_OOO = 27, + GSM48_CC_CAUSE_INV_NR_FORMAT = 28, + GSM48_CC_CAUSE_FACILITY_REJ = 29, + GSM48_CC_CAUSE_RESP_STATUS_INQ = 30, + GSM48_CC_CAUSE_NORMAL_UNSPEC = 31, + GSM48_CC_CAUSE_NO_CIRCUIT_CHAN = 34, + GSM48_CC_CAUSE_NETWORK_OOO = 38, + GSM48_CC_CAUSE_TEMP_FAILURE = 41, + GSM48_CC_CAUSE_SWITCH_CONG = 42, + GSM48_CC_CAUSE_ACC_INF_DISCARD = 43, + GSM48_CC_CAUSE_REQ_CHAN_UNAVAIL = 44, + GSM48_CC_CAUSE_RESOURCE_UNAVAIL = 47, + GSM48_CC_CAUSE_QOS_UNAVAIL = 49, + GSM48_CC_CAUSE_REQ_FAC_NOT_SUBSC= 50, + GSM48_CC_CAUSE_INC_BARRED_CUG = 55, + GSM48_CC_CAUSE_BEARER_CAP_UNAUTH= 57, + GSM48_CC_CAUSE_BEARER_CA_UNAVAIL= 58, + GSM48_CC_CAUSE_SERV_OPT_UNAVAIL = 63, + GSM48_CC_CAUSE_BEARERSERV_UNIMPL= 65, + GSM48_CC_CAUSE_ACM_GE_ACM_MAX = 68, + GSM48_CC_CAUSE_REQ_FAC_NOTIMPL = 69, + GSM48_CC_CAUSE_RESTR_BCAP_AVAIL = 70, + GSM48_CC_CAUSE_SERV_OPT_UNIMPL = 79, + GSM48_CC_CAUSE_INVAL_TRANS_ID = 81, + GSM48_CC_CAUSE_USER_NOT_IN_CUG = 87, + GSM48_CC_CAUSE_INCOMPAT_DEST = 88, + GSM48_CC_CAUSE_INVAL_TRANS_NET = 91, + GSM48_CC_CAUSE_SEMANTIC_INCORR = 95, + GSM48_CC_CAUSE_INVAL_MAND_INF = 96, + GSM48_CC_CAUSE_MSGTYPE_NOTEXIST = 97, + GSM48_CC_CAUSE_MSGTYPE_INCOMPAT = 98, + GSM48_CC_CAUSE_IE_NOTEXIST = 99, + GSM48_CC_CAUSE_COND_IE_ERR = 100, + GSM48_CC_CAUSE_MSG_INCOMP_STATE = 101, + GSM48_CC_CAUSE_RECOVERY_TIMER = 102, + GSM48_CC_CAUSE_PROTO_ERR = 111, + GSM48_CC_CAUSE_INTERWORKING = 127, +}; + +/* Annex G, GSM specific cause values for mobility management */ +enum gsm48_reject_value { + GSM48_REJECT_IMSI_UNKNOWN_IN_HLR = 2, + GSM48_REJECT_ILLEGAL_MS = 3, + GSM48_REJECT_IMSI_UNKNOWN_IN_VLR = 4, + GSM48_REJECT_IMEI_NOT_ACCEPTED = 5, + GSM48_REJECT_ILLEGAL_ME = 6, + GSM48_REJECT_PLMN_NOT_ALLOWED = 11, + GSM48_REJECT_LOC_NOT_ALLOWED = 12, + GSM48_REJECT_ROAMING_NOT_ALLOWED = 13, + GSM48_REJECT_NETWORK_FAILURE = 17, + GSM48_REJECT_CONGESTION = 22, + GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32, + GSM48_REJECT_RQD_SRV_OPT_NOT_SUPPORTED = 33, + GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER = 34, + GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38, + GSM48_REJECT_INCORRECT_MESSAGE = 95, + GSM48_REJECT_INVALID_MANDANTORY_INF = 96, + GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED = 97, + GSM48_REJECT_MSG_TYPE_NOT_COMPATIBLE = 98, + GSM48_REJECT_INF_ELEME_NOT_IMPLEMENTED = 99, + GSM48_REJECT_CONDTIONAL_IE_ERROR = 100, + GSM48_REJECT_MSG_NOT_COMPATIBLE = 101, + GSM48_REJECT_PROTOCOL_ERROR = 111, + + /* according to G.6 Additional cause codes for GMM */ + GSM48_REJECT_GPRS_NOT_ALLOWED = 7, + GSM48_REJECT_SERVICES_NOT_ALLOWED = 8, + GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE = 9, + GSM48_REJECT_IMPLICITLY_DETACHED = 10, + GSM48_REJECT_GPRS_NOT_ALLOWED_IN_PLMN = 14, + GSM48_REJECT_MSC_TMP_NOT_REACHABLE = 16, +}; + +enum chreq_type { + CHREQ_T_EMERG_CALL, + CHREQ_T_CALL_REEST_TCH_F, + CHREQ_T_CALL_REEST_TCH_H, + CHREQ_T_CALL_REEST_TCH_H_DBL, + CHREQ_T_SDCCH, + CHREQ_T_TCH_F, + CHREQ_T_VOICE_CALL_TCH_H, + CHREQ_T_DATA_CALL_TCH_H, + CHREQ_T_LOCATION_UPD, + CHREQ_T_PAG_R_ANY_NECI0, + CHREQ_T_PAG_R_ANY_NECI1, + CHREQ_T_PAG_R_TCH_F, + CHREQ_T_PAG_R_TCH_FH, + CHREQ_T_LMU, + CHREQ_T_RESERVED_SDCCH, + CHREQ_T_RESERVED_IGNORE, +}; + +/* Chapter 11.3 */ +#define GSM48_T301 180, 0 +#define GSM48_T303 30, 0 +#define GSM48_T305 30, 0 +#define GSM48_T306 30, 0 +#define GSM48_T308 10, 0 +#define GSM48_T310 180, 0 +#define GSM48_T313 30, 0 +#define GSM48_T323 30, 0 +#define GSM48_T331 30, 0 +#define GSM48_T333 30, 0 +#define GSM48_T334 25, 0 /* min 15 */ +#define GSM48_T338 30, 0 +#define GSM48_T303_MS 30, 0 +#define GSM48_T305_MS 30, 0 +#define GSM48_T308_MS 30, 0 +#define GSM48_T310_MS 30, 0 +#define GSM48_T313_MS 30, 0 +#define GSM48_T323_MS 30, 0 +#define GSM48_T332_MS 30, 0 +#define GSM48_T335_MS 30, 0 + +/* Chapter 5.1.2.2 */ +#define GSM_CSTATE_NULL 0 +#define GSM_CSTATE_INITIATED 1 +#define GSM_CSTATE_MM_CONNECTION_PEND 2 /* see 10.5.4.6 */ +#define GSM_CSTATE_MO_CALL_PROC 3 +#define GSM_CSTATE_CALL_DELIVERED 4 +#define GSM_CSTATE_CALL_PRESENT 6 +#define GSM_CSTATE_CALL_RECEIVED 7 +#define GSM_CSTATE_CONNECT_REQUEST 8 +#define GSM_CSTATE_MO_TERM_CALL_CONF 9 +#define GSM_CSTATE_ACTIVE 10 +#define GSM_CSTATE_DISCONNECT_REQ 12 +#define GSM_CSTATE_DISCONNECT_IND 12 +#define GSM_CSTATE_RELEASE_REQ 19 +#define GSM_CSTATE_MO_ORIG_MODIFY 26 +#define GSM_CSTATE_MO_TERM_MODIFY 27 +#define GSM_CSTATE_CONNECT_IND 28 + +#define SBIT(a) (1 << a) +#define ALL_STATES 0xffffffff + +/* Table 10.5.3/3GPP TS 04.08: Location Area Identification information element */ +#define GSM_LAC_RESERVED_DETACHED 0x0 +#define GSM_LAC_RESERVED_ALL_BTS 0xfffe + +/* GSM 04.08 Bearer Capability: Information Transfer Capability */ +enum gsm48_bcap_itcap { + GSM48_BCAP_ITCAP_SPEECH = 0, + GSM48_BCAP_ITCAP_UNR_DIG_INF = 1, + GSM48_BCAP_ITCAP_3k1_AUDIO = 2, + GSM48_BCAP_ITCAP_FAX_G3 = 3, + GSM48_BCAP_ITCAP_OTHER = 5, + GSM48_BCAP_ITCAP_RESERVED = 7, +}; + +/* GSM 04.08 Bearer Capability: Transfer Mode */ +enum gsm48_bcap_tmod { + GSM48_BCAP_TMOD_CIRCUIT = 0, + GSM48_BCAP_TMOD_PACKET = 1, +}; + +/* GSM 04.08 Bearer Capability: Coding Standard */ +enum gsm48_bcap_coding { + GSM48_BCAP_CODING_GSM_STD = 0, +}; + +/* GSM 04.08 Bearer Capability: Radio Channel Requirements */ +enum gsm48_bcap_rrq { + GSM48_BCAP_RRQ_FR_ONLY = 1, + GSM48_BCAP_RRQ_DUAL_HR = 2, + GSM48_BCAP_RRQ_DUAL_FR = 3, +}; + +#define GSM48_TMSI_LEN 5 +#define GSM48_MID_TMSI_LEN (GSM48_TMSI_LEN + 2) +#define GSM48_MI_SIZE 32 + +/* Chapter 10.4.4.15 */ +struct gsm48_ra_id { + uint8_t digits[3]; /* MCC + MNC BCD digits */ + uint16_t lac; /* Location Area Code */ + uint8_t rac; /* Routing Area Code */ +} __attribute__ ((packed)); + + + +#endif /* PROTO_GSM_04_08_H */ diff --git a/include/osmocom/gsm/protocol/gsm_04_11.h b/include/osmocom/gsm/protocol/gsm_04_11.h new file mode 100644 index 00000000..c6a2b193 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_04_11.h @@ -0,0 +1,188 @@ +#ifndef PROTO_GSM_04_11_H +#define PROTO_GSM_04_11_H + +#include + +/* GSM TS 04.11 definitions */ + +/* Chapter 5.2.3: SMC-CS states at the network side */ +enum gsm411_cp_state { + GSM411_CPS_IDLE = 0, + GSM411_CPS_MM_CONN_PENDING = 1, /* only MT ! */ + GSM411_CPS_WAIT_CP_ACK = 2, + GSM411_CPS_MM_ESTABLISHED = 3, +}; + +/* Chapter 6.2.2: SMR states at the network side */ +enum gsm411_rp_state { + GSM411_RPS_IDLE = 0, + GSM411_RPS_WAIT_FOR_RP_ACK = 1, + GSM411_RPS_WAIT_TO_TX_RP_ACK = 3, +}; + +/* Chapter 8.1.2 (refers to GSM 04.07 Chapter 11.2.3.1.1 */ +#define GSM411_PDISC_SMS 0x09 + +/* Chapter 8.1.3 */ +#define GSM411_MT_CP_DATA 0x01 +#define GSM411_MT_CP_ACK 0x04 +#define GSM411_MT_CP_ERROR 0x10 + +enum gsm411_cp_ie { + GSM411_CP_IE_USER_DATA = 0x01, /* 8.1.4.1 */ + GSM411_CP_IE_CAUSE = 0x02, /* 8.1.4.2. */ +}; + +/* Section 8.1.4.2 / Table 8.2 */ +enum gsm411_cp_cause { + GSM411_CP_CAUSE_NET_FAIL = 17, + GSM411_CP_CAUSE_CONGESTION = 22, + GSM411_CP_CAUSE_INV_TRANS_ID = 81, + GSM411_CP_CAUSE_SEMANT_INC_MSG = 95, + GSM411_CP_CAUSE_INV_MAND_INF = 96, + GSM411_CP_CAUSE_MSGTYPE_NOTEXIST= 97, + GSM411_CP_CAUSE_MSG_INCOMP_STATE= 98, + GSM411_CP_CAUSE_IE_NOTEXIST = 99, + GSM411_CP_CAUSE_PROTOCOL_ERR = 111, +}; + +/* Chapter 8.2.2 */ +#define GSM411_MT_RP_DATA_MO 0x00 +#define GSM411_MT_RP_DATA_MT 0x01 +#define GSM411_MT_RP_ACK_MO 0x02 +#define GSM411_MT_RP_ACK_MT 0x03 +#define GSM411_MT_RP_ERROR_MO 0x04 +#define GSM411_MT_RP_ERROR_MT 0x05 +#define GSM411_MT_RP_SMMA_MO 0x06 + +enum gsm411_rp_ie { + GSM411_IE_RP_USER_DATA = 0x41, /* 8.2.5.3 */ + GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */ +}; + +/* Chapter 8.2.5.4 Table 8.4 */ +enum gsm411_rp_cause { + /* valid only for MO */ + GSM411_RP_CAUSE_MO_NUM_UNASSIGNED = 1, + GSM411_RP_CAUSE_MO_OP_DET_BARR = 8, + GSM411_RP_CAUSE_MO_CALL_BARRED = 10, + GSM411_RP_CAUSE_MO_SMS_REJECTED = 21, + GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER = 27, + GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR = 28, + GSM411_RP_CAUSE_MO_FACILITY_REJ = 29, + GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR = 30, + GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER = 38, + GSM411_RP_CAUSE_MO_TEMP_FAIL = 41, + GSM411_RP_CAUSE_MO_CONGESTION = 42, + GSM411_RP_CAUSE_MO_RES_UNAVAIL = 47, + GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR = 50, + GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL = 69, + GSM411_RP_CAUSE_MO_INTERWORKING = 127, + /* valid only for MT */ + GSM411_RP_CAUSE_MT_MEM_EXCEEDED = 22, + /* valid for both directions */ + GSM411_RP_CAUSE_INV_TRANS_REF = 81, + GSM411_RP_CAUSE_SEMANT_INC_MSG = 95, + GSM411_RP_CAUSE_INV_MAND_INF = 96, + GSM411_RP_CAUSE_MSGTYPE_NOTEXIST = 97, + GSM411_RP_CAUSE_MSG_INCOMP_STATE = 98, + GSM411_RP_CAUSE_IE_NOTEXIST = 99, + GSM411_RP_CAUSE_PROTOCOL_ERR = 111, +}; + +/* Chapter 10: Timers */ +#define GSM411_TMR_TR1M 40, 0 /* 35 < x < 45 seconds */ +#define GSM411_TMR_TRAM 30, 0 /* 25 < x < 35 seconds */ +#define GSM411_TMR_TR2M 15, 0 /* 12 < x < 20 seconds */ + +#define GSM411_TMR_TC1A 30, 0 + +/* Chapter 8.2.1 */ +struct gsm411_rp_hdr { + uint8_t len; + uint8_t msg_type; + uint8_t msg_ref; + uint8_t data[0]; +} __attribute__ ((packed)); + +/* our own enum, not related to on-air protocol */ +enum sms_alphabet { + DCS_NONE, + DCS_7BIT_DEFAULT, + DCS_UCS2, + DCS_8BIT_DATA, +}; + +/* GSM 03.40 / Chapter 9.2.3.1: TP-Message-Type-Indicator */ +#define GSM340_SMS_DELIVER_SC2MS 0x00 +#define GSM340_SMS_DELIVER_REP_MS2SC 0x00 +#define GSM340_SMS_STATUS_REP_SC2MS 0x02 +#define GSM340_SMS_COMMAND_MS2SC 0x02 +#define GSM340_SMS_SUBMIT_MS2SC 0x01 +#define GSM340_SMS_SUBMIT_REP_SC2MS 0x01 +#define GSM340_SMS_RESSERVED 0x03 + +/* GSM 03.40 / Chapter 9.2.3.2: TP-More-Messages-to-Send */ +#define GSM340_TP_MMS_MORE 0 +#define GSM340_TP_MMS_NO_MORE 1 + +/* GSM 03.40 / Chapter 9.2.3.3: TP-Validity-Period-Format */ +#define GSM340_TP_VPF_NONE 0 +#define GSM340_TP_VPF_RELATIVE 2 +#define GSM340_TP_VPF_ENHANCED 1 +#define GSM340_TP_VPF_ABSOLUTE 3 + +/* GSM 03.40 / Chapter 9.2.3.4: TP-Status-Report-Indication */ +#define GSM340_TP_SRI_NONE 0 +#define GSM340_TP_SRI_PRESENT 1 + +/* GSM 03.40 / Chapter 9.2.3.5: TP-Status-Report-Request */ +#define GSM340_TP_SRR_NONE 0 +#define GSM340_TP_SRR_REQUESTED 1 + +/* GSM 03.40 / Chapter 9.2.3.9: TP-Protocol-Identifier */ +/* telematic interworking (001 or 111 in bits 7-5) */ +#define GSM340_TP_PID_IMPLICIT 0x00 +#define GSM340_TP_PID_TELEX 0x01 +#define GSM340_TP_PID_FAX_G3 0x02 +#define GSM340_TP_PID_FAX_G4 0x03 +#define GSM340_TP_PID_VOICE 0x04 +#define GSM430_TP_PID_ERMES 0x05 +#define GSM430_TP_PID_NATIONAL_PAGING 0x06 +#define GSM430_TP_PID_VIDEOTEX 0x07 +#define GSM430_TP_PID_TELETEX_UNSPEC 0x08 +#define GSM430_TP_PID_TELETEX_PSPDN 0x09 +#define GSM430_TP_PID_TELETEX_CSPDN 0x0a +#define GSM430_TP_PID_TELETEX_PSTN 0x0b +#define GSM430_TP_PID_TELETEX_ISDN 0x0c +#define GSM430_TP_PID_TELETEX_UCI 0x0d +#define GSM430_TP_PID_MSG_HANDLING 0x10 +#define GSM430_TP_PID_MSG_X400 0x11 +#define GSM430_TP_PID_EMAIL 0x12 +#define GSM430_TP_PID_GSM_MS 0x1f +/* if bit 7 = 0 and bit 6 = 1 */ +#define GSM430_TP_PID_SMS_TYPE_0 0 +#define GSM430_TP_PID_SMS_TYPE_1 1 +#define GSM430_TP_PID_SMS_TYPE_2 2 +#define GSM430_TP_PID_SMS_TYPE_3 3 +#define GSM430_TP_PID_SMS_TYPE_4 4 +#define GSM430_TP_PID_SMS_TYPE_5 5 +#define GSM430_TP_PID_SMS_TYPE_6 6 +#define GSM430_TP_PID_SMS_TYPE_7 7 +#define GSM430_TP_PID_RETURN_CALL_MSG 0x1f +#define GSM430_TP_PID_ME_DATA_DNLOAD 0x3d +#define GSM430_TP_PID_ME_DE_PERSONAL 0x3e +#define GSM430_TP_PID_ME_SIM_DNLOAD 0x3f + +/* GSM 03.38 Chapter 4: SMS Data Coding Scheme */ +#define GSM338_DCS_00_ + +#define GSM338_DCS_1110_7BIT (0 << 2) +#define GSM338_DCS_1111_7BIT (0 << 2) +#define GSM338_DCS_1111_8BIT_DATA (1 << 2) +#define GSM338_DCS_1111_CLASS0 0 +#define GSM338_DCS_1111_CLASS1_ME 1 +#define GSM338_DCS_1111_CLASS2_SIM 2 +#define GSM338_DCS_1111_CLASS3_TE 3 /* See TS 07.05 */ + +#endif /* PROTO_GSM_04_11_H */ diff --git a/include/osmocom/gsm/protocol/gsm_04_12.h b/include/osmocom/gsm/protocol/gsm_04_12.h new file mode 100644 index 00000000..9b1538a5 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_04_12.h @@ -0,0 +1,31 @@ +#ifndef PROTO_GSM_04_12_H +#define PROTO_GSM_04_12_H + +#include + +/* GSM TS 04.12 definitions for Short Message Service Cell Broadcast */ + +#define GSM412_SEQ_FST_BLOCK 0x0 +#define GSM412_SEQ_SND_BLOCK 0x1 +#define GSM412_SEQ_TRD_BLOCK 0x2 +#define GSM412_SEQ_FTH_BLOCK 0x3 +#define GSM412_SEQ_FST_SCHED_BLOCK 0x8 +#define GSM412_SEQ_NULL_MSG 0xf + +struct gsm412_block_type { + uint8_t seq_nr : 4, + lb : 1, + lpd : 2, + spare : 1; +} __attribute__((packed)); + +struct gsm412_sched_msg { + uint8_t beg_slot_nr : 6, + type : 2; + uint8_t end_slot_nr : 6, + spare1 : 1, spare2: 1; + uint8_t cbsms_msg_map[6]; + uint8_t data[0]; +} __attribute__((packed)); + +#endif diff --git a/include/osmocom/gsm/protocol/gsm_04_80.h b/include/osmocom/gsm/protocol/gsm_04_80.h new file mode 100644 index 00000000..fa5c9451 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_04_80.h @@ -0,0 +1,126 @@ +#ifndef PROTO_GSM_04_80_H +#define PROTO_GSM_04_80_H + +/* GSM TS 04.80 definitions (Supplementary Services Specification, Formats and Coding) */ + +/* Section 3.4 */ +#define GSM0480_MTYPE_RELEASE_COMPLETE 0x2A +#define GSM0480_MTYPE_FACILITY 0x3A +#define GSM0480_MTYPE_REGISTER 0x3B + +/* Section 3.5 */ +#define GSM0480_IE_FACILITY 0x1C +#define GSM0480_IE_SS_VERSION 0x7F + +/* Section 3.6.2 */ +#define GSM0480_CTYPE_INVOKE 0xA1 +#define GSM0480_CTYPE_RETURN_RESULT 0xA2 +#define GSM0480_CTYPE_RETURN_ERROR 0xA3 +#define GSM0480_CTYPE_REJECT 0xA4 + +/* Section 3.6.3 */ +#define GSM0480_COMPIDTAG_INVOKE_ID 0x02 +#define GSM0480_COMPIDTAG_LINKED_ID 0x80 + +/* Section 3.6.4 */ +#define GSM0480_OPERATION_CODE 0x02 + +/* Section 3.6.5 */ +#define GSM_0480_SEQUENCE_TAG 0x30 +#define GSM_0480_SET_TAG 0x31 + +/* Section 3.6.6 */ +#define GSM_0480_ERROR_CODE_TAG 0x02 + +/* Section 3.6.7 */ +/* Table 3.13 */ +#define GSM_0480_PROBLEM_CODE_TAG_GENERAL 0x80 +#define GSM_0480_PROBLEM_CODE_TAG_INVOKE 0x81 +#define GSM_0480_PROBLEM_CODE_TAG_RETURN_RESULT 0x82 +#define GSM_0480_PROBLEM_CODE_TAG_RETURN_ERROR 0x83 + +/* Table 3.14 */ +#define GSM_0480_GEN_PROB_CODE_UNRECOGNISED 0x00 +#define GSM_0480_GEN_PROB_CODE_MISTYPED 0x01 +#define GSM_0480_GEN_PROB_CODE_BAD_STRUCTURE 0x02 + +/* Table 3.15 */ +#define GSM_0480_INVOKE_PROB_CODE_DUPLICATE_INVOKE_ID 0x00 +#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_OPERATION 0x01 +#define GSM_0480_INVOKE_PROB_CODE_MISTYPED_PARAMETER 0x02 +#define GSM_0480_INVOKE_PROB_CODE_RESOURCE_LIMITATION 0x03 +#define GSM_0480_INVOKE_PROB_CODE_INITIATING_RELEASE 0x04 +#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_LINKED_ID 0x05 +#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_RESPONSE 0x06 +#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_OPERATION 0x07 + +/* Table 3.16 */ +#define GSM_0480_RESULT_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00 +#define GSM_0480_RESULT_PROB_CODE_RETURN_RESULT_UNEXPECTED 0x01 +#define GSM_0480_RESULT_PROB_CODE_MISTYPED_PARAMETER 0x02 + +/* Table 3.17 */ +#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00 +#define GSM_0480_ERROR_PROB_CODE_RETURN_ERROR_UNEXPECTED 0x01 +#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_ERROR 0x02 +#define GSM_0480_ERROR_PROB_CODE_UNEXPECTED_ERROR 0x03 +#define GSM_0480_ERROR_PROB_CODE_MISTYPED_PARAMETER 0x04 + +/* Section 4.5 */ +#define GSM0480_OP_CODE_REGISTER_SS 0x0A +#define GSM0480_OP_CODE_ERASE_SS 0x0B +#define GSM0480_OP_CODE_ACTIVATE_SS 0x0C +#define GSM0480_OP_CODE_DEACTIVATE_SS 0x0D +#define GSM0480_OP_CODE_INTERROGATE_SS 0x0E +#define GSM0480_OP_CODE_NOTIFY_SS 0x10 +#define GSM0480_OP_CODE_REGISTER_PASSWORD 0x11 +#define GSM0480_OP_CODE_GET_PASSWORD 0x12 +#define GSM0480_OP_CODE_PROCESS_USS_DATA 0x13 +#define GSM0480_OP_CODE_FORWARD_CHECK_SS_IND 0x26 +#define GSM0480_OP_CODE_PROCESS_USS_REQ 0x3B +#define GSM0480_OP_CODE_USS_REQUEST 0x3C +#define GSM0480_OP_CODE_USS_NOTIFY 0x3D +#define GSM0480_OP_CODE_FORWARD_CUG_INFO 0x78 +#define GSM0480_OP_CODE_SPLIT_MPTY 0x79 +#define GSM0480_OP_CODE_RETRIEVE_MPTY 0x7A +#define GSM0480_OP_CODE_HOLD_MPTY 0x7B +#define GSM0480_OP_CODE_BUILD_MPTY 0x7C +#define GSM0480_OP_CODE_FORWARD_CHARGE_ADVICE 0x7D + +#define GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER 0x01 +#define GSM0480_ERR_CODE_ILLEGAL_SUBSCRIBER 0x09 +#define GSM0480_ERR_CODE_BEARER_SERVICE_NOT_PROVISIONED 0x0A +#define GSM0480_ERR_CODE_TELESERVICE_NOT_PROVISIONED 0x0B +#define GSM0480_ERR_CODE_ILLEGAL_EQUIPMENT 0x0C +#define GSM0480_ERR_CODE_CALL_BARRED 0x0D +#define GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION 0x10 +#define GSM0480_ERR_CODE_SS_ERROR_STATUS 0x11 +#define GSM0480_ERR_CODE_SS_NOT_AVAILABLE 0x12 +#define GSM0480_ERR_CODE_SS_SUBSCRIPTION_VIOLATION 0x13 +#define GSM0480_ERR_CODE_SS_INCOMPATIBILITY 0x14 +#define GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED 0x15 +#define GSM0480_ERR_CODE_ABSENT_SUBSCRIBER 0x1B +#define GSM0480_ERR_CODE_SYSTEM_FAILURE 0x22 +#define GSM0480_ERR_CODE_DATA_MISSING 0x23 +#define GSM0480_ERR_CODE_UNEXPECTED_DATA_VALUE 0x24 +#define GSM0480_ERR_CODE_PW_REGISTRATION_FAILURE 0x25 +#define GSM0480_ERR_CODE_NEGATIVE_PW_CHECK 0x26 +#define GSM0480_ERR_CODE_NUM_PW_ATTEMPTS_VIOLATION 0x2B +#define GSM0480_ERR_CODE_UNKNOWN_ALPHABET 0x47 +#define GSM0480_ERR_CODE_USSD_BUSY 0x48 +#define GSM0480_ERR_CODE_MAX_MPTY_PARTICIPANTS 0x7E +#define GSM0480_ERR_CODE_RESOURCES_NOT_AVAILABLE 0x7F + +/* ASN.1 type-tags */ +#define ASN1_BOOLEAN_TAG 0x01 +#define ASN1_INTEGER_TAG 0x02 +#define ASN1_BIT_STRING_TAG 0x03 +#define ASN1_OCTET_STRING_TAG 0x04 +#define ASN1_NULL_TYPE_TAG 0x05 +#define ASN1_OBJECT_ID_TAG 0x06 +#define ASN1_UTF8_STRING_TAG 0x0C +#define ASN1_PRINTABLE_STRING_TAG 0x13 +#define ASN1_IA5_STRING_TAG 0x16 +#define ASN1_UNICODE_STRING_TAG 0x1E + +#endif /* PROTO_GSM_04_80_H */ diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h new file mode 100644 index 00000000..6b8f9359 --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -0,0 +1,303 @@ +/* From GSM08.08 */ + +#ifndef GSM_0808_H +#define GSM_0808_H + +#include + +/* + * this is from GSM 03.03 CGI but is copied in GSM 08.08 + * in § 3.2.2.27 for Cell Identifier List + */ +enum CELL_IDENT { + CELL_IDENT_WHOLE_GLOBAL = 0, + CELL_IDENT_LAC_AND_CI = 1, + CELL_IDENT_CI = 2, + CELL_IDENT_NO_CELL = 3, + CELL_IDENT_LAI_AND_LAC = 4, + CELL_IDENT_LAC = 5, + CELL_IDENT_BSS = 6, + CELL_IDENT_UTRAN_PLMN_LAC_RNC = 8, + CELL_IDENT_UTRAN_RNC = 9, + CELL_IDENT_UTRAN_LAC_RNC = 10, +}; + + +/* GSM 08.06 § 6.3 */ +enum BSSAP_MSG_TYPE { + BSSAP_MSG_BSS_MANAGEMENT = 0x0, + BSSAP_MSG_DTAP = 0x1, +}; + +struct bssmap_header { + uint8_t type; + uint8_t length; +} __attribute__((packed)); + +struct dtap_header { + uint8_t type; + uint8_t link_id; + uint8_t length; +} __attribute__((packed)); + + +enum BSS_MAP_MSG_TYPE { + BSS_MAP_MSG_RESERVED_0 = 0, + + /* ASSIGNMENT MESSAGES */ + BSS_MAP_MSG_ASSIGMENT_RQST = 1, + BSS_MAP_MSG_ASSIGMENT_COMPLETE = 2, + BSS_MAP_MSG_ASSIGMENT_FAILURE = 3, + + /* HANDOVER MESSAGES */ + BSS_MAP_MSG_HANDOVER_RQST = 16, + BSS_MAP_MSG_HANDOVER_REQUIRED = 17, + BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE= 18, + BSS_MAP_MSG_HANDOVER_CMD = 19, + BSS_MAP_MSG_HANDOVER_COMPLETE = 20, + BSS_MAP_MSG_HANDOVER_SUCCEEDED = 21, + BSS_MAP_MSG_HANDOVER_FAILURE = 22, + BSS_MAP_MSG_HANDOVER_PERFORMED = 23, + BSS_MAP_MSG_HANDOVER_CANDIDATE_ENQUIRE = 24, + BSS_MAP_MSG_HANDOVER_CANDIDATE_RESPONSE = 25, + BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT = 26, + BSS_MAP_MSG_HANDOVER_DETECT = 27, + + /* RELEASE MESSAGES */ + BSS_MAP_MSG_CLEAR_CMD = 32, + BSS_MAP_MSG_CLEAR_COMPLETE = 33, + BSS_MAP_MSG_CLEAR_RQST = 34, + BSS_MAP_MSG_RESERVED_1 = 35, + BSS_MAP_MSG_RESERVED_2 = 36, + BSS_MAP_MSG_SAPI_N_REJECT = 37, + BSS_MAP_MSG_CONFUSION = 38, + + /* OTHER CONNECTION RELATED MESSAGES */ + BSS_MAP_MSG_SUSPEND = 40, + BSS_MAP_MSG_RESUME = 41, + BSS_MAP_MSG_CONNECTION_ORIENTED_INFORMATION = 42, + BSS_MAP_MSG_PERFORM_LOCATION_RQST = 43, + BSS_MAP_MSG_LSA_INFORMATION = 44, + BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE = 45, + BSS_MAP_MSG_PERFORM_LOCATION_ABORT = 46, + BSS_MAP_MSG_COMMON_ID = 47, + + /* GENERAL MESSAGES */ + BSS_MAP_MSG_RESET = 48, + BSS_MAP_MSG_RESET_ACKNOWLEDGE = 49, + BSS_MAP_MSG_OVERLOAD = 50, + BSS_MAP_MSG_RESERVED_3 = 51, + BSS_MAP_MSG_RESET_CIRCUIT = 52, + BSS_MAP_MSG_RESET_CIRCUIT_ACKNOWLEDGE = 53, + BSS_MAP_MSG_MSC_INVOKE_TRACE = 54, + BSS_MAP_MSG_BSS_INVOKE_TRACE = 55, + BSS_MAP_MSG_CONNECTIONLESS_INFORMATION = 58, + + /* TERRESTRIAL RESOURCE MESSAGES */ + BSS_MAP_MSG_BLOCK = 64, + BSS_MAP_MSG_BLOCKING_ACKNOWLEDGE = 65, + BSS_MAP_MSG_UNBLOCK = 66, + BSS_MAP_MSG_UNBLOCKING_ACKNOWLEDGE = 67, + BSS_MAP_MSG_CIRCUIT_GROUP_BLOCK = 68, + BSS_MAP_MSG_CIRCUIT_GROUP_BLOCKING_ACKNOWLEDGE = 69, + BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCK = 70, + BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCKING_ACKNOWLEDGE = 71, + BSS_MAP_MSG_UNEQUIPPED_CIRCUIT = 72, + BSS_MAP_MSG_CHANGE_CIRCUIT = 78, + BSS_MAP_MSG_CHANGE_CIRCUIT_ACKNOWLEDGE = 79, + + /* RADIO RESOURCE MESSAGES */ + BSS_MAP_MSG_RESOURCE_RQST = 80, + BSS_MAP_MSG_RESOURCE_INDICATION = 81, + BSS_MAP_MSG_PAGING = 82, + BSS_MAP_MSG_CIPHER_MODE_CMD = 83, + BSS_MAP_MSG_CLASSMARK_UPDATE = 84, + BSS_MAP_MSG_CIPHER_MODE_COMPLETE = 85, + BSS_MAP_MSG_QUEUING_INDICATION = 86, + BSS_MAP_MSG_COMPLETE_LAYER_3 = 87, + BSS_MAP_MSG_CLASSMARK_RQST = 88, + BSS_MAP_MSG_CIPHER_MODE_REJECT = 89, + BSS_MAP_MSG_LOAD_INDICATION = 90, + + /* VGCS/VBS */ + BSS_MAP_MSG_VGCS_VBS_SETUP = 4, + BSS_MAP_MSG_VGCS_VBS_SETUP_ACK = 5, + BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE = 6, + BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST = 7, + BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT = 28, + BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE = 29, + BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30, + BSS_MAP_MSG_UPLINK_RQST = 31, + BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39, + BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION = 73, + BSS_MAP_MSG_UPLINK_RELEASE_INDICATION = 74, + BSS_MAP_MSG_UPLINK_REJECT_CMD = 75, + BSS_MAP_MSG_UPLINK_RELEASE_CMD = 76, + BSS_MAP_MSG_UPLINK_SEIZED_CMD = 77, +}; + +enum GSM0808_IE_CODING { + GSM0808_IE_CIRCUIT_IDENTITY_CODE = 1, + GSM0808_IE_RESERVED_0 = 2, + GSM0808_IE_RESOURCE_AVAILABLE = 3, + GSM0808_IE_CAUSE = 4, + GSM0808_IE_CELL_IDENTIFIER = 5, + GSM0808_IE_PRIORITY = 6, + GSM0808_IE_LAYER_3_HEADER_INFORMATION = 7, + GSM0808_IE_IMSI = 8, + GSM0808_IE_TMSI = 9, + GSM0808_IE_ENCRYPTION_INFORMATION = 10, + GSM0808_IE_CHANNEL_TYPE = 11, + GSM0808_IE_PERIODICITY = 12, + GSM0808_IE_EXTENDED_RESOURCE_INDICATOR = 13, + GSM0808_IE_NUMBER_OF_MSS = 14, + GSM0808_IE_RESERVED_1 = 15, + GSM0808_IE_RESERVED_2 = 16, + GSM0808_IE_RESERVED_3 = 17, + GSM0808_IE_CLASSMARK_INFORMATION_T2 = 18, + GSM0808_IE_CLASSMARK_INFORMATION_T3 = 19, + GSM0808_IE_INTERFERENCE_BAND_TO_USE = 20, + GSM0808_IE_RR_CAUSE = 21, + GSM0808_IE_RESERVED_4 = 22, + GSM0808_IE_LAYER_3_INFORMATION = 23, + GSM0808_IE_DLCI = 24, + GSM0808_IE_DOWNLINK_DTX_FLAG = 25, + GSM0808_IE_CELL_IDENTIFIER_LIST = 26, + GSM0808_IE_RESPONSE_RQST = 27, + GSM0808_IE_RESOURCE_INDICATION_METHOD = 28, + GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1 = 29, + GSM0808_IE_CIRCUIT_IDENTITY_CODE_LIST = 30, + GSM0808_IE_DIAGNOSTIC = 31, + GSM0808_IE_LAYER_3_MESSAGE_CONTENTS = 32, + GSM0808_IE_CHOSEN_CHANNEL = 33, + GSM0808_IE_TOTAL_RESOURCE_ACCESSIBLE = 34, + GSM0808_IE_CIPHER_RESPONSE_MODE = 35, + GSM0808_IE_CHANNEL_NEEDED = 36, + GSM0808_IE_TRACE_TYPE = 37, + GSM0808_IE_TRIGGERID = 38, + GSM0808_IE_TRACE_REFERENCE = 39, + GSM0808_IE_TRANSACTIONID = 40, + GSM0808_IE_MOBILE_IDENTITY = 41, + GSM0808_IE_OMCID = 42, + GSM0808_IE_FORWARD_INDICATOR = 43, + GSM0808_IE_CHOSEN_ENCR_ALG = 44, + GSM0808_IE_CIRCUIT_POOL = 45, + GSM0808_IE_CIRCUIT_POOL_LIST = 46, + GSM0808_IE_TIME_INDICATION = 47, + GSM0808_IE_RESOURCE_SITUATION = 48, + GSM0808_IE_CURRENT_CHANNEL_TYPE_1 = 49, + GSM0808_IE_QUEUEING_INDICATOR = 50, + GSM0808_IE_SPEECH_VERSION = 64, + GSM0808_IE_ASSIGNMENT_REQUIREMENT = 51, + GSM0808_IE_TALKER_FLAG = 53, + GSM0808_IE_CONNECTION_RELEASE_RQSTED = 54, + GSM0808_IE_GROUP_CALL_REFERENCE = 55, + GSM0808_IE_EMLPP_PRIORITY = 56, + GSM0808_IE_CONFIG_EVO_INDI = 57, + GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION = 58, + GSM0808_IE_LSA_IDENTIFIER = 59, + GSM0808_IE_LSA_IDENTIFIER_LIST = 60, + GSM0808_IE_LSA_INFORMATION = 61, + GSM0808_IE_LCS_QOS = 62, + GSM0808_IE_LSA_ACCESS_CTRL_SUPPR = 63, + GSM0808_IE_LCS_PRIORITY = 67, + GSM0808_IE_LOCATION_TYPE = 68, + GSM0808_IE_LOCATION_ESTIMATE = 69, + GSM0808_IE_POSITIONING_DATA = 70, + GSM0808_IE_LCS_CAUSE = 71, + GSM0808_IE_LCS_CLIENT_TYPE = 72, + GSM0808_IE_APDU = 73, + GSM0808_IE_NETWORK_ELEMENT_IDENTITY = 74, + GSM0808_IE_GPS_ASSISTANCE_DATA = 75, + GSM0808_IE_DECIPHERING_KEYS = 76, + GSM0808_IE_RETURN_ERROR_RQST = 77, + GSM0808_IE_RETURN_ERROR_CAUSE = 78, + GSM0808_IE_SEGMENTATION = 79, + GSM0808_IE_SERVICE_HANDOVER = 80, + GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS = 81, + GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82, + GSM0808_IE_RESERVED_5 = 65, + GSM0808_IE_RESERVED_6 = 66, +}; + +enum gsm0808_cause { + GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE = 0, + GSM0808_CAUSE_RADIO_INTERFACE_FAILURE = 1, + GSM0808_CAUSE_UPLINK_QUALITY = 2, + GSM0808_CAUSE_UPLINK_STRENGTH = 3, + GSM0808_CAUSE_DOWNLINK_QUALITY = 4, + GSM0808_CAUSE_DOWNLINK_STRENGTH = 5, + GSM0808_CAUSE_DISTANCE = 6, + GSM0808_CAUSE_O_AND_M_INTERVENTION = 7, + GSM0808_CAUSE_RESPONSE_TO_MSC_INVOCATION = 8, + GSM0808_CAUSE_CALL_CONTROL = 9, + GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION = 10, + GSM0808_CAUSE_HANDOVER_SUCCESSFUL = 11, + GSM0808_CAUSE_BETTER_CELL = 12, + GSM0808_CAUSE_DIRECTED_RETRY = 13, + GSM0808_CAUSE_JOINED_GROUP_CALL_CHANNEL = 14, + GSM0808_CAUSE_TRAFFIC = 15, + GSM0808_CAUSE_EQUIPMENT_FAILURE = 32, + GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE = 33, + GSM0808_CAUSE_RQSTED_TERRESTRIAL_RESOURCE_UNAVAILABLE = 34, + GSM0808_CAUSE_CCCH_OVERLOAD = 35, + GSM0808_CAUSE_PROCESSOR_OVERLOAD = 36, + GSM0808_CAUSE_BSS_NOT_EQUIPPED = 37, + GSM0808_CAUSE_MS_NOT_EQUIPPED = 38, + GSM0808_CAUSE_INVALID_CELL = 39, + GSM0808_CAUSE_TRAFFIC_LOAD = 40, + GSM0808_CAUSE_PREEMPTION = 41, + GSM0808_CAUSE_RQSTED_TRANSCODING_RATE_ADAPTION_UNAVAILABLE = 48, + GSM0808_CAUSE_CIRCUIT_POOL_MISMATCH = 49, + GSM0808_CAUSE_SWITCH_CIRCUIT_POOL = 50, + GSM0808_CAUSE_RQSTED_SPEECH_VERSION_UNAVAILABLE = 51, + GSM0808_CAUSE_LSA_NOT_ALLOWED = 52, + GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED = 64, + GSM0808_CAUSE_TERRESTRIAL_CIRCUIT_ALREADY_ALLOCATED = 80, + GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS = 81, + GSM0808_CAUSE_INFORMATION_ELEMENT_OR_FIELD_MISSING = 82, + GSM0808_CAUSE_INCORRECT_VALUE = 83, + GSM0808_CAUSE_UNKNOWN_MESSAGE_TYPE = 84, + GSM0808_CAUSE_UNKNOWN_INFORMATION_ELEMENT = 85, + GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC = 96, +}; + +/* GSM 08.08 3.2.2.11 Channel Type */ +enum gsm0808_chan_indicator { + GSM0808_CHAN_SPEECH = 1, + GSM0808_CHAN_DATA = 2, + GSM0808_CHAN_SIGN = 3, +}; + +enum gsm0808_chan_rate_type_data { + GSM0808_DATA_FULL_BM = 0x8, + GSM0808_DATA_HALF_LM = 0x9, + GSM0808_DATA_FULL_RPREF = 0xa, + GSM0808_DATA_HALF_PREF = 0xb, + GSM0808_DATA_FULL_PREF_NO_CHANGE = 0x1a, + GSM0808_DATA_HALF_PREF_NO_CHANGE = 0x1b, + GSM0808_DATA_MULTI_MASK = 0x20, + GSM0808_DATA_MULTI_MASK_NO_CHANGE = 0x30, +}; + +enum gsm0808_chan_rate_type_speech { + GSM0808_SPEECH_FULL_BM = 0x8, + GSM0808_SPEECH_HALF_LM = 0x9, + GSM0808_SPEECH_FULL_PREF= 0xa, + GSM0808_SPEECH_HALF_PREF= 0xb, + GSM0808_SPEECH_FULL_PREF_NO_CHANGE = 0x1a, + GSM0808_SPEECH_HALF_PREF_NO_CHANGE = 0x1b, + GSM0808_SPEECH_PERM = 0xf, + GSM0808_SPEECH_PERM_NO_CHANGE = 0x1f, +}; + +enum gsm0808_permitted_speech { + GSM0808_PERM_FR1 = 0x01, + GSM0808_PERM_FR2 = 0x11, + GSM0808_PERM_FR3 = 0x21, + GSM0808_PERM_HR1 = GSM0808_PERM_FR1 | 0x4, + GSM0808_PERM_HR2 = GSM0808_PERM_FR2 | 0x4, + GSM0808_PERM_HR3 = GSM0808_PERM_FR3 | 0x4, +}; + +#endif diff --git a/include/osmocom/gsm/protocol/gsm_08_58.h b/include/osmocom/gsm/protocol/gsm_08_58.h new file mode 100644 index 00000000..74a4083b --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_08_58.h @@ -0,0 +1,546 @@ +#ifndef PROTO_GSM_08_58_H +#define PROTO_GSM_08_58_H + +/* GSM Radio Signalling Link messages on the A-bis interface + * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */ + +/* (C) 2008 by Harald Welte + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include + +struct abis_rsl_common_hdr { + uint8_t msg_discr; + uint8_t msg_type; + uint8_t data[0]; +} __attribute__ ((packed)); + +/* Chapter 8.3 */ +struct abis_rsl_rll_hdr { + struct abis_rsl_common_hdr c; + uint8_t ie_chan; + uint8_t chan_nr; + uint8_t ie_link_id; + uint8_t link_id; + uint8_t data[0]; +} __attribute__ ((packed)); + +/* Chapter 8.3 and 8.4 */ +struct abis_rsl_dchan_hdr { + struct abis_rsl_common_hdr c; + uint8_t ie_chan; + uint8_t chan_nr; + uint8_t data[0]; +} __attribute__ ((packed)); + +/* Chapter 8.5 */ +struct abis_rsl_cchan_hdr { + struct abis_rsl_common_hdr c; + uint8_t ie_chan; + uint8_t chan_nr; + uint8_t data[0]; +} __attribute__ ((packed)); + + +/* Chapter 9.1 */ +#define ABIS_RSL_MDISC_RLL 0x02 +#define ABIS_RSL_MDISC_DED_CHAN 0x08 +#define ABIS_RSL_MDISC_COM_CHAN 0x0c +#define ABIS_RSL_MDISC_TRX 0x10 +#define ABIS_RSL_MDISC_LOC 0x20 +#define ABIS_RSL_MDISC_IPACCESS 0x7e +#define ABIS_RSL_MDISC_TRANSP 0x01 + +#define ABIS_RSL_MDISC_IS_TRANSP(x) (x & 0x01) + +/* Chapter 9.1 */ +enum abis_rsl_msgtype { + /* Radio Link Layer Management */ + RSL_MT_DATA_REQ = 0x01, + RSL_MT_DATA_IND, + RSL_MT_ERROR_IND, + RSL_MT_EST_REQ, + RSL_MT_EST_CONF, + RSL_MT_EST_IND, + RSL_MT_REL_REQ, + RSL_MT_REL_CONF, + RSL_MT_REL_IND, + RSL_MT_UNIT_DATA_REQ, + RSL_MT_UNIT_DATA_IND, /* 0x0b */ + RSL_MT_SUSP_REQ, /* non-standard elements */ + RSL_MT_SUSP_CONF, + RSL_MT_RES_REQ, + RSL_MT_RECON_REQ, /* 0x0f */ + + /* Common Channel Management / TRX Management */ + RSL_MT_BCCH_INFO = 0x11, + RSL_MT_CCCH_LOAD_IND, + RSL_MT_CHAN_RQD, + RSL_MT_DELETE_IND, + RSL_MT_PAGING_CMD, + RSL_MT_IMMEDIATE_ASSIGN_CMD, + RSL_MT_SMS_BC_REQ, + RSL_MT_CHAN_CONF, /* non-standard element */ + /* empty */ + RSL_MT_RF_RES_IND = 0x19, + RSL_MT_SACCH_FILL, + RSL_MT_OVERLOAD, + RSL_MT_ERROR_REPORT, + RSL_MT_SMS_BC_CMD, + RSL_MT_CBCH_LOAD_IND, + RSL_MT_NOT_CMD, /* 0x1f */ + + /* Dedicate Channel Management */ + RSL_MT_CHAN_ACTIV = 0x21, + RSL_MT_CHAN_ACTIV_ACK, + RSL_MT_CHAN_ACTIV_NACK, + RSL_MT_CONN_FAIL, + RSL_MT_DEACTIVATE_SACCH, + RSL_MT_ENCR_CMD, + RSL_MT_HANDO_DET, + RSL_MT_MEAS_RES, + RSL_MT_MODE_MODIFY_REQ, + RSL_MT_MODE_MODIFY_ACK, + RSL_MT_MODE_MODIFY_NACK, + RSL_MT_PHY_CONTEXT_REQ, + RSL_MT_PHY_CONTEXT_CONF, + RSL_MT_RF_CHAN_REL, + RSL_MT_MS_POWER_CONTROL, + RSL_MT_BS_POWER_CONTROL, /* 0x30 */ + RSL_MT_PREPROC_CONFIG, + RSL_MT_PREPROC_MEAS_RES, + RSL_MT_RF_CHAN_REL_ACK, + RSL_MT_SACCH_INFO_MODIFY, + RSL_MT_TALKER_DET, + RSL_MT_LISTENER_DET, + RSL_MT_REMOTE_CODEC_CONF_REP, + RSL_MT_RTD_REP, + RSL_MT_PRE_HANDO_NOTIF, + RSL_MT_MR_CODEC_MOD_REQ, + RSL_MT_MR_CODEC_MOD_ACK, + RSL_MT_MR_CODEC_MOD_NACK, + RSL_MT_MR_CODEC_MOD_PER, + RSL_MT_TFO_REP, + RSL_MT_TFO_MOD_REQ, /* 0x3f */ + RSL_MT_LOCATION_INFO = 0x41, + + /* ip.access specific RSL message types */ + RSL_MT_IPAC_DIR_RETR_ENQ = 0x40, + RSL_MT_IPAC_PDCH_ACT = 0x48, + RSL_MT_IPAC_PDCH_ACT_ACK, + RSL_MT_IPAC_PDCH_ACT_NACK, + RSL_MT_IPAC_PDCH_DEACT = 0x4b, + RSL_MT_IPAC_PDCH_DEACT_ACK, + RSL_MT_IPAC_PDCH_DEACT_NACK, + RSL_MT_IPAC_CONNECT_MUX = 0x50, + RSL_MT_IPAC_CONNECT_MUX_ACK, + RSL_MT_IPAC_CONNECT_MUX_NACK, + RSL_MT_IPAC_BIND_MUX = 0x53, + RSL_MT_IPAC_BIND_MUX_ACK, + RSL_MT_IPAC_BIND_MUX_NACK, + RSL_MT_IPAC_DISC_MUX = 0x56, + RSL_MT_IPAC_DISC_MUX_ACK, + RSL_MT_IPAC_DISC_MUX_NACK, + RSL_MT_IPAC_CRCX = 0x70, /* Bind to local BTS RTP port */ + RSL_MT_IPAC_CRCX_ACK, + RSL_MT_IPAC_CRCX_NACK, + RSL_MT_IPAC_MDCX = 0x73, + RSL_MT_IPAC_MDCX_ACK, + RSL_MT_IPAC_MDCX_NACK, + RSL_MT_IPAC_DLCX_IND = 0x76, + RSL_MT_IPAC_DLCX = 0x77, + RSL_MT_IPAC_DLCX_ACK, + RSL_MT_IPAC_DLCX_NACK, +}; + +/* Siemens vendor-specific */ +enum abis_rsl_msgtype_siemens { + RSL_MT_SIEMENS_MRPCI = 0x41, + RSL_MT_SIEMENS_INTRAC_HO_COND_IND = 0x42, + RSL_MT_SIEMENS_INTERC_HO_COND_IND = 0x43, + RSL_MT_SIEMENS_FORCED_HO_REQ = 0x44, + RSL_MT_SIEMENS_PREF_AREA_REQ = 0x45, + RSL_MT_SIEMENS_PREF_AREA = 0x46, + RSL_MT_SIEMENS_START_TRACE = 0x47, + RSL_MT_SIEMENS_START_TRACE_ACK = 0x48, + RSL_MT_SIEMENS_STOP_TRACE = 0x49, + RSL_MT_SIEMENS_TRMR = 0x4a, + RSL_MT_SIEMENS_HO_FAIL_IND = 0x4b, + RSL_MT_SIEMENS_STOP_TRACE_ACK = 0x4c, + RSL_MT_SIEMENS_UPLF = 0x4d, + RSL_MT_SIEMENS_UPLB = 0x4e, + RSL_MT_SIEMENS_SET_SYS_INFO_10 = 0x4f, + RSL_MT_SIEMENS_MODIF_COND_IND = 0x50, +}; + +/* Chapter 9.3 */ +enum abis_rsl_ie { + RSL_IE_CHAN_NR = 0x01, + RSL_IE_LINK_IDENT, + RSL_IE_ACT_TYPE, + RSL_IE_BS_POWER, + RSL_IE_CHAN_IDENT, + RSL_IE_CHAN_MODE, + RSL_IE_ENCR_INFO, + RSL_IE_FRAME_NUMBER, + RSL_IE_HANDO_REF, + RSL_IE_L1_INFO, + RSL_IE_L3_INFO, + RSL_IE_MS_IDENTITY, + RSL_IE_MS_POWER, + RSL_IE_PAGING_GROUP, + RSL_IE_PAGING_LOAD, + RSL_IE_PYHS_CONTEXT = 0x10, + RSL_IE_ACCESS_DELAY, + RSL_IE_RACH_LOAD, + RSL_IE_REQ_REFERENCE, + RSL_IE_RELEASE_MODE, + RSL_IE_RESOURCE_INFO, + RSL_IE_RLM_CAUSE, + RSL_IE_STARTNG_TIME, + RSL_IE_TIMING_ADVANCE, + RSL_IE_UPLINK_MEAS, + RSL_IE_CAUSE, + RSL_IE_MEAS_RES_NR, + RSL_IE_MSG_ID, + /* reserved */ + RSL_IE_SYSINFO_TYPE = 0x1e, + RSL_IE_MS_POWER_PARAM, + RSL_IE_BS_POWER_PARAM, + RSL_IE_PREPROC_PARAM, + RSL_IE_PREPROC_MEAS, + RSL_IE_IMM_ASS_INFO, /* Phase 1 (3.6.0), later Full below */ + RSL_IE_SMSCB_INFO = 0x24, + RSL_IE_MS_TIMING_OFFSET, + RSL_IE_ERR_MSG, + RSL_IE_FULL_BCCH_INFO, + RSL_IE_CHAN_NEEDED, + RSL_IE_CB_CMD_TYPE, + RSL_IE_SMSCB_MSG, + RSL_IE_FULL_IMM_ASS_INFO, + RSL_IE_SACCH_INFO, + RSL_IE_CBCH_LOAD_INFO, + RSL_IE_SMSCB_CHAN_INDICATOR, + RSL_IE_GROUP_CALL_REF, + RSL_IE_CHAN_DESC = 0x30, + RSL_IE_NCH_DRX_INFO, + RSL_IE_CMD_INDICATOR, + RSL_IE_EMLPP_PRIO, + RSL_IE_UIC, + RSL_IE_MAIN_CHAN_REF, + RSL_IE_MR_CONFIG, + RSL_IE_MR_CONTROL, + RSL_IE_SUP_CODEC_TYPES, + RSL_IE_CODEC_CONFIG, + RSL_IE_RTD, + RSL_IE_TFO_STATUS, + RSL_IE_LLP_APDU, + /* Siemens vendor-specific */ + RSL_IE_SIEMENS_MRPCI = 0x40, + RSL_IE_SIEMENS_PREF_AREA_TYPE = 0x43, + RSL_IE_SIEMENS_ININ_CELL_HO_PAR = 0x45, + RSL_IE_SIEMENS_TRACE_REF_NR = 0x46, + RSL_IE_SIEMENS_INT_TRACE_IDX = 0x47, + RSL_IE_SIEMENS_L2_HDR_INFO = 0x48, + RSL_IE_SIEMENS_HIGHEST_RATE = 0x4e, + RSL_IE_SIEMENS_SUGGESTED_RATE = 0x4f, + + /* ip.access */ + RSL_IE_IPAC_SRTP_CONFIG = 0xe0, + RSL_IE_IPAC_PROXY_UDP = 0xe1, + RSL_IE_IPAC_BSCMPL_TOUT = 0xe2, + RSL_IE_IPAC_REMOTE_IP = 0xf0, + RSL_IE_IPAC_REMOTE_PORT = 0xf1, + RSL_IE_IPAC_RTP_PAYLOAD = 0xf2, + RSL_IE_IPAC_LOCAL_PORT = 0xf3, + RSL_IE_IPAC_SPEECH_MODE = 0xf4, + RSL_IE_IPAC_LOCAL_IP = 0xf5, + RSL_IE_IPAC_CONN_STAT = 0xf6, + RSL_IE_IPAC_HO_C_PARMS = 0xf7, + RSL_IE_IPAC_CONN_ID = 0xf8, + RSL_IE_IPAC_RTP_CSD_FMT = 0xf9, + RSL_IE_IPAC_RTP_JIT_BUF = 0xfa, + RSL_IE_IPAC_RTP_COMPR = 0xfb, + RSL_IE_IPAC_RTP_PAYLOAD2= 0xfc, + RSL_IE_IPAC_RTP_MPLEX = 0xfd, + RSL_IE_IPAC_RTP_MPLEX_ID= 0xfe, +}; + +/* Chapter 9.3.1 */ +#define RSL_CHAN_NR_MASK 0xf8 +#define RSL_CHAN_Bm_ACCHs 0x08 +#define RSL_CHAN_Lm_ACCHs 0x10 /* .. 0x18 */ +#define RSL_CHAN_SDCCH4_ACCH 0x20 /* .. 0x38 */ +#define RSL_CHAN_SDCCH8_ACCH 0x40 /* ...0x78 */ +#define RSL_CHAN_BCCH 0x80 +#define RSL_CHAN_RACH 0x88 +#define RSL_CHAN_PCH_AGCH 0x90 + +/* Chapter 9.3.3 */ +#define RSL_ACT_TYPE_INITIAL 0x00 +#define RSL_ACT_TYPE_REACT 0x80 +#define RSL_ACT_INTRA_IMM_ASS 0x00 +#define RSL_ACT_INTRA_NORM_ASS 0x01 +#define RSL_ACT_INTER_ASYNC 0x02 +#define RSL_ACT_INTER_SYNC 0x03 +#define RSL_ACT_SECOND_ADD 0x04 +#define RSL_ACT_SECOND_MULTI 0x05 + +/* Chapter 9.3.6 */ +struct rsl_ie_chan_mode { + uint8_t dtx_dtu; + uint8_t spd_ind; + uint8_t chan_rt; + uint8_t chan_rate; +} __attribute__ ((packed)); +#define RSL_CMOD_DTXu 0x01 /* uplink */ +#define RSL_CMOD_DTXd 0x02 /* downlink */ +enum rsl_cmod_spd { + RSL_CMOD_SPD_SPEECH = 0x01, + RSL_CMOD_SPD_DATA = 0x02, + RSL_CMOD_SPD_SIGN = 0x03, +}; +#define RSL_CMOD_CRT_SDCCH 0x01 +#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */ +#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */ +/* FIXME: More CRT types */ +/* Speech */ +#define RSL_CMOD_SP_GSM1 0x01 +#define RSL_CMOD_SP_GSM2 0x11 +#define RSL_CMOD_SP_GSM3 0x21 +/* Data */ +#define RSL_CMOD_SP_NT_14k5 0x58 +#define RSL_CMOD_SP_NT_12k0 0x50 +#define RSL_CMOD_SP_NT_6k0 0x51 + +/* Chapter 9.3.5 */ +struct rsl_ie_chan_ident { + /* GSM 04.08 10.5.2.5 */ + struct { + uint8_t iei; + uint8_t chan_nr; /* enc_chan_nr */ + uint8_t oct3; + uint8_t oct4; + } chan_desc; +#if 0 /* spec says we need this but Abissim doesn't use it */ + struct { + uint8_t tag; + uint8_t len; + } mobile_alloc; +#endif +} __attribute__ ((packed)); + +/* Chapter 9.3.22 */ +#define RLL_CAUSE_T200_EXPIRED 0x01 +#define RLL_CAUSE_REEST_REQ 0x02 +#define RLL_CAUSE_UNSOL_UA_RESP 0x03 +#define RLL_CAUSE_UNSOL_DM_RESP 0x04 +#define RLL_CAUSE_UNSOL_DM_RESP_MF 0x05 +#define RLL_CAUSE_UNSOL_SPRV_RESP 0x06 +#define RLL_CAUSE_SEQ_ERR 0x07 +#define RLL_CAUSE_UFRM_INC_PARAM 0x08 +#define RLL_CAUSE_SFRM_INC_PARAM 0x09 +#define RLL_CAUSE_IFRM_INC_MBITS 0x0a +#define RLL_CAUSE_IFRM_INC_LEN 0x0b +#define RLL_CAUSE_FRM_UNIMPL 0x0c +#define RLL_CAUSE_SABM_MF 0x0d +#define RLL_CAUSE_SABM_INFO_NOTALL 0x0e + +/* Chapter 9.3.26 */ +#define RSL_ERRCLS_NORMAL 0x00 +#define RSL_ERRCLS_RESOURCE_UNAVAIL 0x20 +#define RSL_ERRCLS_SERVICE_UNAVAIL 0x30 +#define RSL_ERRCLS_SERVICE_UNIMPL 0x40 +#define RSL_ERRCLS_INVAL_MSG 0x50 +#define RSL_ERRCLS_PROTO_ERROR 0x60 +#define RSL_ERRCLS_INTERWORKING 0x70 + +/* normal event */ +#define RSL_ERR_RADIO_IF_FAIL 0x00 +#define RSL_ERR_RADIO_LINK_FAIL 0x01 +#define RSL_ERR_HANDOVER_ACC_FAIL 0x02 +#define RSL_ERR_TALKER_ACC_FAIL 0x03 +#define RSL_ERR_OM_INTERVENTION 0x07 +#define RSL_ERR_NORMAL_UNSPEC 0x0f +#define RSL_ERR_T_MSRFPCI_EXP 0x18 +/* resource unavailable */ +#define RSL_ERR_EQUIPMENT_FAIL 0x20 +#define RSL_ERR_RR_UNAVAIL 0x21 +#define RSL_ERR_TERR_CH_FAIL 0x22 +#define RSL_ERR_CCCH_OVERLOAD 0x23 +#define RSL_ERR_ACCH_OVERLOAD 0x24 +#define RSL_ERR_PROCESSOR_OVERLOAD 0x25 +#define RSL_ERR_RES_UNAVAIL 0x2f +/* service or option not available */ +#define RSL_ERR_TRANSC_UNAVAIL 0x30 +#define RSL_ERR_SERV_OPT_UNAVAIL 0x3f +/* service or option not implemented */ +#define RSL_ERR_ENCR_UNIMPL 0x40 +#define RSL_ERR_SERV_OPT_UNIMPL 0x4f +/* invalid message */ +#define RSL_ERR_RCH_ALR_ACTV_ALLOC 0x50 +#define RSL_ERR_INVALID_MESSAGE 0x5f +/* protocol error */ +#define RSL_ERR_MSG_DISCR 0x60 +#define RSL_ERR_MSG_TYPE 0x61 +#define RSL_ERR_MSG_SEQ 0x62 +#define RSL_ERR_IE_ERROR 0x63 +#define RSL_ERR_MAND_IE_ERROR 0x64 +#define RSL_ERR_OPT_IE_ERROR 0x65 +#define RSL_ERR_IE_NONEXIST 0x66 +#define RSL_ERR_IE_LENGTH 0x67 +#define RSL_ERR_IE_CONTENT 0x68 +#define RSL_ERR_PROTO 0x6f +/* interworking */ +#define RSL_ERR_INTERWORKING 0x7f + +/* Chapter 9.3.30 */ +#define RSL_SYSTEM_INFO_8 0x00 +#define RSL_SYSTEM_INFO_1 0x01 +#define RSL_SYSTEM_INFO_2 0x02 +#define RSL_SYSTEM_INFO_3 0x03 +#define RSL_SYSTEM_INFO_4 0x04 +#define RSL_SYSTEM_INFO_5 0x05 +#define RSL_SYSTEM_INFO_6 0x06 +#define RSL_SYSTEM_INFO_7 0x07 +#define RSL_SYSTEM_INFO_16 0x08 +#define RSL_SYSTEM_INFO_17 0x09 +#define RSL_SYSTEM_INFO_2bis 0x0a +#define RSL_SYSTEM_INFO_2ter 0x0b +#define RSL_SYSTEM_INFO_5bis 0x0d +#define RSL_SYSTEM_INFO_5ter 0x0e +#define RSL_SYSTEM_INFO_10 0x0f +#define REL_EXT_MEAS_ORDER 0x47 +#define RSL_MEAS_INFO 0x48 +#define RSL_SYSTEM_INFO_13 0x28 +#define RSL_SYSTEM_INFO_2quater 0x29 +#define RSL_SYSTEM_INFO_9 0x2a +#define RSL_SYSTEM_INFO_18 0x2b +#define RSL_SYSTEM_INFO_19 0x2c +#define RSL_SYSTEM_INFO_20 0x2d + +/* Chapter 9.3.40 */ +#define RSL_CHANNEED_ANY 0x00 +#define RSL_CHANNEED_SDCCH 0x01 +#define RSL_CHANNEED_TCH_F 0x02 +#define RSL_CHANNEED_TCH_ForH 0x03 + +/* Chapter 9.3.45 */ +struct rsl_ie_cb_cmd_type { + uint8_t last_block:2; + uint8_t spare:1; + uint8_t def_bcast:1; + uint8_t command:4; +} __attribute__ ((packed)); +/* ->command */ +#define RSL_CB_CMD_TYPE_NORMAL 0x00 +#define RSL_CB_CMD_TYPE_SCHEDULE 0x08 +#define RSL_CB_CMD_TYPE_DEFAULT 0x0e +#define RSL_CB_CMD_TYPE_NULL 0x0f +/* ->def_bcast */ +#define RSL_CB_CMD_DEFBCAST_NORMAL 0 +#define RSL_CB_CMD_DEFBCAST_NULL 1 +/* ->last_block */ +#define RSL_CB_CMD_LASTBLOCK_4 0 +#define RSL_CB_CMD_LASTBLOCK_1 1 +#define RSL_CB_CMD_LASTBLOCK_2 2 +#define RSL_CB_CMD_LASTBLOCK_3 3 + +/* Chapter 3.3.2.3 Brocast control channel */ +/* CCCH-CONF, NC is not combined */ +#define RSL_BCCH_CCCH_CONF_1_NC 0x00 +#define RSL_BCCH_CCCH_CONF_1_C 0x01 +#define RSL_BCCH_CCCH_CONF_2_NC 0x02 +#define RSL_BCCH_CCCH_CONF_3_NC 0x04 +#define RSL_BCCH_CCCH_CONF_4_NC 0x06 + +/* BS-PA-MFRMS */ +#define RSL_BS_PA_MFRMS_2 0x00 +#define RSL_BS_PA_MFRMS_3 0x01 +#define RSL_BS_PA_MFRMS_4 0x02 +#define RSL_BS_PA_MFRMS_5 0x03 +#define RSL_BS_PA_MFRMS_6 0x04 +#define RSL_BS_PA_MFRMS_7 0x05 +#define RSL_BS_PA_MFRMS_8 0x06 +#define RSL_BS_PA_MFRMS_9 0x07 + +/* RSL_IE_IPAC_RTP_PAYLOAD[2] */ +enum rsl_ipac_rtp_payload { + RSL_IPAC_RTP_GSM = 1, + RSL_IPAC_RTP_EFR, + RSL_IPAC_RTP_AMR, + RSL_IPAC_RTP_CSD, + RSL_IPAC_RTP_MUX, +}; + +/* RSL_IE_IPAC_SPEECH_MODE, lower four bits */ +enum rsl_ipac_speech_mode_s { + RSL_IPAC_SPEECH_GSM_FR = 0, /* GSM FR (Type 1, FS) */ + RSL_IPAC_SPEECH_GSM_EFR = 1, /* GSM EFR (Type 2, FS) */ + RSL_IPAC_SPEECH_GSM_AMR_FR = 2, /* GSM AMR/FR (Type 3, FS) */ + RSL_IPAC_SPEECH_GSM_HR = 3, /* GSM HR (Type 1, HS) */ + RSL_IPAC_SPEECH_GSM_AMR_HR = 5, /* GSM AMR/hr (Type 3, HS) */ + RSL_IPAC_SPEECH_AS_RTP = 0xf, /* As specified by RTP Payload IE */ +}; +/* RSL_IE_IPAC_SPEECH_MODE, upper four bits */ +enum rsl_ipac_speech_mode_m { + RSL_IPAC_SPEECH_M_RXTX = 0, /* Send and Receive */ + RSL_IPAC_SPEECH_M_RX = 1, /* Receive only */ + RSL_IPAC_SPEECH_M_TX = 2, /* Send only */ +}; + +/* RSL_IE_IPAC_RTP_CSD_FMT, lower four bits */ +enum rsl_ipac_rtp_csd_format_d { + RSL_IPAC_RTP_CSD_EXT_TRAU = 0, + RSL_IPAC_RTP_CSD_NON_TRAU = 1, + RSL_IPAC_RTP_CSD_TRAU_BTS = 2, + RSL_IPAC_RTP_CSD_IWF_FREE = 3, +}; +/* RSL_IE_IPAC_RTP_CSD_FMT, upper four bits */ +enum rsl_ipac_rtp_csd_format_ir { + RSL_IPAC_RTP_CSD_IR_8k = 0, + RSL_IPAC_RTP_CSD_IR_16k = 1, + RSL_IPAC_RTP_CSD_IR_32k = 2, + RSL_IPAC_RTP_CSD_IR_64k = 3, +}; + +/* Siemens vendor-specific RSL extensions */ +struct rsl_mrpci { + uint8_t power_class:3, + vgcs_capable:1, + vbs_capable:1, + gsm_phase:2; +} __attribute__ ((packed)); + +enum rsl_mrpci_pwrclass { + RSL_MRPCI_PWRC_1 = 0, + RSL_MRPCI_PWRC_2 = 1, + RSL_MRPCI_PWRC_3 = 2, + RSL_MRPCI_PWRC_4 = 3, + RSL_MRPCI_PWRC_5 = 4, +}; +enum rsl_mrpci_phase { + RSL_MRPCI_PHASE_1 = 0, + /* reserved */ + RSL_MRPCI_PHASE_2 = 2, + RSL_MRPCI_PHASE_2PLUS = 3, +}; + + +#endif /* PROTO_GSM_08_58_H */ diff --git a/include/osmocom/gsm/protocol/gsm_12_21.h b/include/osmocom/gsm/protocol/gsm_12_21.h new file mode 100644 index 00000000..b8b00f3f --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_12_21.h @@ -0,0 +1,713 @@ +#ifndef PROTO_GSM_12_21_H +#define PROTO_GSM_12_21_H + +/* GSM Network Management messages on the A-bis interface + * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */ + +/* (C) 2008-2009 by Harald Welte + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include + +/* generic header in front of every OML message according to TS 08.59 */ +struct abis_om_hdr { + uint8_t mdisc; + uint8_t placement; + uint8_t sequence; + uint8_t length; + uint8_t data[0]; +} __attribute__ ((packed)); + +#define ABIS_OM_MDISC_FOM 0x80 +#define ABIS_OM_MDISC_MMI 0x40 +#define ABIS_OM_MDISC_TRAU 0x20 +#define ABIS_OM_MDISC_MANUF 0x10 +#define ABIS_OM_PLACEMENT_ONLY 0x80 +#define ABIS_OM_PLACEMENT_FIRST 0x40 +#define ABIS_OM_PLACEMENT_MIDDLE 0x20 +#define ABIS_OM_PLACEMENT_LAST 0x10 + +struct abis_om_obj_inst { + uint8_t bts_nr; + uint8_t trx_nr; + uint8_t ts_nr; +} __attribute__ ((packed)); + +struct abis_om_fom_hdr { + uint8_t msg_type; + uint8_t obj_class; + struct abis_om_obj_inst obj_inst; + uint8_t data[0]; +} __attribute__ ((packed)); + +#define ABIS_OM_FOM_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr)) + +/* Section 9.1: Message Types */ +enum abis_nm_msgtype { + /* SW Download Management Messages */ + NM_MT_LOAD_INIT = 0x01, + NM_MT_LOAD_INIT_ACK, + NM_MT_LOAD_INIT_NACK, + NM_MT_LOAD_SEG, + NM_MT_LOAD_SEG_ACK, + NM_MT_LOAD_ABORT, + NM_MT_LOAD_END, + NM_MT_LOAD_END_ACK, + NM_MT_LOAD_END_NACK, + NM_MT_SW_ACT_REQ, /* BTS->BSC */ + NM_MT_SW_ACT_REQ_ACK, + NM_MT_SW_ACT_REQ_NACK, + NM_MT_ACTIVATE_SW, /* BSC->BTS */ + NM_MT_ACTIVATE_SW_ACK, + NM_MT_ACTIVATE_SW_NACK, + NM_MT_SW_ACTIVATED_REP, /* 0x10 */ + /* A-bis Interface Management Messages */ + NM_MT_ESTABLISH_TEI = 0x21, + NM_MT_ESTABLISH_TEI_ACK, + NM_MT_ESTABLISH_TEI_NACK, + NM_MT_CONN_TERR_SIGN, + NM_MT_CONN_TERR_SIGN_ACK, + NM_MT_CONN_TERR_SIGN_NACK, + NM_MT_DISC_TERR_SIGN, + NM_MT_DISC_TERR_SIGN_ACK, + NM_MT_DISC_TERR_SIGN_NACK, + NM_MT_CONN_TERR_TRAF, + NM_MT_CONN_TERR_TRAF_ACK, + NM_MT_CONN_TERR_TRAF_NACK, + NM_MT_DISC_TERR_TRAF, + NM_MT_DISC_TERR_TRAF_ACK, + NM_MT_DISC_TERR_TRAF_NACK, + /* Transmission Management Messages */ + NM_MT_CONN_MDROP_LINK = 0x31, + NM_MT_CONN_MDROP_LINK_ACK, + NM_MT_CONN_MDROP_LINK_NACK, + NM_MT_DISC_MDROP_LINK, + NM_MT_DISC_MDROP_LINK_ACK, + NM_MT_DISC_MDROP_LINK_NACK, + /* Air Interface Management Messages */ + NM_MT_SET_BTS_ATTR = 0x41, + NM_MT_SET_BTS_ATTR_ACK, + NM_MT_SET_BTS_ATTR_NACK, + NM_MT_SET_RADIO_ATTR, + NM_MT_SET_RADIO_ATTR_ACK, + NM_MT_SET_RADIO_ATTR_NACK, + NM_MT_SET_CHAN_ATTR, + NM_MT_SET_CHAN_ATTR_ACK, + NM_MT_SET_CHAN_ATTR_NACK, + /* Test Management Messages */ + NM_MT_PERF_TEST = 0x51, + NM_MT_PERF_TEST_ACK, + NM_MT_PERF_TEST_NACK, + NM_MT_TEST_REP, + NM_MT_SEND_TEST_REP, + NM_MT_SEND_TEST_REP_ACK, + NM_MT_SEND_TEST_REP_NACK, + NM_MT_STOP_TEST, + NM_MT_STOP_TEST_ACK, + NM_MT_STOP_TEST_NACK, + /* State Management and Event Report Messages */ + NM_MT_STATECHG_EVENT_REP = 0x61, + NM_MT_FAILURE_EVENT_REP, + NM_MT_STOP_EVENT_REP, + NM_MT_STOP_EVENT_REP_ACK, + NM_MT_STOP_EVENT_REP_NACK, + NM_MT_REST_EVENT_REP, + NM_MT_REST_EVENT_REP_ACK, + NM_MT_REST_EVENT_REP_NACK, + NM_MT_CHG_ADM_STATE, + NM_MT_CHG_ADM_STATE_ACK, + NM_MT_CHG_ADM_STATE_NACK, + NM_MT_CHG_ADM_STATE_REQ, + NM_MT_CHG_ADM_STATE_REQ_ACK, + NM_MT_CHG_ADM_STATE_REQ_NACK, + NM_MT_REP_OUTST_ALARMS = 0x93, + NM_MT_REP_OUTST_ALARMS_ACK, + NM_MT_REP_OUTST_ALARMS_NACK, + /* Equipment Management Messages */ + NM_MT_CHANGEOVER = 0x71, + NM_MT_CHANGEOVER_ACK, + NM_MT_CHANGEOVER_NACK, + NM_MT_OPSTART, + NM_MT_OPSTART_ACK, + NM_MT_OPSTART_NACK, + NM_MT_REINIT, + NM_MT_REINIT_ACK, + NM_MT_REINIT_NACK, + NM_MT_SET_SITE_OUT, /* BS11: get alarm ?!? */ + NM_MT_SET_SITE_OUT_ACK, + NM_MT_SET_SITE_OUT_NACK, + NM_MT_CHG_HW_CONF = 0x90, + NM_MT_CHG_HW_CONF_ACK, + NM_MT_CHG_HW_CONF_NACK, + /* Measurement Management Messages */ + NM_MT_MEAS_RES_REQ = 0x8a, + NM_MT_MEAS_RES_RESP, + NM_MT_STOP_MEAS, + NM_MT_START_MEAS, + /* Other Messages */ + NM_MT_GET_ATTR = 0x81, + NM_MT_GET_ATTR_RESP, + NM_MT_GET_ATTR_NACK, + NM_MT_SET_ALARM_THRES, + NM_MT_SET_ALARM_THRES_ACK, + NM_MT_SET_ALARM_THRES_NACK, +}; + +enum abis_nm_msgtype_bs11 { + NM_MT_BS11_RESET_RESOURCE = 0x74, + + NM_MT_BS11_BEGIN_DB_TX = 0xa3, + NM_MT_BS11_BEGIN_DB_TX_ACK, + NM_MT_BS11_BEGIN_DB_TX_NACK, + NM_MT_BS11_END_DB_TX = 0xa6, + NM_MT_BS11_END_DB_TX_ACK, + NM_MT_BS11_END_DB_TX_NACK, + NM_MT_BS11_CREATE_OBJ = 0xa9, + NM_MT_BS11_CREATE_OBJ_ACK, + NM_MT_BS11_CREATE_OBJ_NACK, + NM_MT_BS11_DELETE_OBJ = 0xac, + NM_MT_BS11_DELETE_OBJ_ACK, + NM_MT_BS11_DELETE_OBJ_NACK, + + NM_MT_BS11_SET_ATTR = 0xd0, + NM_MT_BS11_SET_ATTR_ACK, + NM_MT_BS11_SET_ATTR_NACK, + NM_MT_BS11_LMT_SESSION = 0xdc, + + NM_MT_BS11_GET_STATE = 0xe3, + NM_MT_BS11_GET_STATE_ACK, + NM_MT_BS11_LMT_LOGON = 0xe5, + NM_MT_BS11_LMT_LOGON_ACK, + NM_MT_BS11_RESTART = 0xe7, + NM_MT_BS11_RESTART_ACK, + NM_MT_BS11_DISCONNECT = 0xe9, + NM_MT_BS11_DISCONNECT_ACK, + NM_MT_BS11_LMT_LOGOFF = 0xec, + NM_MT_BS11_LMT_LOGOFF_ACK, + NM_MT_BS11_RECONNECT = 0xf1, + NM_MT_BS11_RECONNECT_ACK, +}; + +enum abis_nm_msgtype_ipacc { + NM_MT_IPACC_RESTART = 0x87, + NM_MT_IPACC_RESTART_ACK, + NM_MT_IPACC_RESTART_NACK, + NM_MT_IPACC_RSL_CONNECT = 0xe0, + NM_MT_IPACC_RSL_CONNECT_ACK, + NM_MT_IPACC_RSL_CONNECT_NACK, + NM_MT_IPACC_RSL_DISCONNECT = 0xe3, + NM_MT_IPACC_RSL_DISCONNECT_ACK, + NM_MT_IPACC_RSL_DISCONNECT_NACK, + NM_MT_IPACC_CONN_TRAF = 0xe6, + NM_MT_IPACC_CONN_TRAF_ACK, + NM_MT_IPACC_CONN_TRAF_NACK, + NM_MT_IPACC_DEF_BOOT_SW = 0xec, + NM_MT_IPACC_DEF_BOOT_SW_ACK, + MN_MT_IPACC_DEF_BOOT_SW_NACK, + NM_MT_IPACC_SET_NVATTR = 0xef, + NM_MT_IPACC_SET_NVATTR_ACK, + NM_MT_IPACC_SET_NVATTR_NACK, + NM_MT_IPACC_GET_NVATTR = 0xf2, + NM_MT_IPACC_GET_NVATTR_ACK, + NM_MT_IPACC_GET_NVATTR_NACK, + NM_MT_IPACC_SET_ATTR = 0xf5, + NM_MT_IPACC_SET_ATTR_ACK, + NM_MT_IPACC_SET_ATTR_NACK, +}; + +enum abis_nm_bs11_cell_alloc { + NM_BS11_CANR_GSM = 0x00, + NM_BS11_CANR_DCS1800 = 0x01, +}; + +/* Section 9.2: Object Class */ +enum abis_nm_obj_class { + NM_OC_SITE_MANAGER = 0x00, + NM_OC_BTS, + NM_OC_RADIO_CARRIER, + NM_OC_CHANNEL, + NM_OC_BASEB_TRANSC, + /* RFU: 05-FE */ + + NM_OC_IPAC_E1_TRUNK = 0x0e, + NM_OC_IPAC_E1_PORT = 0x0f, + NM_OC_IPAC_E1_CHAN = 0x10, + NM_OC_IPAC_CLK_MODULE = 0x22, + + NM_OC_BS11_ADJC = 0xa0, + NM_OC_BS11_HANDOVER = 0xa1, + NM_OC_BS11_PWR_CTRL = 0xa2, + NM_OC_BS11_BTSE = 0xa3, /* LMT? */ + NM_OC_BS11_RACK = 0xa4, + NM_OC_BS11 = 0xa5, /* 01: ALCO */ + NM_OC_BS11_TEST = 0xa6, + NM_OC_BS11_ENVABTSE = 0xa8, + NM_OC_BS11_BPORT = 0xa9, + + NM_OC_GPRS_NSE = 0xf0, + NM_OC_GPRS_CELL = 0xf1, + NM_OC_GPRS_NSVC = 0xf2, + + NM_OC_NULL = 0xff, +}; + +/* Section 9.4: Attributes */ +enum abis_nm_attr { + NM_ATT_ABIS_CHANNEL = 0x01, + NM_ATT_ADD_INFO, + NM_ATT_ADD_TEXT, + NM_ATT_ADM_STATE, + NM_ATT_ARFCN_LIST, + NM_ATT_AUTON_REPORT, + NM_ATT_AVAIL_STATUS, + NM_ATT_BCCH_ARFCN, + NM_ATT_BSIC, + NM_ATT_BTS_AIR_TIMER, + NM_ATT_CCCH_L_I_P, + NM_ATT_CCCH_L_T, + NM_ATT_CHAN_COMB, + NM_ATT_CONN_FAIL_CRIT, + NM_ATT_DEST, + /* res */ + NM_ATT_EVENT_TYPE = 0x11, /* BS11: file data ?!? */ + NM_ATT_FILE_ID, + NM_ATT_FILE_VERSION, + NM_ATT_GSM_TIME, + NM_ATT_HSN, + NM_ATT_HW_CONFIG, + NM_ATT_HW_DESC, + NM_ATT_INTAVE_PARAM, + NM_ATT_INTERF_BOUND, + NM_ATT_LIST_REQ_ATTR, + NM_ATT_MAIO, + NM_ATT_MANUF_STATE, + NM_ATT_MANUF_THRESH, + NM_ATT_MANUF_ID, + NM_ATT_MAX_TA, + NM_ATT_MDROP_LINK, /* 0x20 */ + NM_ATT_MDROP_NEXT, + NM_ATT_NACK_CAUSES, + NM_ATT_NY1, + NM_ATT_OPER_STATE, + NM_ATT_OVERL_PERIOD, + NM_ATT_PHYS_CONF, + NM_ATT_POWER_CLASS, + NM_ATT_POWER_THRESH, + NM_ATT_PROB_CAUSE, + NM_ATT_RACH_B_THRESH, + NM_ATT_LDAVG_SLOTS, + NM_ATT_RAD_SUBC, + NM_ATT_RF_MAXPOWR_R, + NM_ATT_SITE_INPUTS, + NM_ATT_SITE_OUTPUTS, + NM_ATT_SOURCE, /* 0x30 */ + NM_ATT_SPEC_PROB, + NM_ATT_START_TIME, + NM_ATT_T200, + NM_ATT_TEI, + NM_ATT_TEST_DUR, + NM_ATT_TEST_NO, + NM_ATT_TEST_REPORT, + NM_ATT_VSWR_THRESH, + NM_ATT_WINDOW_SIZE, + /* Res */ + NM_ATT_BS11_RSSI_OFFS = 0x3d, + NM_ATT_BS11_TXPWR = 0x3e, + NM_ATT_BS11_DIVERSITY = 0x3f, + /* Res */ + NM_ATT_TSC = 0x40, + NM_ATT_SW_CONFIG, + NM_ATT_SW_DESCR, + NM_ATT_SEVERITY, + NM_ATT_GET_ARI, + NM_ATT_HW_CONF_CHG, + NM_ATT_OUTST_ALARM, + NM_ATT_FILE_DATA, + NM_ATT_MEAS_RES, + NM_ATT_MEAS_TYPE, + + NM_ATT_BS11_ESN_FW_CODE_NO = 0x4c, + NM_ATT_BS11_ESN_HW_CODE_NO = 0x4f, + + NM_ATT_BS11_ESN_PCB_SERIAL = 0x55, + NM_ATT_BS11_EXCESSIVE_DISTANCE = 0x58, + + NM_ATT_BS11_ALL_TEST_CATG = 0x60, + NM_ATT_BS11_BTSLS_HOPPING, + NM_ATT_BS11_CELL_ALLOC_NR, + NM_ATT_BS11_CELL_GLOBAL_ID, + NM_ATT_BS11_ENA_INTERF_CLASS = 0x66, + NM_ATT_BS11_ENA_INT_INTEC_HANDO = 0x67, + NM_ATT_BS11_ENA_INT_INTRC_HANDO = 0x68, + NM_ATT_BS11_ENA_MS_PWR_CTRL = 0x69, + NM_ATT_BS11_ENA_PWR_BDGT_HO = 0x6a, + NM_ATT_BS11_ENA_PWR_CTRL_RLFW = 0x6b, + NM_ATT_BS11_ENA_RXLEV_HO = 0x6c, + NM_ATT_BS11_ENA_RXQUAL_HO = 0x6d, + NM_ATT_BS11_FACCH_QUAL = 0x6e, + + NM_ATT_IPACC_DST_IP = 0x80, + NM_ATT_IPACC_DST_IP_PORT = 0x81, + NM_ATT_IPACC_SSRC = 0x82, + NM_ATT_IPACC_RTP_PAYLD_TYPE = 0x83, + NM_ATT_IPACC_BASEB_ID = 0x84, + NM_ATT_IPACC_STREAM_ID = 0x85, + NM_ATT_IPACC_NV_FLAGS = 0x86, + NM_ATT_IPACC_FREQ_CTRL = 0x87, + NM_ATT_IPACC_PRIM_OML_CFG = 0x88, + NM_ATT_IPACC_SEC_OML_CFG = 0x89, + NM_ATT_IPACC_IP_IF_CFG = 0x8a, /* IP interface */ + NM_ATT_IPACC_IP_GW_CFG = 0x8b, /* IP gateway */ + NM_ATT_IPACC_IN_SERV_TIME = 0x8c, + NM_ATT_IPACC_TRX_BTS_ASS = 0x8d, + NM_ATT_IPACC_LOCATION = 0x8e, /* string describing location */ + NM_ATT_IPACC_PAGING_CFG = 0x8f, + NM_ATT_IPACC_FILE_DATA = 0x90, + NM_ATT_IPACC_UNIT_ID = 0x91, /* Site/BTS/TRX */ + NM_ATT_IPACC_PARENT_UNIT_ID = 0x92, + NM_ATT_IPACC_UNIT_NAME = 0x93, /* default: nbts- */ + NM_ATT_IPACC_SNMP_CFG = 0x94, + NM_ATT_IPACC_PRIM_OML_CFG_LIST = 0x95, + NM_ATT_IPACC_PRIM_OML_FB_TOUT = 0x96, + NM_ATT_IPACC_CUR_SW_CFG = 0x97, + NM_ATT_IPACC_TIMING_BUS = 0x98, + NM_ATT_IPACC_CGI = 0x99, + NM_ATT_IPACC_RAC = 0x9a, + NM_ATT_IPACC_OBJ_VERSION = 0x9b, + NM_ATT_IPACC_GPRS_PAGING_CFG = 0x9c, + NM_ATT_IPACC_NSEI = 0x9d, + NM_ATT_IPACC_BVCI = 0x9e, + NM_ATT_IPACC_NSVCI = 0x9f, + NM_ATT_IPACC_NS_CFG = 0xa0, + NM_ATT_IPACC_BSSGP_CFG = 0xa1, + NM_ATT_IPACC_NS_LINK_CFG = 0xa2, + NM_ATT_IPACC_RLC_CFG = 0xa3, + NM_ATT_IPACC_ALM_THRESH_LIST = 0xa4, + NM_ATT_IPACC_MONIT_VAL_LIST = 0xa5, + NM_ATT_IPACC_TIB_CONTROL = 0xa6, + NM_ATT_IPACC_SUPP_FEATURES = 0xa7, + NM_ATT_IPACC_CODING_SCHEMES = 0xa8, + NM_ATT_IPACC_RLC_CFG_2 = 0xa9, + NM_ATT_IPACC_HEARTB_TOUT = 0xaa, + NM_ATT_IPACC_UPTIME = 0xab, + NM_ATT_IPACC_RLC_CFG_3 = 0xac, + NM_ATT_IPACC_SSL_CFG = 0xad, + NM_ATT_IPACC_SEC_POSSIBLE = 0xae, + NM_ATT_IPACC_IML_SSL_STATE = 0xaf, + NM_ATT_IPACC_REVOC_DATE = 0xb0, + + + NM_ATT_BS11_RF_RES_IND_PER = 0x8f, + + NM_ATT_BS11_RX_LEV_MIN_CELL = 0x90, + NM_ATT_BS11_ABIS_EXT_TIME = 0x91, + NM_ATT_BS11_TIMER_HO_REQUEST = 0x92, + NM_ATT_BS11_TIMER_NCELL = 0x93, + NM_ATT_BS11_TSYNC = 0x94, + NM_ATT_BS11_TTRAU = 0x95, + NM_ATT_BS11_EMRG_CFG_MEMBER = 0x9b, + NM_ATT_BS11_TRX_AREA = 0x9f, + + NM_ATT_BS11_BCCH_RECONF = 0xd7, + NM_ATT_BS11_BIT_ERR_THESH = 0xa0, + NM_ATT_BS11_BOOT_SW_VERS = 0xa1, + NM_ATT_BS11_CCLK_ACCURACY = 0xa3, + NM_ATT_BS11_CCLK_TYPE = 0xa4, + NM_ATT_BS11_INP_IMPEDANCE = 0xaa, + NM_ATT_BS11_L1_PROT_TYPE = 0xab, + NM_ATT_BS11_LINE_CFG = 0xac, + NM_ATT_BS11_LI_PORT_1 = 0xad, + NM_ATT_BS11_LI_PORT_2 = 0xae, + + NM_ATT_BS11_L1_REM_ALM_TYPE = 0xb0, + NM_ATT_BS11_SW_LOAD_INTENDED = 0xbb, + NM_ATT_BS11_SW_LOAD_SAFETY = 0xbc, + NM_ATT_BS11_SW_LOAD_STORED = 0xbd, + + NM_ATT_BS11_VENDOR_NAME = 0xc1, + NM_ATT_BS11_HOPPING_MODE = 0xc5, + NM_ATT_BS11_LMT_LOGON_SESSION = 0xc6, + NM_ATT_BS11_LMT_LOGIN_TIME = 0xc7, + NM_ATT_BS11_LMT_USER_ACC_LEV = 0xc8, + NM_ATT_BS11_LMT_USER_NAME = 0xc9, + + NM_ATT_BS11_L1_CONTROL_TS = 0xd8, + NM_ATT_BS11_RADIO_MEAS_GRAN = 0xdc, /* in SACCH multiframes */ + NM_ATT_BS11_RADIO_MEAS_REP = 0xdd, + + NM_ATT_BS11_SH_LAPD_INT_TIMER = 0xe8, + + NM_ATT_BS11_BTS_STATE = 0xf0, + NM_ATT_BS11_E1_STATE = 0xf1, + NM_ATT_BS11_PLL = 0xf2, + NM_ATT_BS11_RX_OFFSET = 0xf3, + NM_ATT_BS11_ANT_TYPE = 0xf4, + NM_ATT_BS11_PLL_MODE = 0xfc, + NM_ATT_BS11_PASSWORD = 0xfd, +}; +#define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE + +/* Section 9.4.4: Administrative State */ +enum abis_nm_adm_state { + NM_STATE_LOCKED = 0x01, + NM_STATE_UNLOCKED = 0x02, + NM_STATE_SHUTDOWN = 0x03, + NM_STATE_NULL = 0xff, +}; + +/* Section 9.4.7: Administrative State */ +enum abis_nm_avail_state { + NM_AVSTATE_IN_TEST = 1, + NM_AVSTATE_POWER_OFF = 2, + NM_AVSTATE_OFF_LINE = 3, + NM_AVSTATE_DEPENDENCY = 5, + NM_AVSTATE_DEGRADED = 6, + NM_AVSTATE_NOT_INSTALLED= 7, + NM_AVSTATE_OK = 0xff, +}; + +enum abis_nm_op_state { + NM_OPSTATE_DISABLED = 1, + NM_OPSTATE_ENABLED = 2, + NM_OPSTATE_NULL = 0xff, +}; + +/* Section 9.4.13: Channel Combination */ +enum abis_nm_chan_comb { + NM_CHANC_TCHFull = 0x00, /* TCH/F + TCH/H + SACCH/TF */ + NM_CHANC_TCHHalf = 0x01, /* TCH/H(0,1) + FACCH/H(0,1) + + SACCH/TH(0,1) */ + NM_CHANC_TCHHalf2 = 0x02, /* TCH/H(0) + FACCH/H(0) + SACCH/TH(0) + + TCH/H(1) */ + NM_CHANC_SDCCH = 0x03, /* SDCCH/8 + SACCH/8 */ + NM_CHANC_mainBCCH = 0x04, /* FCCH + SCH + BCCH + CCCH */ + NM_CHANC_BCCHComb = 0x05, /* FCCH + SCH + BCCH + CCCH + SDCCH/4 + + SACCH/C4 */ + NM_CHANC_BCCH = 0x06, /* BCCH + CCCH */ + NM_CHANC_BCCH_CBCH = 0x07, /* CHANC_BCCHComb + CBCH */ + NM_CHANC_SDCCH_CBCH = 0x08, /* CHANC_SDCCH8 + CBCH */ + /* ip.access */ + NM_CHANC_IPAC_bPDCH = 0x0b, /* PBCCH + PCCCH + PDTCH/F + PACCH/F + + PTCCH/F */ + NM_CHANC_IPAC_cPDCH = 0x0c, /* PBCCH + PDTCH/F + PACCH/F + PTCCH/F */ + NM_CHANC_IPAC_PDCH = 0x0d, /* PDTCH/F + PACCH/F + PTCCH/F */ + NM_CHANC_IPAC_TCHFull_PDCH = 0x80, + NM_CHANC_IPAC_TCHFull_TCHHalf = 0x81, +}; + +/* Section 9.4.16: Event Type */ +enum abis_nm_event_type { + NM_EVT_COMM_FAIL = 0x00, + NM_EVT_QOS_FAIL = 0x01, + NM_EVT_PROC_FAIL = 0x02, + NM_EVT_EQUIP_FAIL = 0x03, + NM_EVT_ENV_FAIL = 0x04, +}; + +/* Section: 9.4.63: Perceived Severity */ +enum abis_nm_severity { + NM_SEVER_CEASED = 0x00, + NM_SEVER_CRITICAL = 0x01, + NM_SEVER_MAJOR = 0x02, + NM_SEVER_MINOR = 0x03, + NM_SEVER_WARNING = 0x04, + NM_SEVER_INDETERMINATE = 0x05, +}; + +/* Section 9.4.43: Probable Cause Type */ +enum abis_nm_pcause_type { + NM_PCAUSE_T_X721 = 0x01, + NM_PCAUSE_T_GSM = 0x02, + NM_PCAUSE_T_MANUF = 0x03, +}; + +/* Section 9.4.36: NACK Causes */ +enum abis_nm_nack_cause { + /* General Nack Causes */ + NM_NACK_INCORR_STRUCT = 0x01, + NM_NACK_MSGTYPE_INVAL = 0x02, + NM_NACK_OBJCLASS_INVAL = 0x05, + NM_NACK_OBJCLASS_NOTSUPP = 0x06, + NM_NACK_BTSNR_UNKN = 0x07, + NM_NACK_TRXNR_UNKN = 0x08, + NM_NACK_OBJINST_UNKN = 0x09, + NM_NACK_ATTRID_INVAL = 0x0c, + NM_NACK_ATTRID_NOTSUPP = 0x0d, + NM_NACK_PARAM_RANGE = 0x0e, + NM_NACK_ATTRLIST_INCONSISTENT = 0x0f, + NM_NACK_SPEC_IMPL_NOTSUPP = 0x10, + NM_NACK_CANT_PERFORM = 0x11, + /* Specific Nack Causes */ + NM_NACK_RES_NOTIMPL = 0x19, + NM_NACK_RES_NOTAVAIL = 0x1a, + NM_NACK_FREQ_NOTAVAIL = 0x1b, + NM_NACK_TEST_NOTSUPP = 0x1c, + NM_NACK_CAPACITY_RESTR = 0x1d, + NM_NACK_PHYSCFG_NOTPERFORM = 0x1e, + NM_NACK_TEST_NOTINIT = 0x1f, + NM_NACK_PHYSCFG_NOTRESTORE = 0x20, + NM_NACK_TEST_NOSUCH = 0x21, + NM_NACK_TEST_NOSTOP = 0x22, + NM_NACK_MSGINCONSIST_PHYSCFG = 0x23, + NM_NACK_FILE_INCOMPLETE = 0x25, + NM_NACK_FILE_NOTAVAIL = 0x26, + NM_NACK_FILE_NOTACTIVATE = 0x27, + NM_NACK_REQ_NOT_GRANT = 0x28, + NM_NACK_WAIT = 0x29, + NM_NACK_NOTH_REPORT_EXIST = 0x2a, + NM_NACK_MEAS_NOTSUPP = 0x2b, + NM_NACK_MEAS_NOTSTART = 0x2c, +}; + +/* Section 9.4.1 */ +struct abis_nm_channel { + uint8_t attrib; + uint8_t bts_port; + uint8_t timeslot; + uint8_t subslot; +} __attribute__ ((packed)); + +/* Siemens BS-11 specific objects in the SienemsHW (0xA5) object class */ +enum abis_bs11_objtype { + BS11_OBJ_ALCO = 0x01, + BS11_OBJ_BBSIG = 0x02, /* obj_class: 0,1 */ + BS11_OBJ_TRX1 = 0x03, /* only DEACTIVATE TRX1 */ + BS11_OBJ_CCLK = 0x04, + BS11_OBJ_GPSU = 0x06, + BS11_OBJ_LI = 0x07, + BS11_OBJ_PA = 0x09, /* obj_class: 0, 1*/ +}; + +enum abis_bs11_trx_power { + BS11_TRX_POWER_GSM_2W = 0x06, + BS11_TRX_POWER_GSM_250mW= 0x07, + BS11_TRX_POWER_GSM_80mW = 0x08, + BS11_TRX_POWER_GSM_30mW = 0x09, + BS11_TRX_POWER_DCS_3W = 0x0a, + BS11_TRX_POWER_DCS_1W6 = 0x0b, + BS11_TRX_POWER_DCS_500mW= 0x0c, + BS11_TRX_POWER_DCS_160mW= 0x0d, +}; + +enum abis_bs11_li_pll_mode { + BS11_LI_PLL_LOCKED = 2, + BS11_LI_PLL_STANDALONE = 3, +}; + +enum abis_bs11_line_cfg { + BS11_LINE_CFG_STAR = 0x00, + BS11_LINE_CFG_MULTIDROP = 0x01, + BS11_LINE_CFG_LOOP = 0x02, +}; + +enum abis_bs11_phase { + BS11_STATE_SOFTWARE_RQD = 0x01, + BS11_STATE_LOAD_SMU_INTENDED = 0x11, + BS11_STATE_LOAD_SMU_SAFETY = 0x21, + BS11_STATE_LOAD_FAILED = 0x31, + BS11_STATE_LOAD_DIAGNOSTIC = 0x41, + BS11_STATE_WARM_UP = 0x51, + BS11_STATE_WARM_UP_2 = 0x52, + BS11_STATE_WAIT_MIN_CFG = 0x62, + BS11_STATE_MAINTENANCE = 0x72, + BS11_STATE_LOAD_MBCCU = 0x92, + BS11_STATE_WAIT_MIN_CFG_2 = 0xA2, + BS11_STATE_NORMAL = 0x03, + BS11_STATE_ABIS_LOAD = 0x13, +}; + +enum abis_nm_ipacc_test_no { + NM_IPACC_TESTNO_RLOOP_ANT = 0x01, + NM_IPACC_TESTNO_RLOOP_XCVR = 0x02, + NM_IPACC_TESTNO_FUNC_OBJ = 0x03, + NM_IPACC_TESTNO_CHAN_USAGE = 0x40, + NM_IPACC_TESTNO_BCCH_CHAN_USAGE = 0x41, + NM_IPACC_TESTNO_FREQ_SYNC = 0x42, + NM_IPACC_TESTNO_BCCH_INFO = 0x43, + NM_IPACC_TESTNO_TX_BEACON = 0x44, + NM_IPACC_TESTNO_SYSINFO_MONITOR = 0x45, + NM_IPACC_TESTNO_BCCCH_MONITOR = 0x46, +}; + +/* first byte after length inside NM_ATT_TEST_REPORT */ +enum abis_nm_ipacc_test_res { + NM_IPACC_TESTRES_SUCCESS = 0, + NM_IPACC_TESTRES_TIMEOUT = 1, + NM_IPACC_TESTRES_NO_CHANS = 2, + NM_IPACC_TESTRES_PARTIAL = 3, + NM_IPACC_TESTRES_STOPPED = 4, +}; + +/* internal IE inside NM_ATT_TEST_REPORT */ +enum abis_nm_ipacc_testres_ie { + NM_IPACC_TR_IE_FREQ_ERR_LIST = 3, + NM_IPACC_TR_IE_CHAN_USAGE = 4, + NM_IPACC_TR_IE_BCCH_INFO = 6, + NM_IPACC_TR_IE_RESULT_DETAILS = 8, + NM_IPACC_TR_IE_FREQ_ERR = 18, +}; + +enum ipac_eie { + NM_IPAC_EIE_ARFCN_WHITE = 0x01, + NM_IPAC_EIE_ARFCH_BLACK = 0x02, + NM_IPAC_EIE_FREQ_ERR_LIST = 0x03, + NM_IPAC_EIE_CHAN_USE_LIST = 0x04, + NM_IPAC_EIE_BCCH_INFO_TYPE = 0x05, + NM_IPAC_EIE_BCCH_INFO = 0x06, + NM_IPAC_EIE_CONFIG = 0x07, + NM_IPAC_EIE_RES_DETAILS = 0x08, + NM_IPAC_EIE_RXLEV_THRESH = 0x09, + NM_IPAC_EIE_FREQ_SYNC_OPTS = 0x0a, + NM_IPAC_EIE_MAC_ADDR = 0x0b, + NM_IPAC_EIE_HW_SW_COMPAT_NR = 0x0c, + NM_IPAC_EIE_MANUF_SER_NR = 0x0d, + NM_IPAC_EIE_OEM_ID = 0x0e, + NM_IPAC_EIE_DATE_TIME_MANUF = 0x0f, + NM_IPAC_EIE_DATE_TIME_CALIB = 0x10, + NM_IPAC_EIE_BEACON_INFO = 0x11, + NM_IPAC_EIE_FREQ_ERR = 0x12, + /* FIXME */ + NM_IPAC_EIE_FREQ_BANDS = 0x1c, + NM_IPAC_EIE_MAX_TA = 0x1d, + NM_IPAC_EIE_CIPH_ALGOS = 0x1e, + NM_IPAC_EIE_CHAN_TYPES = 0x1f, + NM_IPAC_EIE_CHAN_MODES = 0x20, + NM_IPAC_EIE_GPRS_CODING = 0x21, + NM_IPAC_EIE_RTP_FEATURES = 0x22, + NM_IPAC_EIE_RSL_FEATURES = 0x23, + NM_IPAC_EIE_BTS_HW_CLASS = 0x24, + NM_IPAC_EIE_BTS_ID = 0x25, +}; + +enum ipac_bcch_info_type { + IPAC_BINF_RXLEV = (1 << 8), + IPAC_BINF_RXQUAL = (1 << 9), + IPAC_BINF_FREQ_ERR_QUAL = (1 << 10), + IPAC_BINF_FRAME_OFFSET = (1 << 11), + IPAC_BINF_FRAME_NR_OFFSET = (1 << 12), + IPAC_BINF_BSIC = (1 << 13), + IPAC_BINF_CGI = (1 << 14), + IPAC_BINF_NEIGH_BA_SI2 = (1 << 15), + IPAC_BINF_NEIGH_BA_SI2bis = (1 << 0), + IPAC_BINF_NEIGH_BA_SI2ter = (1 << 1), + IPAC_BINF_CELL_ALLOC = (1 << 2), +}; + +#endif /* PROTO_GSM_12_21_H */ diff --git a/include/osmocom/gsm/rsl.h b/include/osmocom/gsm/rsl.h new file mode 100644 index 00000000..7e46330f --- /dev/null +++ b/include/osmocom/gsm/rsl.h @@ -0,0 +1,41 @@ +#ifndef _OSMOCORE_RSL_H +#define _OSMOCORE_RSL_H + +#include +#include +#include + +void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type); + +void rsl_init_cchan_hdr(struct abis_rsl_cchan_hdr *ch, uint8_t msg_type); + +extern const struct tlv_definition rsl_att_tlvdef; +#define rsl_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0) + +/* encode channel number as per Section 9.3.1 */ +uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot); +/* decode channel number as per Section 9.3.1 */ +int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot); +/* Turns channel number into a string */ +const char *rsl_chan_nr_str(uint8_t chan_nr); + + +const char *rsl_err_name(uint8_t err); +const char *rsl_rlm_cause_name(uint8_t err); + +/* Section 3.3.2.3 TS 05.02. I think this looks like a table */ +int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf); + +/* Push a RSL RLL header */ +void rsl_rll_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr, + uint8_t link_id, int transparent); + +/* Push a RSL RLL header with L3_INFO IE */ +void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr, + uint8_t link_id, int transparent); + +/* Allocate msgb and fill with simple RSL RLL header */ +struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr, + uint8_t link_id, int transparent); +#endif /* _OSMOCORE_RSL_H */ diff --git a/include/osmocom/gsm/rxlev_stat.h b/include/osmocom/gsm/rxlev_stat.h new file mode 100644 index 00000000..415509dc --- /dev/null +++ b/include/osmocom/gsm/rxlev_stat.h @@ -0,0 +1,22 @@ +#ifndef _OSMOCORE_RXLEV_STATS_H +#define _OSMOCORE_RXLEV_STATS_H + +#define NUM_RXLEVS 32 +#define NUM_ARFCNS 1024 + +struct rxlev_stats { + /* the maximum number of ARFCN's is 1024, and there are 32 RxLevels, + * so in we keep one 1024bit-bitvec for each RxLev */ + uint8_t rxlev_buckets[NUM_RXLEVS][NUM_ARFCNS/8]; +}; + +void rxlev_stat_input(struct rxlev_stats *st, uint16_t arfcn, uint8_t rxlev); + +/* get the next ARFCN that has the specified Rxlev */ +int16_t rxlev_stat_get_next(const struct rxlev_stats *st, uint8_t rxlev, int16_t arfcn); + +void rxlev_stat_reset(struct rxlev_stats *st); + +void rxlev_stat_dump(const struct rxlev_stats *st); + +#endif /* _OSMOCORE_RXLEV_STATS_H */ diff --git a/include/osmocom/gsm/tlv.h b/include/osmocom/gsm/tlv.h new file mode 100644 index 00000000..552af2bd --- /dev/null +++ b/include/osmocom/gsm/tlv.h @@ -0,0 +1,260 @@ +#ifndef _TLV_H +#define _TLV_H + +#include +#include + +#include + +/* Terminology / wording + tag length value (in bits) + + V - - 8 + LV - 8 N * 8 + TLV 8 8 N * 8 + TL16V 8 16 N * 8 + TLV16 8 8 N * 16 + TvLV 8 8/16 N * 8 + +*/ + +#define LV_GROSS_LEN(x) (x+1) +#define TLV_GROSS_LEN(x) (x+2) +#define TLV16_GROSS_LEN(x) ((2*x)+2) +#define TL16V_GROSS_LEN(x) (x+3) +#define L16TV_GROSS_LEN(x) (x+3) + +#define TVLV_MAX_ONEBYTE 0x7f + +static inline uint16_t TVLV_GROSS_LEN(uint16_t len) +{ + if (len <= TVLV_MAX_ONEBYTE) + return TLV_GROSS_LEN(len); + else + return TL16V_GROSS_LEN(len); +} + +/* TLV generation */ + +static inline uint8_t *lv_put(uint8_t *buf, uint8_t len, + const uint8_t *val) +{ + *buf++ = len; + memcpy(buf, val, len); + return buf + len; +} + +static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len, + const uint8_t *val) +{ + *buf++ = tag; + *buf++ = len; + memcpy(buf, val, len); + return buf + len; +} + +static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len, + const uint16_t *val) +{ + *buf++ = tag; + *buf++ = len; + memcpy(buf, val, len*2); + return buf + len*2; +} + +static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len, + const uint8_t *val) +{ + *buf++ = tag; + *buf++ = len >> 8; + *buf++ = len & 0xff; + memcpy(buf, val, len); + return buf + len*2; +} + +static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len, + const uint8_t *val) +{ + uint8_t *ret; + + if (len <= TVLV_MAX_ONEBYTE) { + ret = tlv_put(buf, tag, len, val); + buf[1] |= 0x80; + } else + ret = tl16v_put(buf, tag, len, val); + + return ret; +} + +static inline uint8_t *msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val) +{ + uint8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len)); + return tlv16_put(buf, tag, len, val); +} + +static inline uint8_t *msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t len, + const uint8_t *val) +{ + uint8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len)); + return tl16v_put(buf, tag, len, val); +} + +static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len, + const uint8_t *val) +{ + uint8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len)); + return tvlv_put(buf, tag, len, val); +} + +static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag, + const uint8_t *val) +{ + uint8_t *buf = msgb_put(msg, L16TV_GROSS_LEN(len)); + + *buf++ = len >> 8; + *buf++ = len & 0xff; + *buf++ = tag; + memcpy(buf, val, len); + return buf + len; +} + +static inline uint8_t *v_put(uint8_t *buf, uint8_t val) +{ + *buf++ = val; + return buf; +} + +static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag, + uint8_t val) +{ + *buf++ = tag; + *buf++ = val; + return buf; +} + +static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag, + unsigned int len, const uint8_t *val) +{ + *buf++ = tag; + memcpy(buf, val, len); + return buf + len; +} + +/* 'val' is still in host byte order! */ +static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag, + uint16_t val) +{ + *buf++ = tag; + *buf++ = val >> 8; + *buf++ = val & 0xff; + return buf; +} + +static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val) +{ + uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len)); + return lv_put(buf, len, val); +} + +static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val) +{ + uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len)); + return tlv_put(buf, tag, len, val); +} + +static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val) +{ + uint8_t *buf = msgb_put(msg, 2); + return tv_put(buf, tag, val); +} + +static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag, + unsigned int len, const uint8_t *val) +{ + uint8_t *buf = msgb_put(msg, 1+len); + return tv_fixed_put(buf, tag, len, val); +} + +static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val) +{ + uint8_t *buf = msgb_put(msg, 1); + return v_put(buf, val); +} + +static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val) +{ + uint8_t *buf = msgb_put(msg, 3); + return tv16_put(buf, tag, val); +} + +static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val) +{ + uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len)); + return tlv_put(buf, tag, len, val); +} + +static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val) +{ + uint8_t *buf = msgb_push(msg, 2); + return tv_put(buf, tag, val); +} + +static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val) +{ + uint8_t *buf = msgb_push(msg, 3); + return tv16_put(buf, tag, val); +} + +static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len, + const uint8_t *val) +{ + uint8_t *buf = msgb_push(msg, TVLV_GROSS_LEN(len)); + return tvlv_put(buf, tag, len, val); +} + +/* TLV parsing */ + +struct tlv_p_entry { + uint16_t len; + const uint8_t *val; +}; + +enum tlv_type { + TLV_TYPE_NONE, + TLV_TYPE_FIXED, + TLV_TYPE_T, + TLV_TYPE_TV, + TLV_TYPE_TLV, + TLV_TYPE_TL16V, + TLV_TYPE_TvLV, + TLV_TYPE_SINGLE_TV +}; + +struct tlv_def { + enum tlv_type type; + uint8_t fixed_len; +}; + +struct tlv_definition { + struct tlv_def def[0xff]; +}; + +struct tlv_parsed { + struct tlv_p_entry lv[0xff]; +}; + +extern struct tlv_definition tvlv_att_def; + +int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val, + const struct tlv_definition *def, + const uint8_t *buf, int buf_len); +int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def, + const uint8_t *buf, int buf_len, uint8_t lv_tag, uint8_t lv_tag2); +/* take a master (src) tlvdev and fill up all empty slots in 'dst' */ +void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src); + +#define TLVP_PRESENT(x, y) ((x)->lv[y].val) +#define TLVP_LEN(x, y) (x)->lv[y].len +#define TLVP_VAL(x, y) (x)->lv[y].val + +#endif /* _TLV_H */ diff --git a/include/osmocom/vty/telnet_interface.h b/include/osmocom/vty/telnet_interface.h index 444e6497..0c034e41 100644 --- a/include/osmocom/vty/telnet_interface.h +++ b/include/osmocom/vty/telnet_interface.h @@ -21,8 +21,8 @@ #ifndef TELNET_INTERFACE_H #define TELNET_INTERFACE_H -#include -#include +#include +#include #include diff --git a/include/osmocore/Makefile.am b/include/osmocore/Makefile.am deleted file mode 100644 index b65589a6..00000000 --- a/include/osmocore/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \ - tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \ - gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \ - gsm48_ie.h logging.h gsm0808.h rate_ctr.h gsmtap_util.h \ - plugin.h crc16.h panic.h process.h gsm0480.h msgfile.h \ - backtrace.h - -if ENABLE_TALLOC -osmocore_HEADERS += talloc.h -endif - -osmocoredir = $(includedir)/osmocore - -SUBDIRS = protocol diff --git a/include/osmocore/backtrace.h b/include/osmocore/backtrace.h deleted file mode 100644 index bbbb2c28..00000000 --- a/include/osmocore/backtrace.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _OSMO_BACKTRACE_H_ -#define _OSMO_BACKTRACE_H_ - -void generate_backtrace(); - -#endif diff --git a/include/osmocore/bits.h b/include/osmocore/bits.h deleted file mode 100644 index 8d4a0789..00000000 --- a/include/osmocore/bits.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _OSMO_BITS_H -#define _OSMO_BITS_H - -#include - -typedef uint8_t sbit_t; /* soft bit (-127...127) */ -typedef uint8_t ubit_t; /* unpacked bit (0 or 1) */ -typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */ - -/* - NOTE on the endianess of pbit_t: - Bits in a pbit_t are ordered MSB first, i.e. 0x80 is the first bit. - Bit i in a pbit_t array is array[i/8] & (1<<(7-i%8)) -*/ - -/* determine how many bytes we would need for 'num_bits' packed bits */ -static inline unsigned int osmo_pbit_bytesize(unsigned int num_bits) -{ - unsigned int pbit_bytesize = num_bits / 8; - - if (num_bits % 8) - pbit_bytesize++; - - return pbit_bytesize; -} - -/* convert unpacked bits to packed bits, return length in bytes */ -int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits); - -/* convert packed bits to unpacked bits, return length in bytes */ -int osmo_pbit2ubit(ubit_t *out, const pbit_t *in, unsigned int num_bits); - -/* convert unpacked bits to packed bits (extended options but slower), - * return length in bytes (max written ofs of output buffer + 1) */ -int osmo_ubit2pbit_ext(pbit_t *out, unsigned int out_ofs, - const ubit_t *in, unsigned int in_ofs, - unsigned int num_bits, int lsb_mode); - -/* convert packed bits to unpacked bits (extended options but slower), - * return length in bytes (max written ofs of output buffer + 1) */ -int osmo_pbit2ubit_ext(ubit_t *out, unsigned int out_ofs, - const pbit_t *in, unsigned int in_ofs, - unsigned int num_bits, int lsb_mode); - -#endif diff --git a/include/osmocore/bitvec.h b/include/osmocore/bitvec.h deleted file mode 100644 index 42977fb2..00000000 --- a/include/osmocore/bitvec.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _BITVEC_H -#define _BITVEC_H - -/* bit vector utility routines */ - -/* (C) 2009 by Harald Welte - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - - -/* In GSM mac blocks, every bit can be 0 or 1, or L or H. L/H are - * defined relative to the 0x2b padding pattern */ -enum bit_value { - ZERO = 0, - ONE = 1, - L = 2, - H = 3, -}; - -struct bitvec { - unsigned int cur_bit; /* curser to the next unused bit */ - unsigned int data_len; /* length of data array in bytes */ - uint8_t *data; /* pointer to data array */ -}; - -/* check if the bit is 0 or 1 for a given position inside a bitvec */ -enum bit_value bitvec_get_bit_pos(const struct bitvec *bv, unsigned int bitnr); - -/* check if the bit is L or H for a given position inside a bitvec */ -enum bit_value bitvec_get_bit_pos_high(const struct bitvec *bv, - unsigned int bitnr); - -/* get the Nth set bit inside the bit vector */ -unsigned int bitvec_get_nth_set_bit(const struct bitvec *bv, unsigned int n); - -/* Set a bit at given position */ -int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum, - enum bit_value bit); - -/* Set the next bit in the vector */ -int bitvec_set_bit(struct bitvec *bv, enum bit_value bit); - -/* get the next bit (low/high) inside a bitvec */ -int bitvec_get_bit_high(struct bitvec *bv); - -/* Set multiple bits at the current position */ -int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count); - -/* Add an unsigned integer (of length count bits) to current position */ -int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count); - -/* get multiple bits (based on numeric value) from current pos */ -int bitvec_get_uint(struct bitvec *bv, int num_bits); - - -/* Pad the bit vector up to a certain bit position */ -int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit); - -#endif /* _BITVEC_H */ diff --git a/include/osmocore/comp128.h b/include/osmocore/comp128.h deleted file mode 100644 index c37808f0..00000000 --- a/include/osmocore/comp128.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * COMP128 header - * - * See comp128.c for details - */ - -#ifndef __COMP128_H__ -#define __COMP128_H__ - -#include - -/* - * Performs the COMP128 algorithm (used as A3/A8) - * ki : uint8_t [16] - * srand : uint8_t [16] - * sres : uint8_t [4] - * kc : uint8_t [8] - */ -void comp128(uint8_t *ki, uint8_t *srand, uint8_t *sres, uint8_t *kc); - -#endif /* __COMP128_H__ */ - diff --git a/include/osmocore/crc16.h b/include/osmocore/crc16.h deleted file mode 100644 index 7a512490..00000000 --- a/include/osmocore/crc16.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This was copied from the linux kernel and adjusted for our types. - */ -/* - * crc16.h - CRC-16 routine - * - * Implements the standard CRC-16: - * Width 16 - * Poly 0x8005 (x^16 + x^15 + x^2 + 1) - * Init 0 - * - * Copyright (c) 2005 Ben Gardner - * - * This source code is licensed under the GNU General Public License, - * Version 2. See the file COPYING for more details. - */ - -#ifndef __CRC16_H -#define __CRC16_H - -#include - -#include - -extern uint16_t const crc16_table[256]; - -extern uint16_t crc16(uint16_t crc, const uint8_t *buffer, size_t len); - -static inline uint16_t crc16_byte(uint16_t crc, const uint8_t data) -{ - return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff]; -} - -#endif /* __CRC16_H */ diff --git a/include/osmocore/gsm0480.h b/include/osmocore/gsm0480.h deleted file mode 100644 index b504332e..00000000 --- a/include/osmocore/gsm0480.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef gsm0480_h -#define gsm0480_h - -#include "msgb.h" -#include "protocol/gsm_04_08.h" -#include "protocol/gsm_04_80.h" - -#define MAX_LEN_USSD_STRING 31 - -struct ussd_request { - char text[MAX_LEN_USSD_STRING + 1]; - uint8_t transaction_id; - uint8_t invoke_id; -}; - -int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len, - struct ussd_request *request); - -struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text); -struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text); -struct msgb *gsm0480_create_notifySS(const char *text); - -int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id); -int gsm0480_wrap_facility(struct msgb *msg); - -#endif diff --git a/include/osmocore/gsm0808.h b/include/osmocore/gsm0808.h deleted file mode 100644 index 1d853775..00000000 --- a/include/osmocore/gsm0808.h +++ /dev/null @@ -1,46 +0,0 @@ -/* (C) 2009,2010 by Holger Hans Peter Freyther - * (C) 2009,2010 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef OSMOCORE_GSM0808_H -#define OSMOCORE_GSM0808_H - -#include "tlv.h" - -struct msgb; - -struct msgb *gsm0808_create_layer3(struct msgb *msg, uint16_t netcode, uint16_t countrycode, int lac, uint16_t ci); -struct msgb *gsm0808_create_reset(void); -struct msgb *gsm0808_create_clear_command(uint8_t reason); -struct msgb *gsm0808_create_clear_complete(void); -struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id); -struct msgb *gsm0808_create_cipher_reject(uint8_t cause); -struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark, uint8_t length); -struct msgb *gsm0808_create_sapi_reject(uint8_t link_id); -struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause, - uint8_t chosen_channel, uint8_t encr_alg_id, - uint8_t speech_mode); -struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause); -struct msgb *gsm0808_create_clear_rqst(uint8_t cause); - -struct msgb *gsm0808_create_dtap(struct msgb *msg, uint8_t link_id); -void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id); - -const struct tlv_definition *gsm0808_att_tlvdef(); - -#endif diff --git a/include/osmocore/gsm48.h b/include/osmocore/gsm48.h deleted file mode 100644 index ffe0399b..00000000 --- a/include/osmocore/gsm48.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _OSMOCORE_GSM48_H -#define _OSMOCORE_GSM48_H - -#include -#include -#include - -/* A parsed GPRS routing area */ -struct gprs_ra_id { - uint16_t mnc; - uint16_t mcc; - uint16_t lac; - uint8_t rac; -}; - -extern const struct tlv_definition gsm48_att_tlvdef; -extern const struct tlv_definition gsm48_rr_att_tlvdef; -extern const struct tlv_definition gsm48_mm_att_tlvdef; -const char *gsm48_cc_state_name(uint8_t state); -const char *gsm48_cc_msg_name(uint8_t msgtype); -const char *rr_cause_name(uint8_t cause); - -void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc, - uint16_t mnc, uint16_t lac); -int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi); -int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi); - -/* Convert Mobile Identity (10.5.1.4) to string */ -int gsm48_mi_to_string(char *string, const int str_len, - const uint8_t *mi, const int mi_len); - -/* Parse Routeing Area Identifier */ -void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf); -int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid); - -#endif diff --git a/include/osmocore/gsm48_ie.h b/include/osmocore/gsm48_ie.h deleted file mode 100644 index fa66159f..00000000 --- a/include/osmocore/gsm48_ie.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef _OSMOCORE_GSM48_IE_H -#define _OSMOCORE_GSM48_IE_H - -#include -#include -#include - -#include -#include -#include -#include - -/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */ -int gsm48_decode_bcd_number(char *output, int output_len, - const uint8_t *bcd_lv, int h_len); - -/* convert a ASCII phone number to 'called/calling/connect party BCD number' */ -int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len, - int h_len, const char *input); -/* decode 'bearer capability' */ -int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap, - const uint8_t *lv); -/* encode 'bearer capability' */ -int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only, - const struct gsm_mncc_bearer_cap *bcap); -/* decode 'call control cap' */ -int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv); -/* encode 'call control cap' */ -int gsm48_encode_cccap(struct msgb *msg, - const struct gsm_mncc_cccap *ccap); -/* decode 'called party BCD number' */ -int gsm48_decode_called(struct gsm_mncc_number *called, - const uint8_t *lv); -/* encode 'called party BCD number' */ -int gsm48_encode_called(struct msgb *msg, - const struct gsm_mncc_number *called); -/* decode callerid of various IEs */ -int gsm48_decode_callerid(struct gsm_mncc_number *callerid, - const uint8_t *lv); -/* encode callerid of various IEs */ -int gsm48_encode_callerid(struct msgb *msg, int ie, int max_len, - const struct gsm_mncc_number *callerid); -/* decode 'cause' */ -int gsm48_decode_cause(struct gsm_mncc_cause *cause, - const uint8_t *lv); -/* encode 'cause' */ -int gsm48_encode_cause(struct msgb *msg, int lv_only, - const struct gsm_mncc_cause *cause); -/* decode 'calling number' */ -int gsm48_decode_calling(struct gsm_mncc_number *calling, - const uint8_t *lv); -/* encode 'calling number' */ -int gsm48_encode_calling(struct msgb *msg, - const struct gsm_mncc_number *calling); -/* decode 'connected number' */ -int gsm48_decode_connected(struct gsm_mncc_number *connected, - const uint8_t *lv); -/* encode 'connected number' */ -int gsm48_encode_connected(struct msgb *msg, - const struct gsm_mncc_number *connected); -/* decode 'redirecting number' */ -int gsm48_decode_redirecting(struct gsm_mncc_number *redirecting, - const uint8_t *lv); -/* encode 'redirecting number' */ -int gsm48_encode_redirecting(struct msgb *msg, - const struct gsm_mncc_number *redirecting); -/* decode 'facility' */ -int gsm48_decode_facility(struct gsm_mncc_facility *facility, - const uint8_t *lv); -/* encode 'facility' */ -int gsm48_encode_facility(struct msgb *msg, int lv_only, - const struct gsm_mncc_facility *facility); -/* decode 'notify' */ -int gsm48_decode_notify(int *notify, const uint8_t *v); -/* encode 'notify' */ -int gsm48_encode_notify(struct msgb *msg, int notify); -/* decode 'signal' */ -int gsm48_decode_signal(int *signal, const uint8_t *v); -/* encode 'signal' */ -int gsm48_encode_signal(struct msgb *msg, int signal); -/* decode 'keypad' */ -int gsm48_decode_keypad(int *keypad, const uint8_t *lv); -/* encode 'keypad' */ -int gsm48_encode_keypad(struct msgb *msg, int keypad); -/* decode 'progress' */ -int gsm48_decode_progress(struct gsm_mncc_progress *progress, - const uint8_t *lv); -/* encode 'progress' */ -int gsm48_encode_progress(struct msgb *msg, int lv_only, - const struct gsm_mncc_progress *p); -/* decode 'user-user' */ -int gsm48_decode_useruser(struct gsm_mncc_useruser *uu, - const uint8_t *lv); -/* encode 'useruser' */ -int gsm48_encode_useruser(struct msgb *msg, int lv_only, - const struct gsm_mncc_useruser *uu); -/* decode 'ss version' */ -int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv, - const uint8_t *lv); -/* encode 'ss version' */ -int gsm48_encode_ssversion(struct msgb *msg, - const struct gsm_mncc_ssversion *ssv); -/* decode 'more data' does not require a function, because it has no value */ -/* encode 'more data' */ -int gsm48_encode_more(struct msgb *msg); - -/* structure of one frequency */ -struct gsm_sysinfo_freq { - /* if the frequency included in the sysinfo */ - uint8_t mask; -}; - -/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */ -int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd, - uint8_t len, uint8_t mask, uint8_t frqt); - -#endif diff --git a/include/osmocore/gsm_utils.h b/include/osmocore/gsm_utils.h deleted file mode 100644 index 19adb70a..00000000 --- a/include/osmocore/gsm_utils.h +++ /dev/null @@ -1,117 +0,0 @@ -/* GSM utility functions, e.g. coding and decoding */ -/* - * (C) 2008 by Daniel Willmann - * (C) 2009 by Holger Hans Peter Freyther - * (C) 2009-2010 by Harald Welte - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef GSM_UTILS_H -#define GSM_UTILS_H - -#include - -#define ADD_MODULO(sum, delta, modulo) do { \ - if ((sum += delta) >= modulo) \ - sum -= modulo; \ - } while (0) - -#define GSM_MAX_FN (26*51*2048) - -struct gsm_time { - uint32_t fn; /* FN count */ - uint16_t t1; /* FN div (26*51) */ - uint8_t t2; /* FN modulo 26 */ - uint8_t t3; /* FN modulo 51 */ - uint8_t tc; -}; - -enum gsm_band { - GSM_BAND_850 = 1, - GSM_BAND_900 = 2, - GSM_BAND_1800 = 4, - GSM_BAND_1900 = 8, - GSM_BAND_450 = 0x10, - GSM_BAND_480 = 0x20, - GSM_BAND_750 = 0x40, - GSM_BAND_810 = 0x80, -}; - -const char *gsm_band_name(enum gsm_band band); -enum gsm_band gsm_band_parse(const char *mhz); - -int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length); -int gsm_7bit_encode(uint8_t *result, const char *data); - -int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm); -int ms_pwr_dbm(enum gsm_band band, uint8_t lvl); - -/* According to TS 08.05 Chapter 8.1.4 */ -int rxlev2dbm(uint8_t rxlev); -uint8_t dbm2rxlev(int dbm); - -/* According to GSM 04.08 Chapter 10.5.1.6 */ -static inline int ms_cm2_a5n_support(uint8_t *cm2, int n) { - switch (n) { - case 0: return 1; - case 1: return (cm2[0] & (1<<3)) ? 0 : 1; - case 2: return (cm2[2] & (1<<0)) ? 1 : 0; - case 3: return (cm2[2] & (1<<1)) ? 1 : 0; - default: - return 0; - } -} - -/* According to GSM 04.08 Chapter 10.5.2.29 */ -static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; } -static inline int rach_max_trans_raw2val(int raw) { - const int tbl[4] = { 1, 2, 4, 7 }; - return tbl[raw & 3]; -} - -#define ARFCN_PCS 0x8000 -#define ARFCN_UPLINK 0x4000 -#define ARFCN_FLAG_MASK 0xf000 /* Reserve the upper 5 bits for flags */ - -enum gsm_band gsm_arfcn2band(uint16_t arfcn); - -/* Convert an ARFCN to the frequency in MHz * 10 */ -uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink); - -/* Convert from frame number to GSM time */ -void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn); - -/* Convert from GSM time to frame number */ -uint32_t gsm_gsmtime2fn(struct gsm_time *time); - -/* GSM TS 03.03 Chapter 2.6 */ -enum gprs_tlli_type { - TLLI_LOCAL, - TLLI_FOREIGN, - TLLI_RANDOM, - TLLI_AUXILIARY, - TLLI_RESERVED, -}; - -/* TS 03.03 Chapter 2.6 */ -int gprs_tlli_type(uint32_t tlli); - -uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type); - -#endif diff --git a/include/osmocore/gsmtap.h b/include/osmocore/gsmtap.h deleted file mode 100644 index 236b25ac..00000000 --- a/include/osmocore/gsmtap.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef _GSMTAP_H -#define _GSMTAP_H - -/* gsmtap header, pseudo-header in front of the actua GSM payload */ - -/* GSMTAP is a generic header format for GSM protocol captures, - * it uses the IANA-assigned UDP port number 4729 and carries - * payload in various formats of GSM interfaces such as Um MAC - * blocks or Um bursts. - * - * Example programs generating GSMTAP data are airprobe - * (http://airprobe.org/) or OsmocomBB (http://bb.osmocom.org/) - */ - -#include - -#define GSMTAP_VERSION 0x02 - -#define GSMTAP_TYPE_UM 0x01 -#define GSMTAP_TYPE_ABIS 0x02 -#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */ -#define GSMTAP_TYPE_SIM 0x04 -#define GSMTAP_TYPE_TETRA_I1 0x05 /* tetra air interface */ -#define GSMTAP_TYPE_TETRA_I1_BURST 0x06 /* tetra air interface */ - -/* sub-types for TYPE_UM_BURST */ -#define GSMTAP_BURST_UNKNOWN 0x00 -#define GSMTAP_BURST_FCCH 0x01 -#define GSMTAP_BURST_PARTIAL_SCH 0x02 -#define GSMTAP_BURST_SCH 0x03 -#define GSMTAP_BURST_CTS_SCH 0x04 -#define GSMTAP_BURST_COMPACT_SCH 0x05 -#define GSMTAP_BURST_NORMAL 0x06 -#define GSMTAP_BURST_DUMMY 0x07 -#define GSMTAP_BURST_ACCESS 0x08 -#define GSMTAP_BURST_NONE 0x09 - -/* sub-types for TYPE_UM */ -#define GSMTAP_CHANNEL_UNKNOWN 0x00 -#define GSMTAP_CHANNEL_BCCH 0x01 -#define GSMTAP_CHANNEL_CCCH 0x02 -#define GSMTAP_CHANNEL_RACH 0x03 -#define GSMTAP_CHANNEL_AGCH 0x04 -#define GSMTAP_CHANNEL_PCH 0x05 -#define GSMTAP_CHANNEL_SDCCH 0x06 -#define GSMTAP_CHANNEL_SDCCH4 0x07 -#define GSMTAP_CHANNEL_SDCCH8 0x08 -#define GSMTAP_CHANNEL_TCH_F 0x09 -#define GSMTAP_CHANNEL_TCH_H 0x0a -#define GSMTAP_CHANNEL_ACCH 0x80 - -/* sub-types for TYPE_TETRA_AIR */ -#define GSMTAP_TETRA_BSCH 0x01 -#define GSMTAP_TETRA_AACH 0x02 -#define GSMTAP_TETRA_SCH_HU 0x03 -#define GSMTAP_TETRA_SCH_HD 0x04 -#define GSMTAP_TETRA_SCH_F 0x05 -#define GSMTAP_TETRA_BNCH 0x06 -#define GSMTAP_TETRA_STCH 0x07 -#define GSMTAP_TETRA_TCH_F 0x08 - -/* flags for the ARFCN */ -#define GSMTAP_ARFCN_F_PCS 0x8000 -#define GSMTAP_ARFCN_F_UPLINK 0x4000 -#define GSMTAP_ARFCN_MASK 0x3fff - -/* IANA-assigned well-known UDP port for GSMTAP messages */ -#define GSMTAP_UDP_PORT 4729 - -struct gsmtap_hdr { - uint8_t version; /* version, set to 0x01 currently */ - uint8_t hdr_len; /* length in number of 32bit words */ - uint8_t type; /* see GSMTAP_TYPE_* */ - uint8_t timeslot; /* timeslot (0..7 on Um) */ - - uint16_t arfcn; /* ARFCN (frequency) */ - int8_t signal_dbm; /* signal level in dBm */ - int8_t snr_db; /* signal/noise ratio in dB */ - - uint32_t frame_number; /* GSM Frame Number (FN) */ - - uint8_t sub_type; /* Type of burst/channel, see above */ - uint8_t antenna_nr; /* Antenna Number */ - uint8_t sub_slot; /* sub-slot within timeslot */ - uint8_t res; /* reserved for future use (RFU) */ - -} __attribute__((packed)); - -#endif /* _GSMTAP_H */ diff --git a/include/osmocore/gsmtap_util.h b/include/osmocore/gsmtap_util.h deleted file mode 100644 index 96449443..00000000 --- a/include/osmocore/gsmtap_util.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _GSMTAP_UTIL_H -#define _GSMTAP_UTIL_H - -#include - -/* convert RSL channel number to GSMTAP channel type */ -uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id); - -/* receive a message from L1/L2 and put it in GSMTAP */ -struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, - uint8_t ss, uint32_t fn, int8_t signal_dbm, - uint8_t snr, const uint8_t *data, unsigned int len); - -/* receive a message from L1/L2 and put it in GSMTAP */ -int gsmtap_sendmsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type, uint8_t ss, - uint32_t fn, int8_t signal_dbm, uint8_t snr, - const uint8_t *data, unsigned int len); - -int gsmtap_init(uint32_t dst_ip); - -#endif /* _GSMTAP_UTIL_H */ diff --git a/include/osmocore/linuxlist.h b/include/osmocore/linuxlist.h deleted file mode 100644 index fb99c5ec..00000000 --- a/include/osmocore/linuxlist.h +++ /dev/null @@ -1,360 +0,0 @@ -#ifndef _LINUX_LLIST_H -#define _LINUX_LLIST_H - -#include - -#ifndef inline -#define inline __inline__ -#endif - -static inline void prefetch(const void *x) {;} - -/** - * container_of - cast a member of a structure out to the containing structure - * - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (typeof( ((type *)0)->member ) *)(ptr); \ - (type *)( (char *)__mptr - offsetof(type, member) );}) - - -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized llist entries. - */ -#define LLIST_POISON1 ((void *) 0x00100100) -#define LLIST_POISON2 ((void *) 0x00200200) - -/* - * Simple doubly linked llist implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole llists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct llist_head { - struct llist_head *next, *prev; -}; - -#define LLIST_HEAD_INIT(name) { &(name), &(name) } - -#define LLIST_HEAD(name) \ - struct llist_head name = LLIST_HEAD_INIT(name) - -#define INIT_LLIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal llist manipulation where we know - * the prev/next entries already! - */ -static inline void __llist_add(struct llist_head *_new, - struct llist_head *prev, - struct llist_head *next) -{ - next->prev = _new; - _new->next = next; - _new->prev = prev; - prev->next = _new; -} - -/** - * llist_add - add a new entry - * @new: new entry to be added - * @head: llist head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void llist_add(struct llist_head *_new, struct llist_head *head) -{ - __llist_add(_new, head, head->next); -} - -/** - * llist_add_tail - add a new entry - * @new: new entry to be added - * @head: llist head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head) -{ - __llist_add(_new, head->prev, head); -} - -/* - * Delete a llist entry by making the prev/next entries - * point to each other. - * - * This is only for internal llist manipulation where we know - * the prev/next entries already! - */ -static inline void __llist_del(struct llist_head * prev, struct llist_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * llist_del - deletes entry from llist. - * @entry: the element to delete from the llist. - * Note: llist_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static inline void llist_del(struct llist_head *entry) -{ - __llist_del(entry->prev, entry->next); - entry->next = (struct llist_head *)LLIST_POISON1; - entry->prev = (struct llist_head *)LLIST_POISON2; -} - -/** - * llist_del_init - deletes entry from llist and reinitialize it. - * @entry: the element to delete from the llist. - */ -static inline void llist_del_init(struct llist_head *entry) -{ - __llist_del(entry->prev, entry->next); - INIT_LLIST_HEAD(entry); -} - -/** - * llist_move - delete from one llist and add as another's head - * @llist: the entry to move - * @head: the head that will precede our entry - */ -static inline void llist_move(struct llist_head *llist, struct llist_head *head) -{ - __llist_del(llist->prev, llist->next); - llist_add(llist, head); -} - -/** - * llist_move_tail - delete from one llist and add as another's tail - * @llist: the entry to move - * @head: the head that will follow our entry - */ -static inline void llist_move_tail(struct llist_head *llist, - struct llist_head *head) -{ - __llist_del(llist->prev, llist->next); - llist_add_tail(llist, head); -} - -/** - * llist_empty - tests whether a llist is empty - * @head: the llist to test. - */ -static inline int llist_empty(const struct llist_head *head) -{ - return head->next == head; -} - -static inline void __llist_splice(struct llist_head *llist, - struct llist_head *head) -{ - struct llist_head *first = llist->next; - struct llist_head *last = llist->prev; - struct llist_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * llist_splice - join two llists - * @llist: the new llist to add. - * @head: the place to add it in the first llist. - */ -static inline void llist_splice(struct llist_head *llist, struct llist_head *head) -{ - if (!llist_empty(llist)) - __llist_splice(llist, head); -} - -/** - * llist_splice_init - join two llists and reinitialise the emptied llist. - * @llist: the new llist to add. - * @head: the place to add it in the first llist. - * - * The llist at @llist is reinitialised - */ -static inline void llist_splice_init(struct llist_head *llist, - struct llist_head *head) -{ - if (!llist_empty(llist)) { - __llist_splice(llist, head); - INIT_LLIST_HEAD(llist); - } -} - -/** - * llist_entry - get the struct for this entry - * @ptr: the &struct llist_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the llist_struct within the struct. - */ -#define llist_entry(ptr, type, member) \ - container_of(ptr, type, member) - -/** - * llist_for_each - iterate over a llist - * @pos: the &struct llist_head to use as a loop counter. - * @head: the head for your llist. - */ -#define llist_for_each(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, prefetch(pos->next)) - -/** - * __llist_for_each - iterate over a llist - * @pos: the &struct llist_head to use as a loop counter. - * @head: the head for your llist. - * - * This variant differs from llist_for_each() in that it's the - * simplest possible llist iteration code, no prefetching is done. - * Use this for code that knows the llist to be very short (empty - * or 1 entry) most of the time. - */ -#define __llist_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * llist_for_each_prev - iterate over a llist backwards - * @pos: the &struct llist_head to use as a loop counter. - * @head: the head for your llist. - */ -#define llist_for_each_prev(pos, head) \ - for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ - pos = pos->prev, prefetch(pos->prev)) - -/** - * llist_for_each_safe - iterate over a llist safe against removal of llist entry - * @pos: the &struct llist_head to use as a loop counter. - * @n: another &struct llist_head to use as temporary storage - * @head: the head for your llist. - */ -#define llist_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * llist_for_each_entry - iterate over llist of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your llist. - * @member: the name of the llist_struct within the struct. - */ -#define llist_for_each_entry(pos, head, member) \ - for (pos = llist_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = llist_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * llist_for_each_entry_reverse - iterate backwards over llist of given type. - * @pos: the type * to use as a loop counter. - * @head: the head for your llist. - * @member: the name of the llist_struct within the struct. - */ -#define llist_for_each_entry_reverse(pos, head, member) \ - for (pos = llist_entry((head)->prev, typeof(*pos), member), \ - prefetch(pos->member.prev); \ - &pos->member != (head); \ - pos = llist_entry(pos->member.prev, typeof(*pos), member), \ - prefetch(pos->member.prev)) - -/** - * llist_for_each_entry_continue - iterate over llist of given type - * continuing after existing point - * @pos: the type * to use as a loop counter. - * @head: the head for your llist. - * @member: the name of the llist_struct within the struct. - */ -#define llist_for_each_entry_continue(pos, head, member) \ - for (pos = llist_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = llist_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -/** - * llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your llist. - * @member: the name of the llist_struct within the struct. - */ -#define llist_for_each_entry_safe(pos, n, head, member) \ - for (pos = llist_entry((head)->next, typeof(*pos), member), \ - n = llist_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = llist_entry(n->member.next, typeof(*n), member)) - -/** - * llist_for_each_rcu - iterate over an rcu-protected llist - * @pos: the &struct llist_head to use as a loop counter. - * @head: the head for your llist. - */ -#define llist_for_each_rcu(pos, head) \ - for (pos = (head)->next, prefetch(pos->next); pos != (head); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) - -#define __llist_for_each_rcu(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next, ({ smp_read_barrier_depends(); 0;})) - -/** - * llist_for_each_safe_rcu - iterate over an rcu-protected llist safe - * against removal of llist entry - * @pos: the &struct llist_head to use as a loop counter. - * @n: another &struct llist_head to use as temporary storage - * @head: the head for your llist. - */ -#define llist_for_each_safe_rcu(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) - -/** - * llist_for_each_entry_rcu - iterate over rcu llist of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your llist. - * @member: the name of the llist_struct within the struct. - */ -#define llist_for_each_entry_rcu(pos, head, member) \ - for (pos = llist_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = llist_entry(pos->member.next, typeof(*pos), member), \ - ({ smp_read_barrier_depends(); 0;}), \ - prefetch(pos->member.next)) - - -/** - * llist_for_each_continue_rcu - iterate over an rcu-protected llist - * continuing after existing point. - * @pos: the &struct llist_head to use as a loop counter. - * @head: the head for your llist. - */ -#define llist_for_each_continue_rcu(pos, head) \ - for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ - (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) - - -#endif diff --git a/include/osmocore/logging.h b/include/osmocore/logging.h deleted file mode 100644 index fd458440..00000000 --- a/include/osmocore/logging.h +++ /dev/null @@ -1,154 +0,0 @@ -#ifndef _OSMOCORE_LOGGING_H -#define _OSMOCORE_LOGGING_H - -#include -#include -#include - -#define LOG_MAX_CATEGORY 32 -#define LOG_MAX_CTX 8 -#define LOG_MAX_FILTERS 8 - -#define DEBUG - -#ifdef DEBUG -#define DEBUGP(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 0, fmt, ## args) -#define DEBUGPC(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 1, fmt, ## args) -#else -#define DEBUGP(xss, fmt, args...) -#define DEBUGPC(ss, fmt, args...) -#endif - - -void logp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); - -/* new logging interface */ -#define LOGP(ss, level, fmt, args...) \ - logp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) -#define LOGPC(ss, level, fmt, args...) \ - logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) - -/* different levels */ -#define LOGL_DEBUG 1 /* debugging information */ -#define LOGL_INFO 3 -#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ -#define LOGL_ERROR 7 /* error condition, requires user action */ -#define LOGL_FATAL 8 /* fatal, program aborted */ - -#define LOG_FILTER_ALL 0x0001 - -struct log_category { - uint8_t loglevel; - uint8_t enabled; -}; - -struct log_info_cat { - const char *name; - const char *color; - const char *description; - uint8_t loglevel; - uint8_t enabled; -}; - -/* log context information, passed to filter */ -struct log_context { - void *ctx[LOG_MAX_CTX+1]; -}; - -struct log_target; - -typedef int log_filter(const struct log_context *ctx, - struct log_target *target); - -struct log_info { - /* filter callback function */ - log_filter *filter_fn; - - /* per-category information */ - const struct log_info_cat *cat; - unsigned int num_cat; -}; - -enum log_target_type { - LOG_TGT_TYPE_VTY, - LOG_TGT_TYPE_SYSLOG, - LOG_TGT_TYPE_FILE, - LOG_TGT_TYPE_STDERR, -}; - -struct log_target { - struct llist_head entry; - - int filter_map; - void *filter_data[LOG_MAX_FILTERS+1]; - - struct log_category categories[LOG_MAX_CATEGORY+1]; - uint8_t loglevel; - int use_color:1; - int print_timestamp:1; - - enum log_target_type type; - - union { - struct { - FILE *out; - const char *fname; - } tgt_file; - - struct { - int priority; - int facility; - } tgt_syslog; - - struct { - void *vty; - } tgt_vty; - }; - - void (*output) (struct log_target *target, unsigned int level, - const char *string); -}; - -/* use the above macros */ -void logp2(unsigned int subsys, unsigned int level, char *file, - int line, int cont, const char *format, ...) - __attribute__ ((format (printf, 6, 7))); -void log_init(const struct log_info *cat); - -/* context management */ -void log_reset_context(void); -int log_set_context(uint8_t ctx, void *value); - -/* filter on the targets */ -void log_set_all_filter(struct log_target *target, int); - -void log_set_use_color(struct log_target *target, int); -void log_set_print_timestamp(struct log_target *target, int); -void log_set_log_level(struct log_target *target, int log_level); -void log_parse_category_mask(struct log_target *target, const char* mask); -int log_parse_level(const char *lvl); -const char *log_level_str(unsigned int lvl); -int log_parse_category(const char *category); -void log_set_category_filter(struct log_target *target, int category, - int enable, int level); - -/* management of the targets */ -struct log_target *log_target_create(void); -void log_target_destroy(struct log_target *target); -struct log_target *log_target_create_stderr(void); -struct log_target *log_target_create_file(const char *fname); -struct log_target *log_target_create_syslog(const char *ident, int option, - int facility); -int log_target_file_reopen(struct log_target *tgt); - -void log_add_target(struct log_target *target); -void log_del_target(struct log_target *target); - -/* Generate command string for VTY use */ -const char *log_vty_command_string(const struct log_info *info); -const char *log_vty_command_description(const struct log_info *info); - -struct log_target *log_target_find(int type, const char *fname); -extern struct llist_head osmo_log_target_list; - -#endif /* _OSMOCORE_LOGGING_H */ diff --git a/include/osmocore/mncc.h b/include/osmocore/mncc.h deleted file mode 100644 index a094bb9b..00000000 --- a/include/osmocore/mncc.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _OSMOCORE_MNCC_H -#define _OSMOCORE_MNCC_H - -#define GSM_MAX_FACILITY 128 -#define GSM_MAX_SSVERSION 128 -#define GSM_MAX_USERUSER 128 - -/* Expanded fields from GSM TS 04.08, Table 10.5.102 */ -struct gsm_mncc_bearer_cap { - int transfer; /* Information Transfer Capability */ - int mode; /* Transfer Mode */ - int coding; /* Coding Standard */ - int radio; /* Radio Channel Requirement */ - int speech_ctm; /* CTM text telephony indication */ - int speech_ver[8]; /* Speech version indication */ -}; - -struct gsm_mncc_number { - int type; - int plan; - int present; - int screen; - char number[33]; -}; - -struct gsm_mncc_cause { - int location; - int coding; - int rec; - int rec_val; - int value; - int diag_len; - char diag[32]; -}; - -struct gsm_mncc_useruser { - int proto; - char info[GSM_MAX_USERUSER + 1]; /* + termination char */ -}; - -struct gsm_mncc_progress { - int coding; - int location; - int descr; -}; - -struct gsm_mncc_facility { - int len; - char info[GSM_MAX_FACILITY]; -}; - -struct gsm_mncc_ssversion { - int len; - char info[GSM_MAX_SSVERSION]; -}; - -struct gsm_mncc_cccap { - int dtmf; - int pcp; -}; - -enum { - GSM_MNCC_BCAP_SPEECH = 0, - GSM_MNCC_BCAP_UNR_DIG = 1, - GSM_MNCC_BCAP_AUDIO = 2, - GSM_MNCC_BCAP_FAX_G3 = 3, - GSM_MNCC_BCAP_OTHER_ITC = 5, - GSM_MNCC_BCAP_RESERVED = 7, -}; - -#endif diff --git a/include/osmocore/msgb.h b/include/osmocore/msgb.h deleted file mode 100644 index c4f44305..00000000 --- a/include/osmocore/msgb.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef _MSGB_H -#define _MSGB_H - -/* (C) 2008 by Harald Welte - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include "linuxlist.h" -#include "utils.h" - -#define MSGB_DEBUG - -struct msgb { - struct llist_head list; - - /* Part of which TRX logical channel we were received / transmitted */ - /* FIXME: move them into the control buffer */ - struct gsm_bts_trx *trx; - struct gsm_lchan *lchan; - - /* the Layer1 header (if any) */ - unsigned char *l1h; - /* the A-bis layer 2 header: OML, RSL(RLL), NS */ - unsigned char *l2h; - /* the layer 3 header. For OML: FOM; RSL: 04.08; GPRS: BSSGP */ - unsigned char *l3h; - /* the layer 4 header */ - unsigned char *l4h; - - /* the 'control buffer', large enough to contain 5 pointers */ - unsigned long cb[5]; - - uint16_t data_len; - uint16_t len; - - unsigned char *head; - unsigned char *tail; - unsigned char *data; - unsigned char _data[0]; -}; - -extern struct msgb *msgb_alloc(uint16_t size, const char *name); -extern void msgb_free(struct msgb *m); -extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg); -extern struct msgb *msgb_dequeue(struct llist_head *queue); -extern void msgb_reset(struct msgb *m); - -#ifdef MSGB_DEBUG -#include -#define MSGB_ABORT(msg, fmt, args ...) do { \ - osmo_panic("msgb(%p): " fmt, msg, ## args); \ - } while(0) -#else -#define MSGB_ABORT(msg, fmt, args ...) -#endif - -#define msgb_l1(m) ((void *)(m->l1h)) -#define msgb_l2(m) ((void *)(m->l2h)) -#define msgb_l3(m) ((void *)(m->l3h)) -#define msgb_sms(m) ((void *)(m->l4h)) - -static inline unsigned int msgb_l1len(const struct msgb *msgb) -{ - return msgb->tail - (uint8_t *)msgb_l1(msgb); -} - -static inline unsigned int msgb_l2len(const struct msgb *msgb) -{ - return msgb->tail - (uint8_t *)msgb_l2(msgb); -} - -static inline unsigned int msgb_l3len(const struct msgb *msgb) -{ - return msgb->tail - (uint8_t *)msgb_l3(msgb); -} - -static inline unsigned int msgb_headlen(const struct msgb *msgb) -{ - return msgb->len - msgb->data_len; -} - -static inline int msgb_tailroom(const struct msgb *msgb) -{ - return (msgb->head + msgb->data_len) - msgb->tail; -} - -static inline int msgb_headroom(const struct msgb *msgb) -{ - return (msgb->data - msgb->head); -} - -static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len) -{ - unsigned char *tmp = msgb->tail; - if (msgb_tailroom(msgb) < (int) len) - MSGB_ABORT(msgb, "Not enough tailroom msgb_push (%u < %u)\n", - msgb_tailroom(msgb), len); - msgb->tail += len; - msgb->len += len; - return tmp; -} -static inline void msgb_put_u8(struct msgb *msgb, uint8_t word) -{ - uint8_t *space = msgb_put(msgb, 1); - space[0] = word & 0xFF; -} -static inline void msgb_put_u16(struct msgb *msgb, uint16_t word) -{ - uint8_t *space = msgb_put(msgb, 2); - space[0] = word >> 8 & 0xFF; - space[1] = word & 0xFF; -} -static inline void msgb_put_u32(struct msgb *msgb, uint32_t word) -{ - uint8_t *space = msgb_put(msgb, 4); - space[0] = word >> 24 & 0xFF; - space[1] = word >> 16 & 0xFF; - space[2] = word >> 8 & 0xFF; - space[3] = word & 0xFF; -} -static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len) -{ - unsigned char *tmp = msgb->data; - msgb->data += len; - msgb->len -= len; - return tmp; -} -static inline uint8_t msgb_get_u8(struct msgb *msgb) -{ - uint8_t *space = msgb_get(msgb, 1); - return space[0]; -} -static inline uint16_t msgb_get_u16(struct msgb *msgb) -{ - uint8_t *space = msgb_get(msgb, 2); - return space[0] << 8 | space[1]; -} -static inline uint32_t msgb_get_u32(struct msgb *msgb) -{ - uint8_t *space = msgb_get(msgb, 4); - return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3]; -} -static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len) -{ - if (msgb_headroom(msgb) < (int) len) - MSGB_ABORT(msgb, "Not enough headroom msgb_push (%u < %u)\n", - msgb_headroom(msgb), len); - msgb->data -= len; - msgb->len += len; - return msgb->data; -} -static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len) -{ - msgb->len -= len; - return msgb->data += len; -} - -/* increase the headroom of an empty msgb, reducing the tailroom */ -static inline void msgb_reserve(struct msgb *msg, int len) -{ - msg->data += len; - msg->tail += len; -} - -static inline struct msgb *msgb_alloc_headroom(int size, int headroom, - const char *name) -{ - static_assert(size > headroom, headroom_bigger); - - struct msgb *msg = msgb_alloc(size, name); - if (msg) - msgb_reserve(msg, headroom); - return msg; -} - -/* non inline functions to ease binding */ -uint8_t *msgb_data(const struct msgb *msg); -uint16_t msgb_length(const struct msgb *msg); - - -#endif /* _MSGB_H */ diff --git a/include/osmocore/msgfile.h b/include/osmocore/msgfile.h deleted file mode 100644 index 92caa9fc..00000000 --- a/include/osmocore/msgfile.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * (C) 2010 by Holger Hans Peter Freyther - * (C) 2010 by On-Waves - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef MSG_FILE_H -#define MSG_FILE_H - -#include "linuxlist.h" - -/** - * One message in the list. - */ -struct msg_entry { - struct llist_head list; - - /* number for everyone to use */ - int nr; - - /* data from the file */ - char *mcc; - char *mnc; - char *option; - char *text; -}; - -struct msg_entries { - struct llist_head entry; -}; - -struct msg_entries *msg_entry_parse(void *ctx, const char *filename); - -#endif diff --git a/include/osmocore/panic.h b/include/osmocore/panic.h deleted file mode 100644 index c5a83778..00000000 --- a/include/osmocore/panic.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef OSMOCORE_PANIC_H -#define OSMOCORE_PANIC_H - -#include - -typedef void (*osmo_panic_handler_t)(const char *fmt, va_list args); - -void osmo_panic(const char *fmt, ...); -void osmo_set_panic_handler(osmo_panic_handler_t h); - -#endif diff --git a/include/osmocore/plugin.h b/include/osmocore/plugin.h deleted file mode 100644 index 98f9b56d..00000000 --- a/include/osmocore/plugin.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _OSMO_PLUGIN_H -#define _OSMO_PLUGIN_H - -int plugin_load_all(const char *directory); - -#endif diff --git a/include/osmocore/process.h b/include/osmocore/process.h deleted file mode 100644 index 2d663828..00000000 --- a/include/osmocore/process.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _OSMO_PROCESS_H -#define _OSMO_PROCESS_H - -int osmo_daemonize(void); - -#endif diff --git a/include/osmocore/protocol/Makefile.am b/include/osmocore/protocol/Makefile.am deleted file mode 100644 index 03a4849d..00000000 --- a/include/osmocore/protocol/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -osmocore_proto_HEADERS = gsm_03_41.h \ - gsm_04_08.h gsm_04_11.h gsm_04_12.h gsm_04_80.h \ - gsm_08_08.h gsm_08_58.h \ - gsm_12_21.h - -osmocore_protodir = $(includedir)/osmocore/protocol diff --git a/include/osmocore/protocol/gsm_03_41.h b/include/osmocore/protocol/gsm_03_41.h deleted file mode 100644 index 54365cbc..00000000 --- a/include/osmocore/protocol/gsm_03_41.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef PROTO_GSM_03_41_H -#define PROTO_GSM_03_41_H - -#include - -/* GSM TS 03.41 definitions also TS 23.041*/ - -/* Chapter 9.3.2 */ -struct gsm341_ms_message { - struct { - uint8_t code_hi:6; - uint8_t gs:2; - uint8_t update:4; - uint8_t code_lo:4; - } serial; - uint16_t msg_id; - struct { - uint8_t language:4; - uint8_t group:4; - } dcs; - struct { - uint8_t total:4; - uint8_t current:4; - } page; - uint8_t data[0]; -} __attribute__((packed)); - -/* Chapter 9.4.1.3 */ -struct gsm341_etws_message { - struct { - uint8_t code_hi:4; - uint8_t popup:1; - uint8_t alert:1; - uint8_t gs:2; - uint8_t update:4; - uint8_t code_lo:4; - } serial; - uint16_t msg_id; - uint16_t warning_type; - uint8_t data[0]; -} __attribute__((packed)); - -#define GSM341_MSG_CODE(ms) ((ms)->serial.code_lo | ((ms)->serial.code_hi << 4)) - -/* Section 9.3.2.1 - Geographical Scope */ -#define GSM341_GS_CELL_WIDE_IMMED 0 -#define GSM341_GS_PLMN_WIDE 1 -#define GSM341_GS_LA_WIDE 2 -#define GSM341_GS_CELL_WIDE 3 - -#endif /* PROTO_GSM_03_41_H */ diff --git a/include/osmocore/protocol/gsm_04_08.h b/include/osmocore/protocol/gsm_04_08.h deleted file mode 100644 index 3ad7dfdc..00000000 --- a/include/osmocore/protocol/gsm_04_08.h +++ /dev/null @@ -1,1262 +0,0 @@ -#ifndef PROTO_GSM_04_08_H -#define PROTO_GSM_04_08_H - -#include - -/* GSM TS 04.08 definitions */ -struct gsm_lchan; - -/* Chapter 10.5.1.5 */ -struct gsm48_classmark1 { - uint8_t pwr_lev:3, - a5_1:1, - es_ind:1, - rev_lev:2, - spare:1; -} __attribute__ ((packed)); - -/* Chapter 10.5.1.6 */ -struct gsm48_classmark2 { - uint8_t pwr_lev:3, - a5_1:1, - es_ind:1, - rev_lev:2, - spare:1; - uint8_t fc:1, - vgcs:1, - vbs:1, - sm_cap:1, - ss_scr:2, - ps_cap:1, - spare2:1; - uint8_t a5_2:1, - a5_3:1, - cmsp:1, - solsa:1, - spare3:1, - lcsva_cap:1, - spare4:1, - cm3:1; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.1b.3 */ -struct gsm48_range_1024 { - uint8_t w1_hi:2, - f0:1, - form_id:5; - uint8_t w1_lo; - uint8_t w2_hi; - uint8_t w3_hi:7, - w2_lo:1; - uint8_t w4_hi:6, - w3_lo:2; - uint8_t w5_hi:6, - w4_lo:2; - uint8_t w6_hi:6, - w5_lo:2; - uint8_t w7_hi:6, - w6_lo:2; - uint8_t w8_hi:6, - w7_lo:2; - uint8_t w9:7, - w8_lo:1; - uint8_t w11_hi:1, - w10:7; - uint8_t w12_hi:2, - w11_lo:6; - uint8_t w13_hi:3, - w12_lo:5; - uint8_t w14_hi:4, - w13_lo:4; - uint8_t w15_hi:5, - w14_lo:3; - uint8_t w16:6, - w15_lo:2; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.1b.4 */ -struct gsm48_range_512 { - uint8_t orig_arfcn_hi:1, - form_id:7; - uint8_t orig_arfcn_mid; - uint8_t w1_hi:7, - orig_arfcn_lo:1; - uint8_t w2_hi:6, - w1_lo:2; - uint8_t w3_hi:6, - w2_lo:2; - uint8_t w4_hi:6, - w3_lo:2; - uint8_t w5:7, - w4_lo:1; - uint8_t w7_hi:1, - w6:7; - uint8_t w8_hi:2, - w7_lo:6; - uint8_t w9_hi:4, - w8_lo:4; - uint8_t w10:6, - w9_lo:2; - uint8_t w12_hi:2, - w11:6; - uint8_t w13_hi:4, - w12_lo:4; - uint8_t w14:6, - w13_lo:2; - uint8_t w16_hi:2, - w15:6; - uint8_t w17:5, - w16_lo:3; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.1b.5 */ -struct gsm48_range_256 { - uint8_t orig_arfcn_hi:1, - form_id:7; - uint8_t orig_arfcn_mid; - uint8_t w1_hi:7, - orig_arfcn_lo:1; - uint8_t w2:7, - w1_lo:1; - uint8_t w4_hi:1, - w3:7; - uint8_t w5_hi:3, - w4_lo:5; - uint8_t w6_hi:5, - w5_lo:3; - uint8_t w8_hi:1, - w7:6, - w6_lo:1; - uint8_t w9_hi:4, - w8_lo:4; - uint8_t w11_hi:2, - w10:5, - w9_lo:1; - uint8_t w12:5, - w11_lo:3; - uint8_t w14_hi:3, - w13:5; - uint8_t w16_hi:1, - w15:5, - w14_lo:2; - uint8_t w18_hi:1, - w17:4, - w16_lo:3; - uint8_t w20_hi:1, - w19:4, - w18_lo:3; - uint8_t spare:1, - w21:4, - w20_lo:3; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.1b.6 */ -struct gsm48_range_128 { - uint8_t orig_arfcn_hi:1, - form_id:7; - uint8_t orig_arfcn_mid; - uint8_t w1:7, - orig_arfcn_lo:1; - uint8_t w3_hi:2, - w2:6; - uint8_t w4_hi:4, - w3_lo:4; - uint8_t w6_hi:2, - w5:5, - w4_lo:1; - uint8_t w7:5, - w6_lo:3; - uint8_t w9:4, - w8:4; - uint8_t w11:4, - w10:4; - uint8_t w13:4, - w12:4; - uint8_t w15:4, - w14:4; - uint8_t w18_hi:2, - w17:3, - w16:3; - uint8_t w21_hi:1, - w20:3, - w19:3, - w18_lo:1; - uint8_t w23:3, - w22:3, - w21_lo:2; - uint8_t w26_hi:2, - w25:3, - w24:3; - uint8_t spare:1, - w28:3, - w27:3, - w26_lo:1; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.1b.7 */ -struct gsm48_var_bit { - uint8_t orig_arfcn_hi:1, - form_id:7; - uint8_t orig_arfcn_mid; - uint8_t rrfcn1_7:7, - orig_arfcn_lo:1; - uint8_t rrfcn8_111[13]; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.5 */ -struct gsm48_chan_desc { - uint8_t chan_nr; - union { - struct { - uint8_t maio_high:4, - h:1, - tsc:3; - uint8_t hsn:6, - maio_low:2; - } h1; - struct { - uint8_t arfcn_high:2, - spare:2, - h:1, - tsc:3; - uint8_t arfcn_low; - } h0; - }; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.20 */ -struct gsm48_meas_res { - uint8_t rxlev_full:6, - dtx_used:1, - ba_used:1; - uint8_t rxlev_sub:6, - meas_valid:1, - spare:1; - uint8_t no_nc_n_hi:1, - rxqual_sub:3, - rxqual_full:3, - spare2:1; - uint8_t rxlev_nc1:6, - no_nc_n_lo:2; - uint8_t bsic_nc1_hi:3, - bcch_f_nc1:5; - uint8_t rxlev_nc2_hi:5, - bsic_nc1_lo:3; - uint8_t bsic_nc2_hi:2, - bcch_f_nc2:5, - rxlev_nc2_lo:1; - uint8_t rxlev_nc3_hi:4, - bsic_nc2_lo:4; - uint8_t bsic_nc3_hi:1, - bcch_f_nc3:5, - rxlev_nc3_lo:2; - uint8_t rxlev_nc4_hi:3, - bsic_nc3_lo:5; - uint8_t bcch_f_nc4:5, - rxlev_nc4_lo:3; - uint8_t rxlev_nc5_hi:2, - bsic_nc4:6; - uint8_t bcch_f_nc5_hi:4, - rxlev_nc5_lo:4; - uint8_t rxlev_nc6_hi:1, - bsic_nc5:6, - bcch_f_nc5_lo:1; - uint8_t bcch_f_nc6_hi:3, - rxlev_nc6_lo:5; - uint8_t bsic_nc6:6, - bcch_f_nc6_lo:2; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.21aa */ -struct gsm48_multi_rate_conf { - uint8_t smod : 2, - spare: 1, - icmi : 1, - nscb : 1, - ver : 3; - uint8_t m4_75 : 1, - m5_15 : 1, - m5_90 : 1, - m6_70 : 1, - m7_40 : 1, - m7_95 : 1, - m10_2 : 1, - m12_2 : 1; -} __attribute__((packed)); - -/* Chapter 10.5.2.28(a) */ -struct gsm48_power_cmd { - uint8_t power_level:5, - spare:2, - atc:1; -} __attribute__((packed)); - -/* Chapter 10.5.2.29 */ -struct gsm48_rach_control { - uint8_t re :1, - cell_bar :1, - tx_integer :4, - max_trans :2; - uint8_t t2; - uint8_t t3; -} __attribute__ ((packed)); - - -/* Chapter 10.5.2.30 */ -struct gsm48_req_ref { - uint8_t ra; - uint8_t t3_high:3, - t1:5; - uint8_t t2:5, - t3_low:3; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.38 */ -struct gsm48_start_time { - uint8_t t3_high:3, - t1:5; - uint8_t t2:5, - t3_low:3; -} __attribute__ ((packed)); - -/* Chapter 10.5.2.39 */ -struct gsm48_sync_ind { - uint8_t si:2, - rot:1, - nci:1, - sync_ie:4; -} __attribute__((packed)); - -/* - * Chapter 9.1.5/9.1.6 - * - * For 9.1.6 the chan_desc has the meaning of 10.5.2.5a - */ -struct gsm48_chan_mode_modify { - struct gsm48_chan_desc chan_desc; - uint8_t mode; -} __attribute__ ((packed)); - -enum gsm48_chan_mode { - GSM48_CMODE_SIGN = 0x00, - GSM48_CMODE_SPEECH_V1 = 0x01, - GSM48_CMODE_SPEECH_EFR = 0x21, - GSM48_CMODE_SPEECH_AMR = 0x41, - GSM48_CMODE_DATA_14k5 = 0x0f, - GSM48_CMODE_DATA_12k0 = 0x03, - GSM48_CMODE_DATA_6k0 = 0x0b, - GSM48_CMODE_DATA_3k6 = 0x23, -}; - -/* Chapter 9.1.2 */ -struct gsm48_ass_cmd { - /* Semantic is from 10.5.2.5a */ - struct gsm48_chan_desc chan_desc; - uint8_t power_command; - uint8_t data[0]; -} __attribute__((packed)); - -/* Chapter 9.1.13 */ -struct gsm48_frq_redef { - /* Semantic is from 10.5.2.5a */ - struct gsm48_chan_desc chan_desc; - uint8_t mob_alloc_len; - uint8_t mob_alloc[0]; -} __attribute__((packed)); - -/* Chapter 10.5.2.2 */ -struct gsm48_cell_desc { - uint8_t bcc:3, - ncc:3, - arfcn_hi:2; - uint8_t arfcn_lo; -} __attribute__((packed)); - -/* Chapter 9.1.15 */ -struct gsm48_ho_cmd { - struct gsm48_cell_desc cell_desc; - struct gsm48_chan_desc chan_desc; - uint8_t ho_ref; - uint8_t power_command; - uint8_t data[0]; -} __attribute__((packed)); - -/* Chapter 9.1.18 */ -struct gsm48_imm_ass { - uint8_t l2_plen; - uint8_t proto_discr; - uint8_t msg_type; - uint8_t page_mode; - struct gsm48_chan_desc chan_desc; - struct gsm48_req_ref req_ref; - uint8_t timing_advance; - uint8_t mob_alloc_len; - uint8_t mob_alloc[0]; -} __attribute__ ((packed)); - -/* Chapter 9.1.25 */ -struct gsm48_pag_resp { - uint8_t spare:4, - key_seq:4; - uint32_t classmark2; - uint8_t mi_len; - uint8_t mi[0]; -} __attribute__ ((packed)); - -/* Chapter 10.5.1.3 */ -struct gsm48_loc_area_id { - uint8_t digits[3]; /* BCD! */ - uint16_t lac; -} __attribute__ ((packed)); - -/* Section 9.2.2 */ -struct gsm48_auth_req { - uint8_t key_seq:4, - spare:4; - uint8_t rand[16]; -} __attribute__ ((packed)); - -/* Section 9.2.3 */ -struct gsm48_auth_resp { - uint8_t sres[4]; -} __attribute__ ((packed)); - -/* Section 9.2.15 */ -struct gsm48_loc_upd_req { - uint8_t type:4, - key_seq:4; - struct gsm48_loc_area_id lai; - struct gsm48_classmark1 classmark1; - uint8_t mi_len; - uint8_t mi[0]; -} __attribute__ ((packed)); - -/* Section 10.1 */ -struct gsm48_hdr { - uint8_t proto_discr; - uint8_t msg_type; - uint8_t data[0]; -} __attribute__ ((packed)); - -/* Section 9.1.3x System information Type header */ -struct gsm48_system_information_type_header { - uint8_t l2_plen; - uint8_t rr_protocol_discriminator :4, - skip_indicator:4; - uint8_t system_information; -} __attribute__ ((packed)); - -/* Section 10.5.2.4 Cell Selection Parameters */ -struct gsm48_cell_sel_par { - uint8_t ms_txpwr_max_ccch:5, /* GSM 05.08 MS-TXPWR-MAX-CCCH */ - cell_resel_hyst:3; /* GSM 05.08 CELL-RESELECT-HYSTERESIS */ - uint8_t rxlev_acc_min:6, /* GSM 05.08 RXLEV-ACCESS-MIN */ - neci:1, - acs:1; -} __attribute__ ((packed)); - -/* Section 10.5.2.11 Control Channel Description , Figure 10.5.33 */ -struct gsm48_control_channel_descr { - uint8_t ccch_conf :3, - bs_ag_blks_res :3, - att :1, - spare1 :1; - uint8_t bs_pa_mfrms : 3, - spare2 :5; - uint8_t t3212; -} __attribute__ ((packed)); - -struct gsm48_cell_options { - uint8_t radio_link_timeout:4, - dtx:2, - pwrc:1, - spare:1; -} __attribute__ ((packed)); - -/* Section 9.2.9 CM service request */ -struct gsm48_service_request { - uint8_t cm_service_type : 4, - cipher_key_seq : 4; - /* length + 3 bytes */ - uint32_t classmark; - uint8_t mi_len; - uint8_t mi[0]; - /* optional priority level */ -} __attribute__ ((packed)); - -/* Section 9.1.31 System information Type 1 */ -struct gsm48_system_information_type_1 { - struct gsm48_system_information_type_header header; - uint8_t cell_channel_description[16]; - struct gsm48_rach_control rach_control; - uint8_t rest_octets[0]; /* NCH position on the CCCH */ -} __attribute__ ((packed)); - -/* Section 9.1.32 System information Type 2 */ -struct gsm48_system_information_type_2 { - struct gsm48_system_information_type_header header; - uint8_t bcch_frequency_list[16]; - uint8_t ncc_permitted; - struct gsm48_rach_control rach_control; -} __attribute__ ((packed)); - -/* Section 9.1.33 System information Type 2bis */ -struct gsm48_system_information_type_2bis { - struct gsm48_system_information_type_header header; - uint8_t bcch_frequency_list[16]; - struct gsm48_rach_control rach_control; - uint8_t rest_octets[0]; -} __attribute__ ((packed)); - -/* Section 9.1.34 System information Type 2ter */ -struct gsm48_system_information_type_2ter { - struct gsm48_system_information_type_header header; - uint8_t ext_bcch_frequency_list[16]; - uint8_t rest_octets[0]; -} __attribute__ ((packed)); - -/* Section 9.1.35 System information Type 3 */ -struct gsm48_system_information_type_3 { - struct gsm48_system_information_type_header header; - uint16_t cell_identity; - struct gsm48_loc_area_id lai; - struct gsm48_control_channel_descr control_channel_desc; - struct gsm48_cell_options cell_options; - struct gsm48_cell_sel_par cell_sel_par; - struct gsm48_rach_control rach_control; - uint8_t rest_octets[0]; -} __attribute__ ((packed)); - -/* Section 9.1.36 System information Type 4 */ -struct gsm48_system_information_type_4 { - struct gsm48_system_information_type_header header; - struct gsm48_loc_area_id lai; - struct gsm48_cell_sel_par cell_sel_par; - struct gsm48_rach_control rach_control; - /* optional CBCH conditional CBCH... followed by - mandantory SI 4 Reset Octets - */ - uint8_t data[0]; -} __attribute__ ((packed)); - -/* Section 9.1.37 System information Type 5 */ -struct gsm48_system_information_type_5 { - uint8_t rr_protocol_discriminator :4, - skip_indicator:4; - uint8_t system_information; - uint8_t bcch_frequency_list[16]; -} __attribute__ ((packed)); - -/* Section 9.1.38 System information Type 5bis */ -struct gsm48_system_information_type_5bis { - uint8_t rr_protocol_discriminator :4, - skip_indicator:4; - uint8_t system_information; - uint8_t bcch_frequency_list[16]; -} __attribute__ ((packed)); - -/* Section 9.1.39 System information Type 5ter */ -struct gsm48_system_information_type_5ter { - uint8_t rr_protocol_discriminator :4, - skip_indicator:4; - uint8_t system_information; - uint8_t bcch_frequency_list[16]; -} __attribute__ ((packed)); - -/* Section 9.1.40 System information Type 6 */ -struct gsm48_system_information_type_6 { - uint8_t rr_protocol_discriminator :4, - skip_indicator:4; - uint8_t system_information; - uint16_t cell_identity; - struct gsm48_loc_area_id lai; - struct gsm48_cell_options cell_options; - uint8_t ncc_permitted; - uint8_t rest_octets[0]; -} __attribute__ ((packed)); - -/* Section 9.1.43a System Information type 13 */ -struct gsm48_system_information_type_13 { - struct gsm48_system_information_type_header header; - uint8_t rest_octets[0]; -} __attribute__ ((packed)); - -/* Section 9.2.12 IMSI Detach Indication */ -struct gsm48_imsi_detach_ind { - struct gsm48_classmark1 classmark1; - uint8_t mi_len; - uint8_t mi[0]; -} __attribute__ ((packed)); - -/* Section 9.1.1 */ -struct gsm48_add_ass { - /* Semantic is from 10.5.2.5 */ - struct gsm48_chan_desc chan_desc; - uint8_t data[0]; -} __attribute__((packed)); - -/* Section 9.1.3 */ -struct gsm48_ass_cpl { - uint8_t rr_cause; -} __attribute__((packed)); - -/* Section 9.1.4 */ -struct gsm48_ass_fail { - uint8_t rr_cause; -} __attribute__((packed)); - -/* Section 9.1.3 */ -struct gsm48_ho_cpl { - uint8_t rr_cause; - uint8_t data[0]; -} __attribute__((packed)); - -/* Section 9.1.4 */ -struct gsm48_ho_fail { - uint8_t rr_cause; -} __attribute__((packed)); - -/* Section 9.1.7 */ -struct gsm48_chan_rel { - uint8_t rr_cause; - uint8_t data[0]; -} __attribute__((packed)); - -/* Section 9.1.9 */ -struct gsm48_cip_mode_cmd { - uint8_t sc:1, - alg_id:3, - cr:1, - spare:3; -} __attribute__((packed)); - -/* Section 9.1.11 */ -struct gsm48_cm_change { - uint8_t cm2_len; - struct gsm48_classmark2 cm2; - uint8_t data[0]; -} __attribute__((packed)); - -/* Section 9.1.19 */ -struct gsm48_imm_ass_ext { - uint8_t l2_plen; - uint8_t proto_discr; - uint8_t msg_type; - uint8_t page_mode; - struct gsm48_chan_desc chan_desc1; - struct gsm48_req_ref req_ref1; - uint8_t timing_advance1; - struct gsm48_chan_desc chan_desc2; - struct gsm48_req_ref req_ref2; - uint8_t timing_advance2; - uint8_t mob_alloc_len; - uint8_t mob_alloc[0]; -} __attribute__ ((packed)); - -/* Section 9.1.20 */ -struct gsm48_imm_ass_rej { - uint8_t l2_plen; - uint8_t proto_discr; - uint8_t msg_type; - uint8_t page_mode; - struct gsm48_req_ref req_ref1; - uint8_t wait_ind1; - struct gsm48_req_ref req_ref2; - uint8_t wait_ind2; - struct gsm48_req_ref req_ref3; - uint8_t wait_ind3; - struct gsm48_req_ref req_ref4; - uint8_t wait_ind4; - uint8_t rest[0]; -} __attribute__ ((packed)); - -/* Section 9.1.22 */ -struct gsm48_paging1 { - uint8_t l2_plen; - uint8_t proto_discr; - uint8_t msg_type; - uint8_t pag_mode:2, - spare:2, - cneed1:2, - cneed2:2; - uint8_t data[0]; -} __attribute__((packed)); - -/* Section 9.1.23 */ -struct gsm48_paging2 { - uint8_t l2_plen; - uint8_t proto_discr; - uint8_t msg_type; - uint8_t pag_mode:2, - spare:2, - cneed1:2, - cneed2:2; - uint32_t tmsi1; - uint32_t tmsi2; - uint8_t data[0]; -} __attribute__((packed)); - -/* Section 9.1.24 */ -struct gsm48_paging3 { - uint8_t l2_plen; - uint8_t proto_discr; - uint8_t msg_type; - uint8_t pag_mode:2, - spare:2, - cneed1:2, - cneed2:2; - uint32_t tmsi1; - uint32_t tmsi2; - uint32_t tmsi3; - uint32_t tmsi4; - uint8_t cneed3:2, - cneed4:2, - spare2:4; - uint8_t rest[0]; -} __attribute__((packed)); - -/* Section 9.1.25 */ -struct gsm48_pag_rsp { - uint8_t key_seq:3, - spare:5; - uint8_t cm2_len; - struct gsm48_classmark2 cm2; - uint8_t data[0]; -} __attribute__((packed)); - -/* Section 9.1.29 */ -struct gsm48_rr_status { - uint8_t rr_cause; -} __attribute__((packed)); - -/* Section 10.2 + GSM 04.07 12.2.3.1.1 */ -#define GSM48_PDISC_GROUP_CC 0x00 -#define GSM48_PDISC_BCAST_CC 0x01 -#define GSM48_PDISC_PDSS1 0x02 -#define GSM48_PDISC_CC 0x03 -#define GSM48_PDISC_PDSS2 0x04 -#define GSM48_PDISC_MM 0x05 -#define GSM48_PDISC_RR 0x06 -#define GSM48_PDISC_MM_GPRS 0x08 -#define GSM48_PDISC_SMS 0x09 -#define GSM48_PDISC_SM_GPRS 0x0a -#define GSM48_PDISC_NC_SS 0x0b -#define GSM48_PDISC_LOC 0x0c -#define GSM48_PDISC_MASK 0x0f -#define GSM48_PDISC_USSD 0x11 - -/* Section 10.4 */ -#define GSM48_MT_RR_INIT_REQ 0x3c -#define GSM48_MT_RR_ADD_ASS 0x3b -#define GSM48_MT_RR_IMM_ASS 0x3f -#define GSM48_MT_RR_IMM_ASS_EXT 0x39 -#define GSM48_MT_RR_IMM_ASS_REJ 0x3a - -#define GSM48_MT_RR_CIPH_M_CMD 0x35 -#define GSM48_MT_RR_CIPH_M_COMPL 0x32 - -#define GSM48_MT_RR_CFG_CHG_CMD 0x30 -#define GSM48_MT_RR_CFG_CHG_ACK 0x31 -#define GSM48_MT_RR_CFG_CHG_REJ 0x33 - -#define GSM48_MT_RR_ASS_CMD 0x2e -#define GSM48_MT_RR_ASS_COMPL 0x29 -#define GSM48_MT_RR_ASS_FAIL 0x2f -#define GSM48_MT_RR_HANDO_CMD 0x2b -#define GSM48_MT_RR_HANDO_COMPL 0x2c -#define GSM48_MT_RR_HANDO_FAIL 0x28 -#define GSM48_MT_RR_HANDO_INFO 0x2d - -#define GSM48_MT_RR_CELL_CHG_ORDER 0x08 -#define GSM48_MT_RR_PDCH_ASS_CMD 0x23 - -#define GSM48_MT_RR_CHAN_REL 0x0d -#define GSM48_MT_RR_PART_REL 0x0a -#define GSM48_MT_RR_PART_REL_COMP 0x0f - -#define GSM48_MT_RR_PAG_REQ_1 0x21 -#define GSM48_MT_RR_PAG_REQ_2 0x22 -#define GSM48_MT_RR_PAG_REQ_3 0x24 -#define GSM48_MT_RR_PAG_RESP 0x27 -#define GSM48_MT_RR_NOTIF_NCH 0x20 -#define GSM48_MT_RR_NOTIF_FACCH 0x25 -#define GSM48_MT_RR_NOTIF_RESP 0x26 - -#define GSM48_MT_RR_SYSINFO_8 0x18 -#define GSM48_MT_RR_SYSINFO_1 0x19 -#define GSM48_MT_RR_SYSINFO_2 0x1a -#define GSM48_MT_RR_SYSINFO_3 0x1b -#define GSM48_MT_RR_SYSINFO_4 0x1c -#define GSM48_MT_RR_SYSINFO_5 0x1d -#define GSM48_MT_RR_SYSINFO_6 0x1e -#define GSM48_MT_RR_SYSINFO_7 0x1f - -#define GSM48_MT_RR_SYSINFO_2bis 0x02 -#define GSM48_MT_RR_SYSINFO_2ter 0x03 -#define GSM48_MT_RR_SYSINFO_5bis 0x05 -#define GSM48_MT_RR_SYSINFO_5ter 0x06 -#define GSM48_MT_RR_SYSINFO_9 0x04 -#define GSM48_MT_RR_SYSINFO_13 0x00 - -#define GSM48_MT_RR_SYSINFO_16 0x3d -#define GSM48_MT_RR_SYSINFO_17 0x3e - -#define GSM48_MT_RR_CHAN_MODE_MODIF 0x10 -#define GSM48_MT_RR_STATUS 0x12 -#define GSM48_MT_RR_CHAN_MODE_MODIF_ACK 0x17 -#define GSM48_MT_RR_FREQ_REDEF 0x14 -#define GSM48_MT_RR_MEAS_REP 0x15 -#define GSM48_MT_RR_CLSM_CHG 0x16 -#define GSM48_MT_RR_CLSM_ENQ 0x13 -#define GSM48_MT_RR_EXT_MEAS_REP 0x36 -#define GSM48_MT_RR_EXT_MEAS_REP_ORD 0x37 -#define GSM48_MT_RR_GPRS_SUSP_REQ 0x34 - -#define GSM48_MT_RR_VGCS_UPL_GRANT 0x08 -#define GSM48_MT_RR_UPLINK_RELEASE 0x0e -#define GSM48_MT_RR_UPLINK_FREE 0x0c -#define GSM48_MT_RR_UPLINK_BUSY 0x2a -#define GSM48_MT_RR_TALKER_IND 0x11 - -#define GSM48_MT_RR_APP_INFO 0x38 - -/* Table 10.2/3GPP TS 04.08 */ -#define GSM48_MT_MM_IMSI_DETACH_IND 0x01 -#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02 -#define GSM48_MT_MM_LOC_UPD_REJECT 0x04 -#define GSM48_MT_MM_LOC_UPD_REQUEST 0x08 - -#define GSM48_MT_MM_AUTH_REJ 0x11 -#define GSM48_MT_MM_AUTH_REQ 0x12 -#define GSM48_MT_MM_AUTH_RESP 0x14 -#define GSM48_MT_MM_ID_REQ 0x18 -#define GSM48_MT_MM_ID_RESP 0x19 -#define GSM48_MT_MM_TMSI_REALL_CMD 0x1a -#define GSM48_MT_MM_TMSI_REALL_COMPL 0x1b - -#define GSM48_MT_MM_CM_SERV_ACC 0x21 -#define GSM48_MT_MM_CM_SERV_REJ 0x22 -#define GSM48_MT_MM_CM_SERV_ABORT 0x23 -#define GSM48_MT_MM_CM_SERV_REQ 0x24 -#define GSM48_MT_MM_CM_SERV_PROMPT 0x25 -#define GSM48_MT_MM_CM_REEST_REQ 0x28 -#define GSM48_MT_MM_ABORT 0x29 - -#define GSM48_MT_MM_NULL 0x30 -#define GSM48_MT_MM_STATUS 0x31 -#define GSM48_MT_MM_INFO 0x32 - -/* Table 10.3/3GPP TS 04.08 */ -#define GSM48_MT_CC_ALERTING 0x01 -#define GSM48_MT_CC_CALL_CONF 0x08 -#define GSM48_MT_CC_CALL_PROC 0x02 -#define GSM48_MT_CC_CONNECT 0x07 -#define GSM48_MT_CC_CONNECT_ACK 0x0f -#define GSM48_MT_CC_EMERG_SETUP 0x0e -#define GSM48_MT_CC_PROGRESS 0x03 -#define GSM48_MT_CC_ESTAB 0x04 -#define GSM48_MT_CC_ESTAB_CONF 0x06 -#define GSM48_MT_CC_RECALL 0x0b -#define GSM48_MT_CC_START_CC 0x09 -#define GSM48_MT_CC_SETUP 0x05 - -#define GSM48_MT_CC_MODIFY 0x17 -#define GSM48_MT_CC_MODIFY_COMPL 0x1f -#define GSM48_MT_CC_MODIFY_REJECT 0x13 -#define GSM48_MT_CC_USER_INFO 0x10 -#define GSM48_MT_CC_HOLD 0x18 -#define GSM48_MT_CC_HOLD_ACK 0x19 -#define GSM48_MT_CC_HOLD_REJ 0x1a -#define GSM48_MT_CC_RETR 0x1c -#define GSM48_MT_CC_RETR_ACK 0x1d -#define GSM48_MT_CC_RETR_REJ 0x1e - -#define GSM48_MT_CC_DISCONNECT 0x25 -#define GSM48_MT_CC_RELEASE 0x2d -#define GSM48_MT_CC_RELEASE_COMPL 0x2a - -#define GSM48_MT_CC_CONG_CTRL 0x39 -#define GSM48_MT_CC_NOTIFY 0x3e -#define GSM48_MT_CC_STATUS 0x3d -#define GSM48_MT_CC_STATUS_ENQ 0x34 -#define GSM48_MT_CC_START_DTMF 0x35 -#define GSM48_MT_CC_STOP_DTMF 0x31 -#define GSM48_MT_CC_STOP_DTMF_ACK 0x32 -#define GSM48_MT_CC_START_DTMF_ACK 0x36 -#define GSM48_MT_CC_START_DTMF_REJ 0x37 -#define GSM48_MT_CC_FACILITY 0x3a - -/* FIXME: Table 10.4 / 10.4a (GPRS) */ - -/* Section 10.5.3.3 CM service type */ -#define GSM48_CMSERV_MO_CALL_PACKET 1 -#define GSM48_CMSERV_EMERGENCY 2 -#define GSM48_CMSERV_SMS 4 -#define GSM48_CMSERV_SUP_SERV 8 -#define GSM48_CMSERV_VGCS 9 -#define GSM48_CMSERV_VBS 10 -#define GSM48_CMSERV_LOC_SERV 11 - -/* Section 10.5.2.26, Table 10.5.64 */ -#define GSM48_PM_MASK 0x03 -#define GSM48_PM_NORMAL 0x00 -#define GSM48_PM_EXTENDED 0x01 -#define GSM48_PM_REORG 0x02 -#define GSM48_PM_SAME 0x03 - -/* Chapter 10.5.3.5 / Table 10.5.93 */ -#define GSM48_LUPD_NORMAL 0x0 -#define GSM48_LUPD_PERIODIC 0x1 -#define GSM48_LUPD_IMSI_ATT 0x2 -#define GSM48_LUPD_RESERVED 0x3 - -/* Table 10.5.4 */ -#define GSM_MI_TYPE_MASK 0x07 -#define GSM_MI_TYPE_NONE 0x00 -#define GSM_MI_TYPE_IMSI 0x01 -#define GSM_MI_TYPE_IMEI 0x02 -#define GSM_MI_TYPE_IMEISV 0x03 -#define GSM_MI_TYPE_TMSI 0x04 -#define GSM_MI_ODD 0x08 - -#define GSM48_IE_MOBILE_ID 0x17 /* 10.5.1.4 */ -#define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */ -#define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */ -#define GSM48_IE_UTC 0x46 /* 10.5.3.8 */ -#define GSM48_IE_NET_TIME_TZ 0x47 /* 10.5.3.9 */ -#define GSM48_IE_LSA_IDENT 0x48 /* 10.5.3.11 */ - -#define GSM48_IE_BEARER_CAP 0x04 /* 10.5.4.5 */ -#define GSM48_IE_CAUSE 0x08 /* 10.5.4.11 */ -#define GSM48_IE_CC_CAP 0x15 /* 10.5.4.5a */ -#define GSM48_IE_ALERT 0x19 /* 10.5.4.26 */ -#define GSM48_IE_FACILITY 0x1c /* 10.5.4.15 */ -#define GSM48_IE_PROGR_IND 0x1e /* 10.5.4.21 */ -#define GSM48_IE_AUX_STATUS 0x24 /* 10.5.4.4 */ -#define GSM48_IE_NOTIFY 0x27 /* 10.5.4.20 */ -#define GSM48_IE_KPD_FACILITY 0x2c /* 10.5.4.17 */ -#define GSM48_IE_SIGNAL 0x34 /* 10.5.4.23 */ -#define GSM48_IE_CONN_BCD 0x4c /* 10.5.4.13 */ -#define GSM48_IE_CONN_SUB 0x4d /* 10.5.4.14 */ -#define GSM48_IE_CALLING_BCD 0x5c /* 10.5.4.9 */ -#define GSM48_IE_CALLING_SUB 0x5d /* 10.5.4.10 */ -#define GSM48_IE_CALLED_BCD 0x5e /* 10.5.4.7 */ -#define GSM48_IE_CALLED_SUB 0x6d /* 10.5.4.8 */ -#define GSM48_IE_REDIR_BCD 0x74 /* 10.5.4.21a */ -#define GSM48_IE_REDIR_SUB 0x75 /* 10.5.4.21b */ -#define GSM48_IE_LOWL_COMPAT 0x7c /* 10.5.4.18 */ -#define GSM48_IE_HIGHL_COMPAT 0x7d /* 10.5.4.16 */ -#define GSM48_IE_USER_USER 0x7e /* 10.5.4.25 */ -#define GSM48_IE_SS_VERS 0x7f /* 10.5.4.24 */ -#define GSM48_IE_MORE_DATA 0xa0 /* 10.5.4.19 */ -#define GSM48_IE_CLIR_SUPP 0xa1 /* 10.5.4.11a */ -#define GSM48_IE_CLIR_INVOC 0xa2 /* 10.5.4.11b */ -#define GSM48_IE_REV_C_SETUP 0xa3 /* 10.5.4.22a */ -#define GSM48_IE_REPEAT_CIR 0xd1 /* 10.5.4.22 */ -#define GSM48_IE_REPEAT_SEQ 0xd3 /* 10.5.4.22 */ - -/* Section 10.5.4.11 / Table 10.5.122 */ -#define GSM48_CAUSE_CS_GSM 0x60 - -/* Section 9.1.2 / Table 9.3 */ -/* RR elements */ -#define GSM48_IE_VGCS_TARGET 0x01 -//#define GSM48_IE_VGCS_T_MODE_I 0x01 -#define GSM48_IE_FRQSHORT_AFTER 0x02 -#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */ -#define GSM48_IE_FREQ_L_AFTER 0x05 -#define GSM48_IE_MSLOT_DESC 0x10 -#define GSM48_IE_CHANMODE_2 0x11 -#define GSM48_IE_FRQSHORT_BEFORE 0x12 -//#define GSM48_IE_FRQSHORT_BEFOR 0x12 -#define GSM48_IE_CHANMODE_3 0x13 -#define GSM48_IE_CHANMODE_4 0x14 -#define GSM48_IE_CHANMODE_5 0x15 -#define GSM48_IE_CHANMODE_6 0x16 -#define GSM48_IE_CHANMODE_7 0x17 -#define GSM48_IE_CHANMODE_8 0x18 -#define GSM48_IE_CHANDESC_2 0x64 -#define GSM48_IE_MA_AFTER 0x72 -#define GSM48_IE_START_TIME 0x7c -#define GSM48_IE_FREQ_L_BEFORE 0x19 -//#define GSM48_IE_FRQLIST_BEFORE 0x19 -#define GSM48_IE_CH_DESC_1_BEFORE 0x1c -//#define GSM48_IE_CHDES_1_BEFORE 0x1c -#define GSM48_IE_CH_DESC_2_BEFORE 0x1d -//#define GSM48_IE_CHDES_2_BEFORE 0x1d -#define GSM48_IE_F_CH_SEQ_BEFORE 0x1e -//#define GSM48_IE_FRQSEQ_BEFORE 0x1e -#define GSM48_IE_CLASSMARK3 0x20 -#define GSM48_IE_MA_BEFORE 0x21 -#define GSM48_IE_RR_PACKET_UL 0x22 -#define GSM48_IE_RR_PACKET_DL 0x23 -#define GSM48_IE_CELL_CH_DESC 0x62 -#define GSM48_IE_CHANMODE_1 0x63 -#define GSM48_IE_CHDES_2_AFTER 0x64 -#define GSM48_IE_MODE_SEC_CH 0x66 -#define GSM48_IE_F_CH_SEQ_AFTER 0x69 -#define GSM48_IE_MA_AFTER 0x72 -#define GSM48_IE_BA_RANGE 0x73 -#define GSM48_IE_GROUP_CHDES 0x74 -#define GSM48_IE_BA_LIST_PREF 0x75 -#define GSM48_IE_MOB_OVSERV_DIF 0x77 -#define GSM48_IE_REALTIME_DIFF 0x7b -#define GSM48_IE_START_TIME 0x7c -#define GSM48_IE_TIMING_ADVANCE 0x7d -#define GSM48_IE_GROUP_CIP_SEQ 0x80 -#define GSM48_IE_CIP_MODE_SET 0x90 -#define GSM48_IE_GPRS_RESUMPT 0xc0 -#define GSM48_IE_SYNC_IND 0xd0 -/* System Information 4 (types are equal IEs above) */ -#define GSM48_IE_CBCH_CHAN_DESC 0x64 -#define GSM48_IE_CBCH_MOB_AL 0x72 - -/* Additional MM elements */ -#define GSM48_IE_LOCATION_AREA 0x13 -#define GSM48_IE_PRIORITY_LEV 0x80 -#define GSM48_IE_FOLLOW_ON_PROC 0xa1 -#define GSM48_IE_CTS_PERMISSION 0xa2 - -/* Section 10.5.4.23 / Table 10.5.130 */ -enum gsm48_signal_val { - GSM48_SIGNAL_DIALTONE = 0x00, - GSM48_SIGNAL_RINGBACK = 0x01, - GSM48_SIGNAL_INTERCEPT = 0x02, - GSM48_SIGNAL_NET_CONG = 0x03, - GSM48_SIGNAL_BUSY = 0x04, - GSM48_SIGNAL_CONFIRM = 0x05, - GSM48_SIGNAL_ANSWER = 0x06, - GSM48_SIGNAL_CALL_WAIT = 0x07, - GSM48_SIGNAL_OFF_HOOK = 0x08, - GSM48_SIGNAL_OFF = 0x3f, - GSM48_SIGNAL_ALERT_OFF = 0x4f, -}; - -enum gsm48_cause_loc { - GSM48_CAUSE_LOC_USER = 0x00, - GSM48_CAUSE_LOC_PRN_S_LU = 0x01, - GSM48_CAUSE_LOC_PUN_S_LU = 0x02, - GSM48_CAUSE_LOC_TRANS_NET = 0x03, - GSM48_CAUSE_LOC_PUN_S_RU = 0x04, - GSM48_CAUSE_LOC_PRN_S_RU = 0x05, - /* not defined */ - GSM48_CAUSE_LOC_INN_NET = 0x07, - GSM48_CAUSE_LOC_NET_BEYOND = 0x0a, -}; - -/* Section 10.5.2.31 RR Cause / Table 10.5.70 */ -enum gsm48_rr_cause { - GSM48_RR_CAUSE_NORMAL = 0x00, - GSM48_RR_CAUSE_ABNORMAL_UNSPEC = 0x01, - GSM48_RR_CAUSE_ABNORMAL_UNACCT = 0x02, - GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03, - GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04, - GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05, - GSM48_RR_CAUSE_HNDOVER_IMP = 0x06, - GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x07, - GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x08, - GSM48_RR_CAUSE_CALL_CLEARED = 0x41, - GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f, - GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60, - GSM48_RR_CAUSE_MSG_TYPE_N = 0x61, - GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT= 0x62, - GSM48_RR_CAUSE_COND_IE_ERROR = 0x64, - GSM48_RR_CAUSE_NO_CELL_ALLOC_A = 0x65, - GSM48_RR_CAUSE_PROT_ERROR_UNSPC = 0x6f, -}; - -/* Section 10.5.4.11 CC Cause / Table 10.5.123 */ -enum gsm48_cc_cause { - GSM48_CC_CAUSE_UNASSIGNED_NR = 1, - GSM48_CC_CAUSE_NO_ROUTE = 3, - GSM48_CC_CAUSE_CHAN_UNACCEPT = 6, - GSM48_CC_CAUSE_OP_DET_BARRING = 8, - GSM48_CC_CAUSE_NORM_CALL_CLEAR = 16, - GSM48_CC_CAUSE_USER_BUSY = 17, - GSM48_CC_CAUSE_USER_NOTRESPOND = 18, - GSM48_CC_CAUSE_USER_ALERTING_NA = 19, - GSM48_CC_CAUSE_CALL_REJECTED = 21, - GSM48_CC_CAUSE_NUMBER_CHANGED = 22, - GSM48_CC_CAUSE_PRE_EMPTION = 25, - GSM48_CC_CAUSE_NONSE_USER_CLR = 26, - GSM48_CC_CAUSE_DEST_OOO = 27, - GSM48_CC_CAUSE_INV_NR_FORMAT = 28, - GSM48_CC_CAUSE_FACILITY_REJ = 29, - GSM48_CC_CAUSE_RESP_STATUS_INQ = 30, - GSM48_CC_CAUSE_NORMAL_UNSPEC = 31, - GSM48_CC_CAUSE_NO_CIRCUIT_CHAN = 34, - GSM48_CC_CAUSE_NETWORK_OOO = 38, - GSM48_CC_CAUSE_TEMP_FAILURE = 41, - GSM48_CC_CAUSE_SWITCH_CONG = 42, - GSM48_CC_CAUSE_ACC_INF_DISCARD = 43, - GSM48_CC_CAUSE_REQ_CHAN_UNAVAIL = 44, - GSM48_CC_CAUSE_RESOURCE_UNAVAIL = 47, - GSM48_CC_CAUSE_QOS_UNAVAIL = 49, - GSM48_CC_CAUSE_REQ_FAC_NOT_SUBSC= 50, - GSM48_CC_CAUSE_INC_BARRED_CUG = 55, - GSM48_CC_CAUSE_BEARER_CAP_UNAUTH= 57, - GSM48_CC_CAUSE_BEARER_CA_UNAVAIL= 58, - GSM48_CC_CAUSE_SERV_OPT_UNAVAIL = 63, - GSM48_CC_CAUSE_BEARERSERV_UNIMPL= 65, - GSM48_CC_CAUSE_ACM_GE_ACM_MAX = 68, - GSM48_CC_CAUSE_REQ_FAC_NOTIMPL = 69, - GSM48_CC_CAUSE_RESTR_BCAP_AVAIL = 70, - GSM48_CC_CAUSE_SERV_OPT_UNIMPL = 79, - GSM48_CC_CAUSE_INVAL_TRANS_ID = 81, - GSM48_CC_CAUSE_USER_NOT_IN_CUG = 87, - GSM48_CC_CAUSE_INCOMPAT_DEST = 88, - GSM48_CC_CAUSE_INVAL_TRANS_NET = 91, - GSM48_CC_CAUSE_SEMANTIC_INCORR = 95, - GSM48_CC_CAUSE_INVAL_MAND_INF = 96, - GSM48_CC_CAUSE_MSGTYPE_NOTEXIST = 97, - GSM48_CC_CAUSE_MSGTYPE_INCOMPAT = 98, - GSM48_CC_CAUSE_IE_NOTEXIST = 99, - GSM48_CC_CAUSE_COND_IE_ERR = 100, - GSM48_CC_CAUSE_MSG_INCOMP_STATE = 101, - GSM48_CC_CAUSE_RECOVERY_TIMER = 102, - GSM48_CC_CAUSE_PROTO_ERR = 111, - GSM48_CC_CAUSE_INTERWORKING = 127, -}; - -/* Annex G, GSM specific cause values for mobility management */ -enum gsm48_reject_value { - GSM48_REJECT_IMSI_UNKNOWN_IN_HLR = 2, - GSM48_REJECT_ILLEGAL_MS = 3, - GSM48_REJECT_IMSI_UNKNOWN_IN_VLR = 4, - GSM48_REJECT_IMEI_NOT_ACCEPTED = 5, - GSM48_REJECT_ILLEGAL_ME = 6, - GSM48_REJECT_PLMN_NOT_ALLOWED = 11, - GSM48_REJECT_LOC_NOT_ALLOWED = 12, - GSM48_REJECT_ROAMING_NOT_ALLOWED = 13, - GSM48_REJECT_NETWORK_FAILURE = 17, - GSM48_REJECT_CONGESTION = 22, - GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32, - GSM48_REJECT_RQD_SRV_OPT_NOT_SUPPORTED = 33, - GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER = 34, - GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38, - GSM48_REJECT_INCORRECT_MESSAGE = 95, - GSM48_REJECT_INVALID_MANDANTORY_INF = 96, - GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED = 97, - GSM48_REJECT_MSG_TYPE_NOT_COMPATIBLE = 98, - GSM48_REJECT_INF_ELEME_NOT_IMPLEMENTED = 99, - GSM48_REJECT_CONDTIONAL_IE_ERROR = 100, - GSM48_REJECT_MSG_NOT_COMPATIBLE = 101, - GSM48_REJECT_PROTOCOL_ERROR = 111, - - /* according to G.6 Additional cause codes for GMM */ - GSM48_REJECT_GPRS_NOT_ALLOWED = 7, - GSM48_REJECT_SERVICES_NOT_ALLOWED = 8, - GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE = 9, - GSM48_REJECT_IMPLICITLY_DETACHED = 10, - GSM48_REJECT_GPRS_NOT_ALLOWED_IN_PLMN = 14, - GSM48_REJECT_MSC_TMP_NOT_REACHABLE = 16, -}; - -enum chreq_type { - CHREQ_T_EMERG_CALL, - CHREQ_T_CALL_REEST_TCH_F, - CHREQ_T_CALL_REEST_TCH_H, - CHREQ_T_CALL_REEST_TCH_H_DBL, - CHREQ_T_SDCCH, - CHREQ_T_TCH_F, - CHREQ_T_VOICE_CALL_TCH_H, - CHREQ_T_DATA_CALL_TCH_H, - CHREQ_T_LOCATION_UPD, - CHREQ_T_PAG_R_ANY_NECI0, - CHREQ_T_PAG_R_ANY_NECI1, - CHREQ_T_PAG_R_TCH_F, - CHREQ_T_PAG_R_TCH_FH, - CHREQ_T_LMU, - CHREQ_T_RESERVED_SDCCH, - CHREQ_T_RESERVED_IGNORE, -}; - -/* Chapter 11.3 */ -#define GSM48_T301 180, 0 -#define GSM48_T303 30, 0 -#define GSM48_T305 30, 0 -#define GSM48_T306 30, 0 -#define GSM48_T308 10, 0 -#define GSM48_T310 180, 0 -#define GSM48_T313 30, 0 -#define GSM48_T323 30, 0 -#define GSM48_T331 30, 0 -#define GSM48_T333 30, 0 -#define GSM48_T334 25, 0 /* min 15 */ -#define GSM48_T338 30, 0 -#define GSM48_T303_MS 30, 0 -#define GSM48_T305_MS 30, 0 -#define GSM48_T308_MS 30, 0 -#define GSM48_T310_MS 30, 0 -#define GSM48_T313_MS 30, 0 -#define GSM48_T323_MS 30, 0 -#define GSM48_T332_MS 30, 0 -#define GSM48_T335_MS 30, 0 - -/* Chapter 5.1.2.2 */ -#define GSM_CSTATE_NULL 0 -#define GSM_CSTATE_INITIATED 1 -#define GSM_CSTATE_MM_CONNECTION_PEND 2 /* see 10.5.4.6 */ -#define GSM_CSTATE_MO_CALL_PROC 3 -#define GSM_CSTATE_CALL_DELIVERED 4 -#define GSM_CSTATE_CALL_PRESENT 6 -#define GSM_CSTATE_CALL_RECEIVED 7 -#define GSM_CSTATE_CONNECT_REQUEST 8 -#define GSM_CSTATE_MO_TERM_CALL_CONF 9 -#define GSM_CSTATE_ACTIVE 10 -#define GSM_CSTATE_DISCONNECT_REQ 12 -#define GSM_CSTATE_DISCONNECT_IND 12 -#define GSM_CSTATE_RELEASE_REQ 19 -#define GSM_CSTATE_MO_ORIG_MODIFY 26 -#define GSM_CSTATE_MO_TERM_MODIFY 27 -#define GSM_CSTATE_CONNECT_IND 28 - -#define SBIT(a) (1 << a) -#define ALL_STATES 0xffffffff - -/* Table 10.5.3/3GPP TS 04.08: Location Area Identification information element */ -#define GSM_LAC_RESERVED_DETACHED 0x0 -#define GSM_LAC_RESERVED_ALL_BTS 0xfffe - -/* GSM 04.08 Bearer Capability: Information Transfer Capability */ -enum gsm48_bcap_itcap { - GSM48_BCAP_ITCAP_SPEECH = 0, - GSM48_BCAP_ITCAP_UNR_DIG_INF = 1, - GSM48_BCAP_ITCAP_3k1_AUDIO = 2, - GSM48_BCAP_ITCAP_FAX_G3 = 3, - GSM48_BCAP_ITCAP_OTHER = 5, - GSM48_BCAP_ITCAP_RESERVED = 7, -}; - -/* GSM 04.08 Bearer Capability: Transfer Mode */ -enum gsm48_bcap_tmod { - GSM48_BCAP_TMOD_CIRCUIT = 0, - GSM48_BCAP_TMOD_PACKET = 1, -}; - -/* GSM 04.08 Bearer Capability: Coding Standard */ -enum gsm48_bcap_coding { - GSM48_BCAP_CODING_GSM_STD = 0, -}; - -/* GSM 04.08 Bearer Capability: Radio Channel Requirements */ -enum gsm48_bcap_rrq { - GSM48_BCAP_RRQ_FR_ONLY = 1, - GSM48_BCAP_RRQ_DUAL_HR = 2, - GSM48_BCAP_RRQ_DUAL_FR = 3, -}; - -#define GSM48_TMSI_LEN 5 -#define GSM48_MID_TMSI_LEN (GSM48_TMSI_LEN + 2) -#define GSM48_MI_SIZE 32 - -/* Chapter 10.4.4.15 */ -struct gsm48_ra_id { - uint8_t digits[3]; /* MCC + MNC BCD digits */ - uint16_t lac; /* Location Area Code */ - uint8_t rac; /* Routing Area Code */ -} __attribute__ ((packed)); - - - -#endif /* PROTO_GSM_04_08_H */ diff --git a/include/osmocore/protocol/gsm_04_11.h b/include/osmocore/protocol/gsm_04_11.h deleted file mode 100644 index c6a2b193..00000000 --- a/include/osmocore/protocol/gsm_04_11.h +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef PROTO_GSM_04_11_H -#define PROTO_GSM_04_11_H - -#include - -/* GSM TS 04.11 definitions */ - -/* Chapter 5.2.3: SMC-CS states at the network side */ -enum gsm411_cp_state { - GSM411_CPS_IDLE = 0, - GSM411_CPS_MM_CONN_PENDING = 1, /* only MT ! */ - GSM411_CPS_WAIT_CP_ACK = 2, - GSM411_CPS_MM_ESTABLISHED = 3, -}; - -/* Chapter 6.2.2: SMR states at the network side */ -enum gsm411_rp_state { - GSM411_RPS_IDLE = 0, - GSM411_RPS_WAIT_FOR_RP_ACK = 1, - GSM411_RPS_WAIT_TO_TX_RP_ACK = 3, -}; - -/* Chapter 8.1.2 (refers to GSM 04.07 Chapter 11.2.3.1.1 */ -#define GSM411_PDISC_SMS 0x09 - -/* Chapter 8.1.3 */ -#define GSM411_MT_CP_DATA 0x01 -#define GSM411_MT_CP_ACK 0x04 -#define GSM411_MT_CP_ERROR 0x10 - -enum gsm411_cp_ie { - GSM411_CP_IE_USER_DATA = 0x01, /* 8.1.4.1 */ - GSM411_CP_IE_CAUSE = 0x02, /* 8.1.4.2. */ -}; - -/* Section 8.1.4.2 / Table 8.2 */ -enum gsm411_cp_cause { - GSM411_CP_CAUSE_NET_FAIL = 17, - GSM411_CP_CAUSE_CONGESTION = 22, - GSM411_CP_CAUSE_INV_TRANS_ID = 81, - GSM411_CP_CAUSE_SEMANT_INC_MSG = 95, - GSM411_CP_CAUSE_INV_MAND_INF = 96, - GSM411_CP_CAUSE_MSGTYPE_NOTEXIST= 97, - GSM411_CP_CAUSE_MSG_INCOMP_STATE= 98, - GSM411_CP_CAUSE_IE_NOTEXIST = 99, - GSM411_CP_CAUSE_PROTOCOL_ERR = 111, -}; - -/* Chapter 8.2.2 */ -#define GSM411_MT_RP_DATA_MO 0x00 -#define GSM411_MT_RP_DATA_MT 0x01 -#define GSM411_MT_RP_ACK_MO 0x02 -#define GSM411_MT_RP_ACK_MT 0x03 -#define GSM411_MT_RP_ERROR_MO 0x04 -#define GSM411_MT_RP_ERROR_MT 0x05 -#define GSM411_MT_RP_SMMA_MO 0x06 - -enum gsm411_rp_ie { - GSM411_IE_RP_USER_DATA = 0x41, /* 8.2.5.3 */ - GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */ -}; - -/* Chapter 8.2.5.4 Table 8.4 */ -enum gsm411_rp_cause { - /* valid only for MO */ - GSM411_RP_CAUSE_MO_NUM_UNASSIGNED = 1, - GSM411_RP_CAUSE_MO_OP_DET_BARR = 8, - GSM411_RP_CAUSE_MO_CALL_BARRED = 10, - GSM411_RP_CAUSE_MO_SMS_REJECTED = 21, - GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER = 27, - GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR = 28, - GSM411_RP_CAUSE_MO_FACILITY_REJ = 29, - GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR = 30, - GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER = 38, - GSM411_RP_CAUSE_MO_TEMP_FAIL = 41, - GSM411_RP_CAUSE_MO_CONGESTION = 42, - GSM411_RP_CAUSE_MO_RES_UNAVAIL = 47, - GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR = 50, - GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL = 69, - GSM411_RP_CAUSE_MO_INTERWORKING = 127, - /* valid only for MT */ - GSM411_RP_CAUSE_MT_MEM_EXCEEDED = 22, - /* valid for both directions */ - GSM411_RP_CAUSE_INV_TRANS_REF = 81, - GSM411_RP_CAUSE_SEMANT_INC_MSG = 95, - GSM411_RP_CAUSE_INV_MAND_INF = 96, - GSM411_RP_CAUSE_MSGTYPE_NOTEXIST = 97, - GSM411_RP_CAUSE_MSG_INCOMP_STATE = 98, - GSM411_RP_CAUSE_IE_NOTEXIST = 99, - GSM411_RP_CAUSE_PROTOCOL_ERR = 111, -}; - -/* Chapter 10: Timers */ -#define GSM411_TMR_TR1M 40, 0 /* 35 < x < 45 seconds */ -#define GSM411_TMR_TRAM 30, 0 /* 25 < x < 35 seconds */ -#define GSM411_TMR_TR2M 15, 0 /* 12 < x < 20 seconds */ - -#define GSM411_TMR_TC1A 30, 0 - -/* Chapter 8.2.1 */ -struct gsm411_rp_hdr { - uint8_t len; - uint8_t msg_type; - uint8_t msg_ref; - uint8_t data[0]; -} __attribute__ ((packed)); - -/* our own enum, not related to on-air protocol */ -enum sms_alphabet { - DCS_NONE, - DCS_7BIT_DEFAULT, - DCS_UCS2, - DCS_8BIT_DATA, -}; - -/* GSM 03.40 / Chapter 9.2.3.1: TP-Message-Type-Indicator */ -#define GSM340_SMS_DELIVER_SC2MS 0x00 -#define GSM340_SMS_DELIVER_REP_MS2SC 0x00 -#define GSM340_SMS_STATUS_REP_SC2MS 0x02 -#define GSM340_SMS_COMMAND_MS2SC 0x02 -#define GSM340_SMS_SUBMIT_MS2SC 0x01 -#define GSM340_SMS_SUBMIT_REP_SC2MS 0x01 -#define GSM340_SMS_RESSERVED 0x03 - -/* GSM 03.40 / Chapter 9.2.3.2: TP-More-Messages-to-Send */ -#define GSM340_TP_MMS_MORE 0 -#define GSM340_TP_MMS_NO_MORE 1 - -/* GSM 03.40 / Chapter 9.2.3.3: TP-Validity-Period-Format */ -#define GSM340_TP_VPF_NONE 0 -#define GSM340_TP_VPF_RELATIVE 2 -#define GSM340_TP_VPF_ENHANCED 1 -#define GSM340_TP_VPF_ABSOLUTE 3 - -/* GSM 03.40 / Chapter 9.2.3.4: TP-Status-Report-Indication */ -#define GSM340_TP_SRI_NONE 0 -#define GSM340_TP_SRI_PRESENT 1 - -/* GSM 03.40 / Chapter 9.2.3.5: TP-Status-Report-Request */ -#define GSM340_TP_SRR_NONE 0 -#define GSM340_TP_SRR_REQUESTED 1 - -/* GSM 03.40 / Chapter 9.2.3.9: TP-Protocol-Identifier */ -/* telematic interworking (001 or 111 in bits 7-5) */ -#define GSM340_TP_PID_IMPLICIT 0x00 -#define GSM340_TP_PID_TELEX 0x01 -#define GSM340_TP_PID_FAX_G3 0x02 -#define GSM340_TP_PID_FAX_G4 0x03 -#define GSM340_TP_PID_VOICE 0x04 -#define GSM430_TP_PID_ERMES 0x05 -#define GSM430_TP_PID_NATIONAL_PAGING 0x06 -#define GSM430_TP_PID_VIDEOTEX 0x07 -#define GSM430_TP_PID_TELETEX_UNSPEC 0x08 -#define GSM430_TP_PID_TELETEX_PSPDN 0x09 -#define GSM430_TP_PID_TELETEX_CSPDN 0x0a -#define GSM430_TP_PID_TELETEX_PSTN 0x0b -#define GSM430_TP_PID_TELETEX_ISDN 0x0c -#define GSM430_TP_PID_TELETEX_UCI 0x0d -#define GSM430_TP_PID_MSG_HANDLING 0x10 -#define GSM430_TP_PID_MSG_X400 0x11 -#define GSM430_TP_PID_EMAIL 0x12 -#define GSM430_TP_PID_GSM_MS 0x1f -/* if bit 7 = 0 and bit 6 = 1 */ -#define GSM430_TP_PID_SMS_TYPE_0 0 -#define GSM430_TP_PID_SMS_TYPE_1 1 -#define GSM430_TP_PID_SMS_TYPE_2 2 -#define GSM430_TP_PID_SMS_TYPE_3 3 -#define GSM430_TP_PID_SMS_TYPE_4 4 -#define GSM430_TP_PID_SMS_TYPE_5 5 -#define GSM430_TP_PID_SMS_TYPE_6 6 -#define GSM430_TP_PID_SMS_TYPE_7 7 -#define GSM430_TP_PID_RETURN_CALL_MSG 0x1f -#define GSM430_TP_PID_ME_DATA_DNLOAD 0x3d -#define GSM430_TP_PID_ME_DE_PERSONAL 0x3e -#define GSM430_TP_PID_ME_SIM_DNLOAD 0x3f - -/* GSM 03.38 Chapter 4: SMS Data Coding Scheme */ -#define GSM338_DCS_00_ - -#define GSM338_DCS_1110_7BIT (0 << 2) -#define GSM338_DCS_1111_7BIT (0 << 2) -#define GSM338_DCS_1111_8BIT_DATA (1 << 2) -#define GSM338_DCS_1111_CLASS0 0 -#define GSM338_DCS_1111_CLASS1_ME 1 -#define GSM338_DCS_1111_CLASS2_SIM 2 -#define GSM338_DCS_1111_CLASS3_TE 3 /* See TS 07.05 */ - -#endif /* PROTO_GSM_04_11_H */ diff --git a/include/osmocore/protocol/gsm_04_12.h b/include/osmocore/protocol/gsm_04_12.h deleted file mode 100644 index 9b1538a5..00000000 --- a/include/osmocore/protocol/gsm_04_12.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PROTO_GSM_04_12_H -#define PROTO_GSM_04_12_H - -#include - -/* GSM TS 04.12 definitions for Short Message Service Cell Broadcast */ - -#define GSM412_SEQ_FST_BLOCK 0x0 -#define GSM412_SEQ_SND_BLOCK 0x1 -#define GSM412_SEQ_TRD_BLOCK 0x2 -#define GSM412_SEQ_FTH_BLOCK 0x3 -#define GSM412_SEQ_FST_SCHED_BLOCK 0x8 -#define GSM412_SEQ_NULL_MSG 0xf - -struct gsm412_block_type { - uint8_t seq_nr : 4, - lb : 1, - lpd : 2, - spare : 1; -} __attribute__((packed)); - -struct gsm412_sched_msg { - uint8_t beg_slot_nr : 6, - type : 2; - uint8_t end_slot_nr : 6, - spare1 : 1, spare2: 1; - uint8_t cbsms_msg_map[6]; - uint8_t data[0]; -} __attribute__((packed)); - -#endif diff --git a/include/osmocore/protocol/gsm_04_80.h b/include/osmocore/protocol/gsm_04_80.h deleted file mode 100644 index fa5c9451..00000000 --- a/include/osmocore/protocol/gsm_04_80.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef PROTO_GSM_04_80_H -#define PROTO_GSM_04_80_H - -/* GSM TS 04.80 definitions (Supplementary Services Specification, Formats and Coding) */ - -/* Section 3.4 */ -#define GSM0480_MTYPE_RELEASE_COMPLETE 0x2A -#define GSM0480_MTYPE_FACILITY 0x3A -#define GSM0480_MTYPE_REGISTER 0x3B - -/* Section 3.5 */ -#define GSM0480_IE_FACILITY 0x1C -#define GSM0480_IE_SS_VERSION 0x7F - -/* Section 3.6.2 */ -#define GSM0480_CTYPE_INVOKE 0xA1 -#define GSM0480_CTYPE_RETURN_RESULT 0xA2 -#define GSM0480_CTYPE_RETURN_ERROR 0xA3 -#define GSM0480_CTYPE_REJECT 0xA4 - -/* Section 3.6.3 */ -#define GSM0480_COMPIDTAG_INVOKE_ID 0x02 -#define GSM0480_COMPIDTAG_LINKED_ID 0x80 - -/* Section 3.6.4 */ -#define GSM0480_OPERATION_CODE 0x02 - -/* Section 3.6.5 */ -#define GSM_0480_SEQUENCE_TAG 0x30 -#define GSM_0480_SET_TAG 0x31 - -/* Section 3.6.6 */ -#define GSM_0480_ERROR_CODE_TAG 0x02 - -/* Section 3.6.7 */ -/* Table 3.13 */ -#define GSM_0480_PROBLEM_CODE_TAG_GENERAL 0x80 -#define GSM_0480_PROBLEM_CODE_TAG_INVOKE 0x81 -#define GSM_0480_PROBLEM_CODE_TAG_RETURN_RESULT 0x82 -#define GSM_0480_PROBLEM_CODE_TAG_RETURN_ERROR 0x83 - -/* Table 3.14 */ -#define GSM_0480_GEN_PROB_CODE_UNRECOGNISED 0x00 -#define GSM_0480_GEN_PROB_CODE_MISTYPED 0x01 -#define GSM_0480_GEN_PROB_CODE_BAD_STRUCTURE 0x02 - -/* Table 3.15 */ -#define GSM_0480_INVOKE_PROB_CODE_DUPLICATE_INVOKE_ID 0x00 -#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_OPERATION 0x01 -#define GSM_0480_INVOKE_PROB_CODE_MISTYPED_PARAMETER 0x02 -#define GSM_0480_INVOKE_PROB_CODE_RESOURCE_LIMITATION 0x03 -#define GSM_0480_INVOKE_PROB_CODE_INITIATING_RELEASE 0x04 -#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_LINKED_ID 0x05 -#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_RESPONSE 0x06 -#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_OPERATION 0x07 - -/* Table 3.16 */ -#define GSM_0480_RESULT_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00 -#define GSM_0480_RESULT_PROB_CODE_RETURN_RESULT_UNEXPECTED 0x01 -#define GSM_0480_RESULT_PROB_CODE_MISTYPED_PARAMETER 0x02 - -/* Table 3.17 */ -#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00 -#define GSM_0480_ERROR_PROB_CODE_RETURN_ERROR_UNEXPECTED 0x01 -#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_ERROR 0x02 -#define GSM_0480_ERROR_PROB_CODE_UNEXPECTED_ERROR 0x03 -#define GSM_0480_ERROR_PROB_CODE_MISTYPED_PARAMETER 0x04 - -/* Section 4.5 */ -#define GSM0480_OP_CODE_REGISTER_SS 0x0A -#define GSM0480_OP_CODE_ERASE_SS 0x0B -#define GSM0480_OP_CODE_ACTIVATE_SS 0x0C -#define GSM0480_OP_CODE_DEACTIVATE_SS 0x0D -#define GSM0480_OP_CODE_INTERROGATE_SS 0x0E -#define GSM0480_OP_CODE_NOTIFY_SS 0x10 -#define GSM0480_OP_CODE_REGISTER_PASSWORD 0x11 -#define GSM0480_OP_CODE_GET_PASSWORD 0x12 -#define GSM0480_OP_CODE_PROCESS_USS_DATA 0x13 -#define GSM0480_OP_CODE_FORWARD_CHECK_SS_IND 0x26 -#define GSM0480_OP_CODE_PROCESS_USS_REQ 0x3B -#define GSM0480_OP_CODE_USS_REQUEST 0x3C -#define GSM0480_OP_CODE_USS_NOTIFY 0x3D -#define GSM0480_OP_CODE_FORWARD_CUG_INFO 0x78 -#define GSM0480_OP_CODE_SPLIT_MPTY 0x79 -#define GSM0480_OP_CODE_RETRIEVE_MPTY 0x7A -#define GSM0480_OP_CODE_HOLD_MPTY 0x7B -#define GSM0480_OP_CODE_BUILD_MPTY 0x7C -#define GSM0480_OP_CODE_FORWARD_CHARGE_ADVICE 0x7D - -#define GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER 0x01 -#define GSM0480_ERR_CODE_ILLEGAL_SUBSCRIBER 0x09 -#define GSM0480_ERR_CODE_BEARER_SERVICE_NOT_PROVISIONED 0x0A -#define GSM0480_ERR_CODE_TELESERVICE_NOT_PROVISIONED 0x0B -#define GSM0480_ERR_CODE_ILLEGAL_EQUIPMENT 0x0C -#define GSM0480_ERR_CODE_CALL_BARRED 0x0D -#define GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION 0x10 -#define GSM0480_ERR_CODE_SS_ERROR_STATUS 0x11 -#define GSM0480_ERR_CODE_SS_NOT_AVAILABLE 0x12 -#define GSM0480_ERR_CODE_SS_SUBSCRIPTION_VIOLATION 0x13 -#define GSM0480_ERR_CODE_SS_INCOMPATIBILITY 0x14 -#define GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED 0x15 -#define GSM0480_ERR_CODE_ABSENT_SUBSCRIBER 0x1B -#define GSM0480_ERR_CODE_SYSTEM_FAILURE 0x22 -#define GSM0480_ERR_CODE_DATA_MISSING 0x23 -#define GSM0480_ERR_CODE_UNEXPECTED_DATA_VALUE 0x24 -#define GSM0480_ERR_CODE_PW_REGISTRATION_FAILURE 0x25 -#define GSM0480_ERR_CODE_NEGATIVE_PW_CHECK 0x26 -#define GSM0480_ERR_CODE_NUM_PW_ATTEMPTS_VIOLATION 0x2B -#define GSM0480_ERR_CODE_UNKNOWN_ALPHABET 0x47 -#define GSM0480_ERR_CODE_USSD_BUSY 0x48 -#define GSM0480_ERR_CODE_MAX_MPTY_PARTICIPANTS 0x7E -#define GSM0480_ERR_CODE_RESOURCES_NOT_AVAILABLE 0x7F - -/* ASN.1 type-tags */ -#define ASN1_BOOLEAN_TAG 0x01 -#define ASN1_INTEGER_TAG 0x02 -#define ASN1_BIT_STRING_TAG 0x03 -#define ASN1_OCTET_STRING_TAG 0x04 -#define ASN1_NULL_TYPE_TAG 0x05 -#define ASN1_OBJECT_ID_TAG 0x06 -#define ASN1_UTF8_STRING_TAG 0x0C -#define ASN1_PRINTABLE_STRING_TAG 0x13 -#define ASN1_IA5_STRING_TAG 0x16 -#define ASN1_UNICODE_STRING_TAG 0x1E - -#endif /* PROTO_GSM_04_80_H */ diff --git a/include/osmocore/protocol/gsm_08_08.h b/include/osmocore/protocol/gsm_08_08.h deleted file mode 100644 index 6b8f9359..00000000 --- a/include/osmocore/protocol/gsm_08_08.h +++ /dev/null @@ -1,303 +0,0 @@ -/* From GSM08.08 */ - -#ifndef GSM_0808_H -#define GSM_0808_H - -#include - -/* - * this is from GSM 03.03 CGI but is copied in GSM 08.08 - * in § 3.2.2.27 for Cell Identifier List - */ -enum CELL_IDENT { - CELL_IDENT_WHOLE_GLOBAL = 0, - CELL_IDENT_LAC_AND_CI = 1, - CELL_IDENT_CI = 2, - CELL_IDENT_NO_CELL = 3, - CELL_IDENT_LAI_AND_LAC = 4, - CELL_IDENT_LAC = 5, - CELL_IDENT_BSS = 6, - CELL_IDENT_UTRAN_PLMN_LAC_RNC = 8, - CELL_IDENT_UTRAN_RNC = 9, - CELL_IDENT_UTRAN_LAC_RNC = 10, -}; - - -/* GSM 08.06 § 6.3 */ -enum BSSAP_MSG_TYPE { - BSSAP_MSG_BSS_MANAGEMENT = 0x0, - BSSAP_MSG_DTAP = 0x1, -}; - -struct bssmap_header { - uint8_t type; - uint8_t length; -} __attribute__((packed)); - -struct dtap_header { - uint8_t type; - uint8_t link_id; - uint8_t length; -} __attribute__((packed)); - - -enum BSS_MAP_MSG_TYPE { - BSS_MAP_MSG_RESERVED_0 = 0, - - /* ASSIGNMENT MESSAGES */ - BSS_MAP_MSG_ASSIGMENT_RQST = 1, - BSS_MAP_MSG_ASSIGMENT_COMPLETE = 2, - BSS_MAP_MSG_ASSIGMENT_FAILURE = 3, - - /* HANDOVER MESSAGES */ - BSS_MAP_MSG_HANDOVER_RQST = 16, - BSS_MAP_MSG_HANDOVER_REQUIRED = 17, - BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE= 18, - BSS_MAP_MSG_HANDOVER_CMD = 19, - BSS_MAP_MSG_HANDOVER_COMPLETE = 20, - BSS_MAP_MSG_HANDOVER_SUCCEEDED = 21, - BSS_MAP_MSG_HANDOVER_FAILURE = 22, - BSS_MAP_MSG_HANDOVER_PERFORMED = 23, - BSS_MAP_MSG_HANDOVER_CANDIDATE_ENQUIRE = 24, - BSS_MAP_MSG_HANDOVER_CANDIDATE_RESPONSE = 25, - BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT = 26, - BSS_MAP_MSG_HANDOVER_DETECT = 27, - - /* RELEASE MESSAGES */ - BSS_MAP_MSG_CLEAR_CMD = 32, - BSS_MAP_MSG_CLEAR_COMPLETE = 33, - BSS_MAP_MSG_CLEAR_RQST = 34, - BSS_MAP_MSG_RESERVED_1 = 35, - BSS_MAP_MSG_RESERVED_2 = 36, - BSS_MAP_MSG_SAPI_N_REJECT = 37, - BSS_MAP_MSG_CONFUSION = 38, - - /* OTHER CONNECTION RELATED MESSAGES */ - BSS_MAP_MSG_SUSPEND = 40, - BSS_MAP_MSG_RESUME = 41, - BSS_MAP_MSG_CONNECTION_ORIENTED_INFORMATION = 42, - BSS_MAP_MSG_PERFORM_LOCATION_RQST = 43, - BSS_MAP_MSG_LSA_INFORMATION = 44, - BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE = 45, - BSS_MAP_MSG_PERFORM_LOCATION_ABORT = 46, - BSS_MAP_MSG_COMMON_ID = 47, - - /* GENERAL MESSAGES */ - BSS_MAP_MSG_RESET = 48, - BSS_MAP_MSG_RESET_ACKNOWLEDGE = 49, - BSS_MAP_MSG_OVERLOAD = 50, - BSS_MAP_MSG_RESERVED_3 = 51, - BSS_MAP_MSG_RESET_CIRCUIT = 52, - BSS_MAP_MSG_RESET_CIRCUIT_ACKNOWLEDGE = 53, - BSS_MAP_MSG_MSC_INVOKE_TRACE = 54, - BSS_MAP_MSG_BSS_INVOKE_TRACE = 55, - BSS_MAP_MSG_CONNECTIONLESS_INFORMATION = 58, - - /* TERRESTRIAL RESOURCE MESSAGES */ - BSS_MAP_MSG_BLOCK = 64, - BSS_MAP_MSG_BLOCKING_ACKNOWLEDGE = 65, - BSS_MAP_MSG_UNBLOCK = 66, - BSS_MAP_MSG_UNBLOCKING_ACKNOWLEDGE = 67, - BSS_MAP_MSG_CIRCUIT_GROUP_BLOCK = 68, - BSS_MAP_MSG_CIRCUIT_GROUP_BLOCKING_ACKNOWLEDGE = 69, - BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCK = 70, - BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCKING_ACKNOWLEDGE = 71, - BSS_MAP_MSG_UNEQUIPPED_CIRCUIT = 72, - BSS_MAP_MSG_CHANGE_CIRCUIT = 78, - BSS_MAP_MSG_CHANGE_CIRCUIT_ACKNOWLEDGE = 79, - - /* RADIO RESOURCE MESSAGES */ - BSS_MAP_MSG_RESOURCE_RQST = 80, - BSS_MAP_MSG_RESOURCE_INDICATION = 81, - BSS_MAP_MSG_PAGING = 82, - BSS_MAP_MSG_CIPHER_MODE_CMD = 83, - BSS_MAP_MSG_CLASSMARK_UPDATE = 84, - BSS_MAP_MSG_CIPHER_MODE_COMPLETE = 85, - BSS_MAP_MSG_QUEUING_INDICATION = 86, - BSS_MAP_MSG_COMPLETE_LAYER_3 = 87, - BSS_MAP_MSG_CLASSMARK_RQST = 88, - BSS_MAP_MSG_CIPHER_MODE_REJECT = 89, - BSS_MAP_MSG_LOAD_INDICATION = 90, - - /* VGCS/VBS */ - BSS_MAP_MSG_VGCS_VBS_SETUP = 4, - BSS_MAP_MSG_VGCS_VBS_SETUP_ACK = 5, - BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE = 6, - BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST = 7, - BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT = 28, - BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE = 29, - BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30, - BSS_MAP_MSG_UPLINK_RQST = 31, - BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39, - BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION = 73, - BSS_MAP_MSG_UPLINK_RELEASE_INDICATION = 74, - BSS_MAP_MSG_UPLINK_REJECT_CMD = 75, - BSS_MAP_MSG_UPLINK_RELEASE_CMD = 76, - BSS_MAP_MSG_UPLINK_SEIZED_CMD = 77, -}; - -enum GSM0808_IE_CODING { - GSM0808_IE_CIRCUIT_IDENTITY_CODE = 1, - GSM0808_IE_RESERVED_0 = 2, - GSM0808_IE_RESOURCE_AVAILABLE = 3, - GSM0808_IE_CAUSE = 4, - GSM0808_IE_CELL_IDENTIFIER = 5, - GSM0808_IE_PRIORITY = 6, - GSM0808_IE_LAYER_3_HEADER_INFORMATION = 7, - GSM0808_IE_IMSI = 8, - GSM0808_IE_TMSI = 9, - GSM0808_IE_ENCRYPTION_INFORMATION = 10, - GSM0808_IE_CHANNEL_TYPE = 11, - GSM0808_IE_PERIODICITY = 12, - GSM0808_IE_EXTENDED_RESOURCE_INDICATOR = 13, - GSM0808_IE_NUMBER_OF_MSS = 14, - GSM0808_IE_RESERVED_1 = 15, - GSM0808_IE_RESERVED_2 = 16, - GSM0808_IE_RESERVED_3 = 17, - GSM0808_IE_CLASSMARK_INFORMATION_T2 = 18, - GSM0808_IE_CLASSMARK_INFORMATION_T3 = 19, - GSM0808_IE_INTERFERENCE_BAND_TO_USE = 20, - GSM0808_IE_RR_CAUSE = 21, - GSM0808_IE_RESERVED_4 = 22, - GSM0808_IE_LAYER_3_INFORMATION = 23, - GSM0808_IE_DLCI = 24, - GSM0808_IE_DOWNLINK_DTX_FLAG = 25, - GSM0808_IE_CELL_IDENTIFIER_LIST = 26, - GSM0808_IE_RESPONSE_RQST = 27, - GSM0808_IE_RESOURCE_INDICATION_METHOD = 28, - GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1 = 29, - GSM0808_IE_CIRCUIT_IDENTITY_CODE_LIST = 30, - GSM0808_IE_DIAGNOSTIC = 31, - GSM0808_IE_LAYER_3_MESSAGE_CONTENTS = 32, - GSM0808_IE_CHOSEN_CHANNEL = 33, - GSM0808_IE_TOTAL_RESOURCE_ACCESSIBLE = 34, - GSM0808_IE_CIPHER_RESPONSE_MODE = 35, - GSM0808_IE_CHANNEL_NEEDED = 36, - GSM0808_IE_TRACE_TYPE = 37, - GSM0808_IE_TRIGGERID = 38, - GSM0808_IE_TRACE_REFERENCE = 39, - GSM0808_IE_TRANSACTIONID = 40, - GSM0808_IE_MOBILE_IDENTITY = 41, - GSM0808_IE_OMCID = 42, - GSM0808_IE_FORWARD_INDICATOR = 43, - GSM0808_IE_CHOSEN_ENCR_ALG = 44, - GSM0808_IE_CIRCUIT_POOL = 45, - GSM0808_IE_CIRCUIT_POOL_LIST = 46, - GSM0808_IE_TIME_INDICATION = 47, - GSM0808_IE_RESOURCE_SITUATION = 48, - GSM0808_IE_CURRENT_CHANNEL_TYPE_1 = 49, - GSM0808_IE_QUEUEING_INDICATOR = 50, - GSM0808_IE_SPEECH_VERSION = 64, - GSM0808_IE_ASSIGNMENT_REQUIREMENT = 51, - GSM0808_IE_TALKER_FLAG = 53, - GSM0808_IE_CONNECTION_RELEASE_RQSTED = 54, - GSM0808_IE_GROUP_CALL_REFERENCE = 55, - GSM0808_IE_EMLPP_PRIORITY = 56, - GSM0808_IE_CONFIG_EVO_INDI = 57, - GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION = 58, - GSM0808_IE_LSA_IDENTIFIER = 59, - GSM0808_IE_LSA_IDENTIFIER_LIST = 60, - GSM0808_IE_LSA_INFORMATION = 61, - GSM0808_IE_LCS_QOS = 62, - GSM0808_IE_LSA_ACCESS_CTRL_SUPPR = 63, - GSM0808_IE_LCS_PRIORITY = 67, - GSM0808_IE_LOCATION_TYPE = 68, - GSM0808_IE_LOCATION_ESTIMATE = 69, - GSM0808_IE_POSITIONING_DATA = 70, - GSM0808_IE_LCS_CAUSE = 71, - GSM0808_IE_LCS_CLIENT_TYPE = 72, - GSM0808_IE_APDU = 73, - GSM0808_IE_NETWORK_ELEMENT_IDENTITY = 74, - GSM0808_IE_GPS_ASSISTANCE_DATA = 75, - GSM0808_IE_DECIPHERING_KEYS = 76, - GSM0808_IE_RETURN_ERROR_RQST = 77, - GSM0808_IE_RETURN_ERROR_CAUSE = 78, - GSM0808_IE_SEGMENTATION = 79, - GSM0808_IE_SERVICE_HANDOVER = 80, - GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS = 81, - GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82, - GSM0808_IE_RESERVED_5 = 65, - GSM0808_IE_RESERVED_6 = 66, -}; - -enum gsm0808_cause { - GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE = 0, - GSM0808_CAUSE_RADIO_INTERFACE_FAILURE = 1, - GSM0808_CAUSE_UPLINK_QUALITY = 2, - GSM0808_CAUSE_UPLINK_STRENGTH = 3, - GSM0808_CAUSE_DOWNLINK_QUALITY = 4, - GSM0808_CAUSE_DOWNLINK_STRENGTH = 5, - GSM0808_CAUSE_DISTANCE = 6, - GSM0808_CAUSE_O_AND_M_INTERVENTION = 7, - GSM0808_CAUSE_RESPONSE_TO_MSC_INVOCATION = 8, - GSM0808_CAUSE_CALL_CONTROL = 9, - GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION = 10, - GSM0808_CAUSE_HANDOVER_SUCCESSFUL = 11, - GSM0808_CAUSE_BETTER_CELL = 12, - GSM0808_CAUSE_DIRECTED_RETRY = 13, - GSM0808_CAUSE_JOINED_GROUP_CALL_CHANNEL = 14, - GSM0808_CAUSE_TRAFFIC = 15, - GSM0808_CAUSE_EQUIPMENT_FAILURE = 32, - GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE = 33, - GSM0808_CAUSE_RQSTED_TERRESTRIAL_RESOURCE_UNAVAILABLE = 34, - GSM0808_CAUSE_CCCH_OVERLOAD = 35, - GSM0808_CAUSE_PROCESSOR_OVERLOAD = 36, - GSM0808_CAUSE_BSS_NOT_EQUIPPED = 37, - GSM0808_CAUSE_MS_NOT_EQUIPPED = 38, - GSM0808_CAUSE_INVALID_CELL = 39, - GSM0808_CAUSE_TRAFFIC_LOAD = 40, - GSM0808_CAUSE_PREEMPTION = 41, - GSM0808_CAUSE_RQSTED_TRANSCODING_RATE_ADAPTION_UNAVAILABLE = 48, - GSM0808_CAUSE_CIRCUIT_POOL_MISMATCH = 49, - GSM0808_CAUSE_SWITCH_CIRCUIT_POOL = 50, - GSM0808_CAUSE_RQSTED_SPEECH_VERSION_UNAVAILABLE = 51, - GSM0808_CAUSE_LSA_NOT_ALLOWED = 52, - GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED = 64, - GSM0808_CAUSE_TERRESTRIAL_CIRCUIT_ALREADY_ALLOCATED = 80, - GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS = 81, - GSM0808_CAUSE_INFORMATION_ELEMENT_OR_FIELD_MISSING = 82, - GSM0808_CAUSE_INCORRECT_VALUE = 83, - GSM0808_CAUSE_UNKNOWN_MESSAGE_TYPE = 84, - GSM0808_CAUSE_UNKNOWN_INFORMATION_ELEMENT = 85, - GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC = 96, -}; - -/* GSM 08.08 3.2.2.11 Channel Type */ -enum gsm0808_chan_indicator { - GSM0808_CHAN_SPEECH = 1, - GSM0808_CHAN_DATA = 2, - GSM0808_CHAN_SIGN = 3, -}; - -enum gsm0808_chan_rate_type_data { - GSM0808_DATA_FULL_BM = 0x8, - GSM0808_DATA_HALF_LM = 0x9, - GSM0808_DATA_FULL_RPREF = 0xa, - GSM0808_DATA_HALF_PREF = 0xb, - GSM0808_DATA_FULL_PREF_NO_CHANGE = 0x1a, - GSM0808_DATA_HALF_PREF_NO_CHANGE = 0x1b, - GSM0808_DATA_MULTI_MASK = 0x20, - GSM0808_DATA_MULTI_MASK_NO_CHANGE = 0x30, -}; - -enum gsm0808_chan_rate_type_speech { - GSM0808_SPEECH_FULL_BM = 0x8, - GSM0808_SPEECH_HALF_LM = 0x9, - GSM0808_SPEECH_FULL_PREF= 0xa, - GSM0808_SPEECH_HALF_PREF= 0xb, - GSM0808_SPEECH_FULL_PREF_NO_CHANGE = 0x1a, - GSM0808_SPEECH_HALF_PREF_NO_CHANGE = 0x1b, - GSM0808_SPEECH_PERM = 0xf, - GSM0808_SPEECH_PERM_NO_CHANGE = 0x1f, -}; - -enum gsm0808_permitted_speech { - GSM0808_PERM_FR1 = 0x01, - GSM0808_PERM_FR2 = 0x11, - GSM0808_PERM_FR3 = 0x21, - GSM0808_PERM_HR1 = GSM0808_PERM_FR1 | 0x4, - GSM0808_PERM_HR2 = GSM0808_PERM_FR2 | 0x4, - GSM0808_PERM_HR3 = GSM0808_PERM_FR3 | 0x4, -}; - -#endif diff --git a/include/osmocore/protocol/gsm_08_58.h b/include/osmocore/protocol/gsm_08_58.h deleted file mode 100644 index 74a4083b..00000000 --- a/include/osmocore/protocol/gsm_08_58.h +++ /dev/null @@ -1,546 +0,0 @@ -#ifndef PROTO_GSM_08_58_H -#define PROTO_GSM_08_58_H - -/* GSM Radio Signalling Link messages on the A-bis interface - * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */ - -/* (C) 2008 by Harald Welte - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include - -struct abis_rsl_common_hdr { - uint8_t msg_discr; - uint8_t msg_type; - uint8_t data[0]; -} __attribute__ ((packed)); - -/* Chapter 8.3 */ -struct abis_rsl_rll_hdr { - struct abis_rsl_common_hdr c; - uint8_t ie_chan; - uint8_t chan_nr; - uint8_t ie_link_id; - uint8_t link_id; - uint8_t data[0]; -} __attribute__ ((packed)); - -/* Chapter 8.3 and 8.4 */ -struct abis_rsl_dchan_hdr { - struct abis_rsl_common_hdr c; - uint8_t ie_chan; - uint8_t chan_nr; - uint8_t data[0]; -} __attribute__ ((packed)); - -/* Chapter 8.5 */ -struct abis_rsl_cchan_hdr { - struct abis_rsl_common_hdr c; - uint8_t ie_chan; - uint8_t chan_nr; - uint8_t data[0]; -} __attribute__ ((packed)); - - -/* Chapter 9.1 */ -#define ABIS_RSL_MDISC_RLL 0x02 -#define ABIS_RSL_MDISC_DED_CHAN 0x08 -#define ABIS_RSL_MDISC_COM_CHAN 0x0c -#define ABIS_RSL_MDISC_TRX 0x10 -#define ABIS_RSL_MDISC_LOC 0x20 -#define ABIS_RSL_MDISC_IPACCESS 0x7e -#define ABIS_RSL_MDISC_TRANSP 0x01 - -#define ABIS_RSL_MDISC_IS_TRANSP(x) (x & 0x01) - -/* Chapter 9.1 */ -enum abis_rsl_msgtype { - /* Radio Link Layer Management */ - RSL_MT_DATA_REQ = 0x01, - RSL_MT_DATA_IND, - RSL_MT_ERROR_IND, - RSL_MT_EST_REQ, - RSL_MT_EST_CONF, - RSL_MT_EST_IND, - RSL_MT_REL_REQ, - RSL_MT_REL_CONF, - RSL_MT_REL_IND, - RSL_MT_UNIT_DATA_REQ, - RSL_MT_UNIT_DATA_IND, /* 0x0b */ - RSL_MT_SUSP_REQ, /* non-standard elements */ - RSL_MT_SUSP_CONF, - RSL_MT_RES_REQ, - RSL_MT_RECON_REQ, /* 0x0f */ - - /* Common Channel Management / TRX Management */ - RSL_MT_BCCH_INFO = 0x11, - RSL_MT_CCCH_LOAD_IND, - RSL_MT_CHAN_RQD, - RSL_MT_DELETE_IND, - RSL_MT_PAGING_CMD, - RSL_MT_IMMEDIATE_ASSIGN_CMD, - RSL_MT_SMS_BC_REQ, - RSL_MT_CHAN_CONF, /* non-standard element */ - /* empty */ - RSL_MT_RF_RES_IND = 0x19, - RSL_MT_SACCH_FILL, - RSL_MT_OVERLOAD, - RSL_MT_ERROR_REPORT, - RSL_MT_SMS_BC_CMD, - RSL_MT_CBCH_LOAD_IND, - RSL_MT_NOT_CMD, /* 0x1f */ - - /* Dedicate Channel Management */ - RSL_MT_CHAN_ACTIV = 0x21, - RSL_MT_CHAN_ACTIV_ACK, - RSL_MT_CHAN_ACTIV_NACK, - RSL_MT_CONN_FAIL, - RSL_MT_DEACTIVATE_SACCH, - RSL_MT_ENCR_CMD, - RSL_MT_HANDO_DET, - RSL_MT_MEAS_RES, - RSL_MT_MODE_MODIFY_REQ, - RSL_MT_MODE_MODIFY_ACK, - RSL_MT_MODE_MODIFY_NACK, - RSL_MT_PHY_CONTEXT_REQ, - RSL_MT_PHY_CONTEXT_CONF, - RSL_MT_RF_CHAN_REL, - RSL_MT_MS_POWER_CONTROL, - RSL_MT_BS_POWER_CONTROL, /* 0x30 */ - RSL_MT_PREPROC_CONFIG, - RSL_MT_PREPROC_MEAS_RES, - RSL_MT_RF_CHAN_REL_ACK, - RSL_MT_SACCH_INFO_MODIFY, - RSL_MT_TALKER_DET, - RSL_MT_LISTENER_DET, - RSL_MT_REMOTE_CODEC_CONF_REP, - RSL_MT_RTD_REP, - RSL_MT_PRE_HANDO_NOTIF, - RSL_MT_MR_CODEC_MOD_REQ, - RSL_MT_MR_CODEC_MOD_ACK, - RSL_MT_MR_CODEC_MOD_NACK, - RSL_MT_MR_CODEC_MOD_PER, - RSL_MT_TFO_REP, - RSL_MT_TFO_MOD_REQ, /* 0x3f */ - RSL_MT_LOCATION_INFO = 0x41, - - /* ip.access specific RSL message types */ - RSL_MT_IPAC_DIR_RETR_ENQ = 0x40, - RSL_MT_IPAC_PDCH_ACT = 0x48, - RSL_MT_IPAC_PDCH_ACT_ACK, - RSL_MT_IPAC_PDCH_ACT_NACK, - RSL_MT_IPAC_PDCH_DEACT = 0x4b, - RSL_MT_IPAC_PDCH_DEACT_ACK, - RSL_MT_IPAC_PDCH_DEACT_NACK, - RSL_MT_IPAC_CONNECT_MUX = 0x50, - RSL_MT_IPAC_CONNECT_MUX_ACK, - RSL_MT_IPAC_CONNECT_MUX_NACK, - RSL_MT_IPAC_BIND_MUX = 0x53, - RSL_MT_IPAC_BIND_MUX_ACK, - RSL_MT_IPAC_BIND_MUX_NACK, - RSL_MT_IPAC_DISC_MUX = 0x56, - RSL_MT_IPAC_DISC_MUX_ACK, - RSL_MT_IPAC_DISC_MUX_NACK, - RSL_MT_IPAC_CRCX = 0x70, /* Bind to local BTS RTP port */ - RSL_MT_IPAC_CRCX_ACK, - RSL_MT_IPAC_CRCX_NACK, - RSL_MT_IPAC_MDCX = 0x73, - RSL_MT_IPAC_MDCX_ACK, - RSL_MT_IPAC_MDCX_NACK, - RSL_MT_IPAC_DLCX_IND = 0x76, - RSL_MT_IPAC_DLCX = 0x77, - RSL_MT_IPAC_DLCX_ACK, - RSL_MT_IPAC_DLCX_NACK, -}; - -/* Siemens vendor-specific */ -enum abis_rsl_msgtype_siemens { - RSL_MT_SIEMENS_MRPCI = 0x41, - RSL_MT_SIEMENS_INTRAC_HO_COND_IND = 0x42, - RSL_MT_SIEMENS_INTERC_HO_COND_IND = 0x43, - RSL_MT_SIEMENS_FORCED_HO_REQ = 0x44, - RSL_MT_SIEMENS_PREF_AREA_REQ = 0x45, - RSL_MT_SIEMENS_PREF_AREA = 0x46, - RSL_MT_SIEMENS_START_TRACE = 0x47, - RSL_MT_SIEMENS_START_TRACE_ACK = 0x48, - RSL_MT_SIEMENS_STOP_TRACE = 0x49, - RSL_MT_SIEMENS_TRMR = 0x4a, - RSL_MT_SIEMENS_HO_FAIL_IND = 0x4b, - RSL_MT_SIEMENS_STOP_TRACE_ACK = 0x4c, - RSL_MT_SIEMENS_UPLF = 0x4d, - RSL_MT_SIEMENS_UPLB = 0x4e, - RSL_MT_SIEMENS_SET_SYS_INFO_10 = 0x4f, - RSL_MT_SIEMENS_MODIF_COND_IND = 0x50, -}; - -/* Chapter 9.3 */ -enum abis_rsl_ie { - RSL_IE_CHAN_NR = 0x01, - RSL_IE_LINK_IDENT, - RSL_IE_ACT_TYPE, - RSL_IE_BS_POWER, - RSL_IE_CHAN_IDENT, - RSL_IE_CHAN_MODE, - RSL_IE_ENCR_INFO, - RSL_IE_FRAME_NUMBER, - RSL_IE_HANDO_REF, - RSL_IE_L1_INFO, - RSL_IE_L3_INFO, - RSL_IE_MS_IDENTITY, - RSL_IE_MS_POWER, - RSL_IE_PAGING_GROUP, - RSL_IE_PAGING_LOAD, - RSL_IE_PYHS_CONTEXT = 0x10, - RSL_IE_ACCESS_DELAY, - RSL_IE_RACH_LOAD, - RSL_IE_REQ_REFERENCE, - RSL_IE_RELEASE_MODE, - RSL_IE_RESOURCE_INFO, - RSL_IE_RLM_CAUSE, - RSL_IE_STARTNG_TIME, - RSL_IE_TIMING_ADVANCE, - RSL_IE_UPLINK_MEAS, - RSL_IE_CAUSE, - RSL_IE_MEAS_RES_NR, - RSL_IE_MSG_ID, - /* reserved */ - RSL_IE_SYSINFO_TYPE = 0x1e, - RSL_IE_MS_POWER_PARAM, - RSL_IE_BS_POWER_PARAM, - RSL_IE_PREPROC_PARAM, - RSL_IE_PREPROC_MEAS, - RSL_IE_IMM_ASS_INFO, /* Phase 1 (3.6.0), later Full below */ - RSL_IE_SMSCB_INFO = 0x24, - RSL_IE_MS_TIMING_OFFSET, - RSL_IE_ERR_MSG, - RSL_IE_FULL_BCCH_INFO, - RSL_IE_CHAN_NEEDED, - RSL_IE_CB_CMD_TYPE, - RSL_IE_SMSCB_MSG, - RSL_IE_FULL_IMM_ASS_INFO, - RSL_IE_SACCH_INFO, - RSL_IE_CBCH_LOAD_INFO, - RSL_IE_SMSCB_CHAN_INDICATOR, - RSL_IE_GROUP_CALL_REF, - RSL_IE_CHAN_DESC = 0x30, - RSL_IE_NCH_DRX_INFO, - RSL_IE_CMD_INDICATOR, - RSL_IE_EMLPP_PRIO, - RSL_IE_UIC, - RSL_IE_MAIN_CHAN_REF, - RSL_IE_MR_CONFIG, - RSL_IE_MR_CONTROL, - RSL_IE_SUP_CODEC_TYPES, - RSL_IE_CODEC_CONFIG, - RSL_IE_RTD, - RSL_IE_TFO_STATUS, - RSL_IE_LLP_APDU, - /* Siemens vendor-specific */ - RSL_IE_SIEMENS_MRPCI = 0x40, - RSL_IE_SIEMENS_PREF_AREA_TYPE = 0x43, - RSL_IE_SIEMENS_ININ_CELL_HO_PAR = 0x45, - RSL_IE_SIEMENS_TRACE_REF_NR = 0x46, - RSL_IE_SIEMENS_INT_TRACE_IDX = 0x47, - RSL_IE_SIEMENS_L2_HDR_INFO = 0x48, - RSL_IE_SIEMENS_HIGHEST_RATE = 0x4e, - RSL_IE_SIEMENS_SUGGESTED_RATE = 0x4f, - - /* ip.access */ - RSL_IE_IPAC_SRTP_CONFIG = 0xe0, - RSL_IE_IPAC_PROXY_UDP = 0xe1, - RSL_IE_IPAC_BSCMPL_TOUT = 0xe2, - RSL_IE_IPAC_REMOTE_IP = 0xf0, - RSL_IE_IPAC_REMOTE_PORT = 0xf1, - RSL_IE_IPAC_RTP_PAYLOAD = 0xf2, - RSL_IE_IPAC_LOCAL_PORT = 0xf3, - RSL_IE_IPAC_SPEECH_MODE = 0xf4, - RSL_IE_IPAC_LOCAL_IP = 0xf5, - RSL_IE_IPAC_CONN_STAT = 0xf6, - RSL_IE_IPAC_HO_C_PARMS = 0xf7, - RSL_IE_IPAC_CONN_ID = 0xf8, - RSL_IE_IPAC_RTP_CSD_FMT = 0xf9, - RSL_IE_IPAC_RTP_JIT_BUF = 0xfa, - RSL_IE_IPAC_RTP_COMPR = 0xfb, - RSL_IE_IPAC_RTP_PAYLOAD2= 0xfc, - RSL_IE_IPAC_RTP_MPLEX = 0xfd, - RSL_IE_IPAC_RTP_MPLEX_ID= 0xfe, -}; - -/* Chapter 9.3.1 */ -#define RSL_CHAN_NR_MASK 0xf8 -#define RSL_CHAN_Bm_ACCHs 0x08 -#define RSL_CHAN_Lm_ACCHs 0x10 /* .. 0x18 */ -#define RSL_CHAN_SDCCH4_ACCH 0x20 /* .. 0x38 */ -#define RSL_CHAN_SDCCH8_ACCH 0x40 /* ...0x78 */ -#define RSL_CHAN_BCCH 0x80 -#define RSL_CHAN_RACH 0x88 -#define RSL_CHAN_PCH_AGCH 0x90 - -/* Chapter 9.3.3 */ -#define RSL_ACT_TYPE_INITIAL 0x00 -#define RSL_ACT_TYPE_REACT 0x80 -#define RSL_ACT_INTRA_IMM_ASS 0x00 -#define RSL_ACT_INTRA_NORM_ASS 0x01 -#define RSL_ACT_INTER_ASYNC 0x02 -#define RSL_ACT_INTER_SYNC 0x03 -#define RSL_ACT_SECOND_ADD 0x04 -#define RSL_ACT_SECOND_MULTI 0x05 - -/* Chapter 9.3.6 */ -struct rsl_ie_chan_mode { - uint8_t dtx_dtu; - uint8_t spd_ind; - uint8_t chan_rt; - uint8_t chan_rate; -} __attribute__ ((packed)); -#define RSL_CMOD_DTXu 0x01 /* uplink */ -#define RSL_CMOD_DTXd 0x02 /* downlink */ -enum rsl_cmod_spd { - RSL_CMOD_SPD_SPEECH = 0x01, - RSL_CMOD_SPD_DATA = 0x02, - RSL_CMOD_SPD_SIGN = 0x03, -}; -#define RSL_CMOD_CRT_SDCCH 0x01 -#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */ -#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */ -/* FIXME: More CRT types */ -/* Speech */ -#define RSL_CMOD_SP_GSM1 0x01 -#define RSL_CMOD_SP_GSM2 0x11 -#define RSL_CMOD_SP_GSM3 0x21 -/* Data */ -#define RSL_CMOD_SP_NT_14k5 0x58 -#define RSL_CMOD_SP_NT_12k0 0x50 -#define RSL_CMOD_SP_NT_6k0 0x51 - -/* Chapter 9.3.5 */ -struct rsl_ie_chan_ident { - /* GSM 04.08 10.5.2.5 */ - struct { - uint8_t iei; - uint8_t chan_nr; /* enc_chan_nr */ - uint8_t oct3; - uint8_t oct4; - } chan_desc; -#if 0 /* spec says we need this but Abissim doesn't use it */ - struct { - uint8_t tag; - uint8_t len; - } mobile_alloc; -#endif -} __attribute__ ((packed)); - -/* Chapter 9.3.22 */ -#define RLL_CAUSE_T200_EXPIRED 0x01 -#define RLL_CAUSE_REEST_REQ 0x02 -#define RLL_CAUSE_UNSOL_UA_RESP 0x03 -#define RLL_CAUSE_UNSOL_DM_RESP 0x04 -#define RLL_CAUSE_UNSOL_DM_RESP_MF 0x05 -#define RLL_CAUSE_UNSOL_SPRV_RESP 0x06 -#define RLL_CAUSE_SEQ_ERR 0x07 -#define RLL_CAUSE_UFRM_INC_PARAM 0x08 -#define RLL_CAUSE_SFRM_INC_PARAM 0x09 -#define RLL_CAUSE_IFRM_INC_MBITS 0x0a -#define RLL_CAUSE_IFRM_INC_LEN 0x0b -#define RLL_CAUSE_FRM_UNIMPL 0x0c -#define RLL_CAUSE_SABM_MF 0x0d -#define RLL_CAUSE_SABM_INFO_NOTALL 0x0e - -/* Chapter 9.3.26 */ -#define RSL_ERRCLS_NORMAL 0x00 -#define RSL_ERRCLS_RESOURCE_UNAVAIL 0x20 -#define RSL_ERRCLS_SERVICE_UNAVAIL 0x30 -#define RSL_ERRCLS_SERVICE_UNIMPL 0x40 -#define RSL_ERRCLS_INVAL_MSG 0x50 -#define RSL_ERRCLS_PROTO_ERROR 0x60 -#define RSL_ERRCLS_INTERWORKING 0x70 - -/* normal event */ -#define RSL_ERR_RADIO_IF_FAIL 0x00 -#define RSL_ERR_RADIO_LINK_FAIL 0x01 -#define RSL_ERR_HANDOVER_ACC_FAIL 0x02 -#define RSL_ERR_TALKER_ACC_FAIL 0x03 -#define RSL_ERR_OM_INTERVENTION 0x07 -#define RSL_ERR_NORMAL_UNSPEC 0x0f -#define RSL_ERR_T_MSRFPCI_EXP 0x18 -/* resource unavailable */ -#define RSL_ERR_EQUIPMENT_FAIL 0x20 -#define RSL_ERR_RR_UNAVAIL 0x21 -#define RSL_ERR_TERR_CH_FAIL 0x22 -#define RSL_ERR_CCCH_OVERLOAD 0x23 -#define RSL_ERR_ACCH_OVERLOAD 0x24 -#define RSL_ERR_PROCESSOR_OVERLOAD 0x25 -#define RSL_ERR_RES_UNAVAIL 0x2f -/* service or option not available */ -#define RSL_ERR_TRANSC_UNAVAIL 0x30 -#define RSL_ERR_SERV_OPT_UNAVAIL 0x3f -/* service or option not implemented */ -#define RSL_ERR_ENCR_UNIMPL 0x40 -#define RSL_ERR_SERV_OPT_UNIMPL 0x4f -/* invalid message */ -#define RSL_ERR_RCH_ALR_ACTV_ALLOC 0x50 -#define RSL_ERR_INVALID_MESSAGE 0x5f -/* protocol error */ -#define RSL_ERR_MSG_DISCR 0x60 -#define RSL_ERR_MSG_TYPE 0x61 -#define RSL_ERR_MSG_SEQ 0x62 -#define RSL_ERR_IE_ERROR 0x63 -#define RSL_ERR_MAND_IE_ERROR 0x64 -#define RSL_ERR_OPT_IE_ERROR 0x65 -#define RSL_ERR_IE_NONEXIST 0x66 -#define RSL_ERR_IE_LENGTH 0x67 -#define RSL_ERR_IE_CONTENT 0x68 -#define RSL_ERR_PROTO 0x6f -/* interworking */ -#define RSL_ERR_INTERWORKING 0x7f - -/* Chapter 9.3.30 */ -#define RSL_SYSTEM_INFO_8 0x00 -#define RSL_SYSTEM_INFO_1 0x01 -#define RSL_SYSTEM_INFO_2 0x02 -#define RSL_SYSTEM_INFO_3 0x03 -#define RSL_SYSTEM_INFO_4 0x04 -#define RSL_SYSTEM_INFO_5 0x05 -#define RSL_SYSTEM_INFO_6 0x06 -#define RSL_SYSTEM_INFO_7 0x07 -#define RSL_SYSTEM_INFO_16 0x08 -#define RSL_SYSTEM_INFO_17 0x09 -#define RSL_SYSTEM_INFO_2bis 0x0a -#define RSL_SYSTEM_INFO_2ter 0x0b -#define RSL_SYSTEM_INFO_5bis 0x0d -#define RSL_SYSTEM_INFO_5ter 0x0e -#define RSL_SYSTEM_INFO_10 0x0f -#define REL_EXT_MEAS_ORDER 0x47 -#define RSL_MEAS_INFO 0x48 -#define RSL_SYSTEM_INFO_13 0x28 -#define RSL_SYSTEM_INFO_2quater 0x29 -#define RSL_SYSTEM_INFO_9 0x2a -#define RSL_SYSTEM_INFO_18 0x2b -#define RSL_SYSTEM_INFO_19 0x2c -#define RSL_SYSTEM_INFO_20 0x2d - -/* Chapter 9.3.40 */ -#define RSL_CHANNEED_ANY 0x00 -#define RSL_CHANNEED_SDCCH 0x01 -#define RSL_CHANNEED_TCH_F 0x02 -#define RSL_CHANNEED_TCH_ForH 0x03 - -/* Chapter 9.3.45 */ -struct rsl_ie_cb_cmd_type { - uint8_t last_block:2; - uint8_t spare:1; - uint8_t def_bcast:1; - uint8_t command:4; -} __attribute__ ((packed)); -/* ->command */ -#define RSL_CB_CMD_TYPE_NORMAL 0x00 -#define RSL_CB_CMD_TYPE_SCHEDULE 0x08 -#define RSL_CB_CMD_TYPE_DEFAULT 0x0e -#define RSL_CB_CMD_TYPE_NULL 0x0f -/* ->def_bcast */ -#define RSL_CB_CMD_DEFBCAST_NORMAL 0 -#define RSL_CB_CMD_DEFBCAST_NULL 1 -/* ->last_block */ -#define RSL_CB_CMD_LASTBLOCK_4 0 -#define RSL_CB_CMD_LASTBLOCK_1 1 -#define RSL_CB_CMD_LASTBLOCK_2 2 -#define RSL_CB_CMD_LASTBLOCK_3 3 - -/* Chapter 3.3.2.3 Brocast control channel */ -/* CCCH-CONF, NC is not combined */ -#define RSL_BCCH_CCCH_CONF_1_NC 0x00 -#define RSL_BCCH_CCCH_CONF_1_C 0x01 -#define RSL_BCCH_CCCH_CONF_2_NC 0x02 -#define RSL_BCCH_CCCH_CONF_3_NC 0x04 -#define RSL_BCCH_CCCH_CONF_4_NC 0x06 - -/* BS-PA-MFRMS */ -#define RSL_BS_PA_MFRMS_2 0x00 -#define RSL_BS_PA_MFRMS_3 0x01 -#define RSL_BS_PA_MFRMS_4 0x02 -#define RSL_BS_PA_MFRMS_5 0x03 -#define RSL_BS_PA_MFRMS_6 0x04 -#define RSL_BS_PA_MFRMS_7 0x05 -#define RSL_BS_PA_MFRMS_8 0x06 -#define RSL_BS_PA_MFRMS_9 0x07 - -/* RSL_IE_IPAC_RTP_PAYLOAD[2] */ -enum rsl_ipac_rtp_payload { - RSL_IPAC_RTP_GSM = 1, - RSL_IPAC_RTP_EFR, - RSL_IPAC_RTP_AMR, - RSL_IPAC_RTP_CSD, - RSL_IPAC_RTP_MUX, -}; - -/* RSL_IE_IPAC_SPEECH_MODE, lower four bits */ -enum rsl_ipac_speech_mode_s { - RSL_IPAC_SPEECH_GSM_FR = 0, /* GSM FR (Type 1, FS) */ - RSL_IPAC_SPEECH_GSM_EFR = 1, /* GSM EFR (Type 2, FS) */ - RSL_IPAC_SPEECH_GSM_AMR_FR = 2, /* GSM AMR/FR (Type 3, FS) */ - RSL_IPAC_SPEECH_GSM_HR = 3, /* GSM HR (Type 1, HS) */ - RSL_IPAC_SPEECH_GSM_AMR_HR = 5, /* GSM AMR/hr (Type 3, HS) */ - RSL_IPAC_SPEECH_AS_RTP = 0xf, /* As specified by RTP Payload IE */ -}; -/* RSL_IE_IPAC_SPEECH_MODE, upper four bits */ -enum rsl_ipac_speech_mode_m { - RSL_IPAC_SPEECH_M_RXTX = 0, /* Send and Receive */ - RSL_IPAC_SPEECH_M_RX = 1, /* Receive only */ - RSL_IPAC_SPEECH_M_TX = 2, /* Send only */ -}; - -/* RSL_IE_IPAC_RTP_CSD_FMT, lower four bits */ -enum rsl_ipac_rtp_csd_format_d { - RSL_IPAC_RTP_CSD_EXT_TRAU = 0, - RSL_IPAC_RTP_CSD_NON_TRAU = 1, - RSL_IPAC_RTP_CSD_TRAU_BTS = 2, - RSL_IPAC_RTP_CSD_IWF_FREE = 3, -}; -/* RSL_IE_IPAC_RTP_CSD_FMT, upper four bits */ -enum rsl_ipac_rtp_csd_format_ir { - RSL_IPAC_RTP_CSD_IR_8k = 0, - RSL_IPAC_RTP_CSD_IR_16k = 1, - RSL_IPAC_RTP_CSD_IR_32k = 2, - RSL_IPAC_RTP_CSD_IR_64k = 3, -}; - -/* Siemens vendor-specific RSL extensions */ -struct rsl_mrpci { - uint8_t power_class:3, - vgcs_capable:1, - vbs_capable:1, - gsm_phase:2; -} __attribute__ ((packed)); - -enum rsl_mrpci_pwrclass { - RSL_MRPCI_PWRC_1 = 0, - RSL_MRPCI_PWRC_2 = 1, - RSL_MRPCI_PWRC_3 = 2, - RSL_MRPCI_PWRC_4 = 3, - RSL_MRPCI_PWRC_5 = 4, -}; -enum rsl_mrpci_phase { - RSL_MRPCI_PHASE_1 = 0, - /* reserved */ - RSL_MRPCI_PHASE_2 = 2, - RSL_MRPCI_PHASE_2PLUS = 3, -}; - - -#endif /* PROTO_GSM_08_58_H */ diff --git a/include/osmocore/protocol/gsm_12_21.h b/include/osmocore/protocol/gsm_12_21.h deleted file mode 100644 index 9cae45da..00000000 --- a/include/osmocore/protocol/gsm_12_21.h +++ /dev/null @@ -1,713 +0,0 @@ -#ifndef PROTO_GSM_12_21_H -#define PROTO_GSM_12_21_H - -/* GSM Network Management messages on the A-bis interface - * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */ - -/* (C) 2008-2009 by Harald Welte - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include -#include - -/* generic header in front of every OML message according to TS 08.59 */ -struct abis_om_hdr { - uint8_t mdisc; - uint8_t placement; - uint8_t sequence; - uint8_t length; - uint8_t data[0]; -} __attribute__ ((packed)); - -#define ABIS_OM_MDISC_FOM 0x80 -#define ABIS_OM_MDISC_MMI 0x40 -#define ABIS_OM_MDISC_TRAU 0x20 -#define ABIS_OM_MDISC_MANUF 0x10 -#define ABIS_OM_PLACEMENT_ONLY 0x80 -#define ABIS_OM_PLACEMENT_FIRST 0x40 -#define ABIS_OM_PLACEMENT_MIDDLE 0x20 -#define ABIS_OM_PLACEMENT_LAST 0x10 - -struct abis_om_obj_inst { - uint8_t bts_nr; - uint8_t trx_nr; - uint8_t ts_nr; -} __attribute__ ((packed)); - -struct abis_om_fom_hdr { - uint8_t msg_type; - uint8_t obj_class; - struct abis_om_obj_inst obj_inst; - uint8_t data[0]; -} __attribute__ ((packed)); - -#define ABIS_OM_FOM_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr)) - -/* Section 9.1: Message Types */ -enum abis_nm_msgtype { - /* SW Download Management Messages */ - NM_MT_LOAD_INIT = 0x01, - NM_MT_LOAD_INIT_ACK, - NM_MT_LOAD_INIT_NACK, - NM_MT_LOAD_SEG, - NM_MT_LOAD_SEG_ACK, - NM_MT_LOAD_ABORT, - NM_MT_LOAD_END, - NM_MT_LOAD_END_ACK, - NM_MT_LOAD_END_NACK, - NM_MT_SW_ACT_REQ, /* BTS->BSC */ - NM_MT_SW_ACT_REQ_ACK, - NM_MT_SW_ACT_REQ_NACK, - NM_MT_ACTIVATE_SW, /* BSC->BTS */ - NM_MT_ACTIVATE_SW_ACK, - NM_MT_ACTIVATE_SW_NACK, - NM_MT_SW_ACTIVATED_REP, /* 0x10 */ - /* A-bis Interface Management Messages */ - NM_MT_ESTABLISH_TEI = 0x21, - NM_MT_ESTABLISH_TEI_ACK, - NM_MT_ESTABLISH_TEI_NACK, - NM_MT_CONN_TERR_SIGN, - NM_MT_CONN_TERR_SIGN_ACK, - NM_MT_CONN_TERR_SIGN_NACK, - NM_MT_DISC_TERR_SIGN, - NM_MT_DISC_TERR_SIGN_ACK, - NM_MT_DISC_TERR_SIGN_NACK, - NM_MT_CONN_TERR_TRAF, - NM_MT_CONN_TERR_TRAF_ACK, - NM_MT_CONN_TERR_TRAF_NACK, - NM_MT_DISC_TERR_TRAF, - NM_MT_DISC_TERR_TRAF_ACK, - NM_MT_DISC_TERR_TRAF_NACK, - /* Transmission Management Messages */ - NM_MT_CONN_MDROP_LINK = 0x31, - NM_MT_CONN_MDROP_LINK_ACK, - NM_MT_CONN_MDROP_LINK_NACK, - NM_MT_DISC_MDROP_LINK, - NM_MT_DISC_MDROP_LINK_ACK, - NM_MT_DISC_MDROP_LINK_NACK, - /* Air Interface Management Messages */ - NM_MT_SET_BTS_ATTR = 0x41, - NM_MT_SET_BTS_ATTR_ACK, - NM_MT_SET_BTS_ATTR_NACK, - NM_MT_SET_RADIO_ATTR, - NM_MT_SET_RADIO_ATTR_ACK, - NM_MT_SET_RADIO_ATTR_NACK, - NM_MT_SET_CHAN_ATTR, - NM_MT_SET_CHAN_ATTR_ACK, - NM_MT_SET_CHAN_ATTR_NACK, - /* Test Management Messages */ - NM_MT_PERF_TEST = 0x51, - NM_MT_PERF_TEST_ACK, - NM_MT_PERF_TEST_NACK, - NM_MT_TEST_REP, - NM_MT_SEND_TEST_REP, - NM_MT_SEND_TEST_REP_ACK, - NM_MT_SEND_TEST_REP_NACK, - NM_MT_STOP_TEST, - NM_MT_STOP_TEST_ACK, - NM_MT_STOP_TEST_NACK, - /* State Management and Event Report Messages */ - NM_MT_STATECHG_EVENT_REP = 0x61, - NM_MT_FAILURE_EVENT_REP, - NM_MT_STOP_EVENT_REP, - NM_MT_STOP_EVENT_REP_ACK, - NM_MT_STOP_EVENT_REP_NACK, - NM_MT_REST_EVENT_REP, - NM_MT_REST_EVENT_REP_ACK, - NM_MT_REST_EVENT_REP_NACK, - NM_MT_CHG_ADM_STATE, - NM_MT_CHG_ADM_STATE_ACK, - NM_MT_CHG_ADM_STATE_NACK, - NM_MT_CHG_ADM_STATE_REQ, - NM_MT_CHG_ADM_STATE_REQ_ACK, - NM_MT_CHG_ADM_STATE_REQ_NACK, - NM_MT_REP_OUTST_ALARMS = 0x93, - NM_MT_REP_OUTST_ALARMS_ACK, - NM_MT_REP_OUTST_ALARMS_NACK, - /* Equipment Management Messages */ - NM_MT_CHANGEOVER = 0x71, - NM_MT_CHANGEOVER_ACK, - NM_MT_CHANGEOVER_NACK, - NM_MT_OPSTART, - NM_MT_OPSTART_ACK, - NM_MT_OPSTART_NACK, - NM_MT_REINIT, - NM_MT_REINIT_ACK, - NM_MT_REINIT_NACK, - NM_MT_SET_SITE_OUT, /* BS11: get alarm ?!? */ - NM_MT_SET_SITE_OUT_ACK, - NM_MT_SET_SITE_OUT_NACK, - NM_MT_CHG_HW_CONF = 0x90, - NM_MT_CHG_HW_CONF_ACK, - NM_MT_CHG_HW_CONF_NACK, - /* Measurement Management Messages */ - NM_MT_MEAS_RES_REQ = 0x8a, - NM_MT_MEAS_RES_RESP, - NM_MT_STOP_MEAS, - NM_MT_START_MEAS, - /* Other Messages */ - NM_MT_GET_ATTR = 0x81, - NM_MT_GET_ATTR_RESP, - NM_MT_GET_ATTR_NACK, - NM_MT_SET_ALARM_THRES, - NM_MT_SET_ALARM_THRES_ACK, - NM_MT_SET_ALARM_THRES_NACK, -}; - -enum abis_nm_msgtype_bs11 { - NM_MT_BS11_RESET_RESOURCE = 0x74, - - NM_MT_BS11_BEGIN_DB_TX = 0xa3, - NM_MT_BS11_BEGIN_DB_TX_ACK, - NM_MT_BS11_BEGIN_DB_TX_NACK, - NM_MT_BS11_END_DB_TX = 0xa6, - NM_MT_BS11_END_DB_TX_ACK, - NM_MT_BS11_END_DB_TX_NACK, - NM_MT_BS11_CREATE_OBJ = 0xa9, - NM_MT_BS11_CREATE_OBJ_ACK, - NM_MT_BS11_CREATE_OBJ_NACK, - NM_MT_BS11_DELETE_OBJ = 0xac, - NM_MT_BS11_DELETE_OBJ_ACK, - NM_MT_BS11_DELETE_OBJ_NACK, - - NM_MT_BS11_SET_ATTR = 0xd0, - NM_MT_BS11_SET_ATTR_ACK, - NM_MT_BS11_SET_ATTR_NACK, - NM_MT_BS11_LMT_SESSION = 0xdc, - - NM_MT_BS11_GET_STATE = 0xe3, - NM_MT_BS11_GET_STATE_ACK, - NM_MT_BS11_LMT_LOGON = 0xe5, - NM_MT_BS11_LMT_LOGON_ACK, - NM_MT_BS11_RESTART = 0xe7, - NM_MT_BS11_RESTART_ACK, - NM_MT_BS11_DISCONNECT = 0xe9, - NM_MT_BS11_DISCONNECT_ACK, - NM_MT_BS11_LMT_LOGOFF = 0xec, - NM_MT_BS11_LMT_LOGOFF_ACK, - NM_MT_BS11_RECONNECT = 0xf1, - NM_MT_BS11_RECONNECT_ACK, -}; - -enum abis_nm_msgtype_ipacc { - NM_MT_IPACC_RESTART = 0x87, - NM_MT_IPACC_RESTART_ACK, - NM_MT_IPACC_RESTART_NACK, - NM_MT_IPACC_RSL_CONNECT = 0xe0, - NM_MT_IPACC_RSL_CONNECT_ACK, - NM_MT_IPACC_RSL_CONNECT_NACK, - NM_MT_IPACC_RSL_DISCONNECT = 0xe3, - NM_MT_IPACC_RSL_DISCONNECT_ACK, - NM_MT_IPACC_RSL_DISCONNECT_NACK, - NM_MT_IPACC_CONN_TRAF = 0xe6, - NM_MT_IPACC_CONN_TRAF_ACK, - NM_MT_IPACC_CONN_TRAF_NACK, - NM_MT_IPACC_DEF_BOOT_SW = 0xec, - NM_MT_IPACC_DEF_BOOT_SW_ACK, - MN_MT_IPACC_DEF_BOOT_SW_NACK, - NM_MT_IPACC_SET_NVATTR = 0xef, - NM_MT_IPACC_SET_NVATTR_ACK, - NM_MT_IPACC_SET_NVATTR_NACK, - NM_MT_IPACC_GET_NVATTR = 0xf2, - NM_MT_IPACC_GET_NVATTR_ACK, - NM_MT_IPACC_GET_NVATTR_NACK, - NM_MT_IPACC_SET_ATTR = 0xf5, - NM_MT_IPACC_SET_ATTR_ACK, - NM_MT_IPACC_SET_ATTR_NACK, -}; - -enum abis_nm_bs11_cell_alloc { - NM_BS11_CANR_GSM = 0x00, - NM_BS11_CANR_DCS1800 = 0x01, -}; - -/* Section 9.2: Object Class */ -enum abis_nm_obj_class { - NM_OC_SITE_MANAGER = 0x00, - NM_OC_BTS, - NM_OC_RADIO_CARRIER, - NM_OC_CHANNEL, - NM_OC_BASEB_TRANSC, - /* RFU: 05-FE */ - - NM_OC_IPAC_E1_TRUNK = 0x0e, - NM_OC_IPAC_E1_PORT = 0x0f, - NM_OC_IPAC_E1_CHAN = 0x10, - NM_OC_IPAC_CLK_MODULE = 0x22, - - NM_OC_BS11_ADJC = 0xa0, - NM_OC_BS11_HANDOVER = 0xa1, - NM_OC_BS11_PWR_CTRL = 0xa2, - NM_OC_BS11_BTSE = 0xa3, /* LMT? */ - NM_OC_BS11_RACK = 0xa4, - NM_OC_BS11 = 0xa5, /* 01: ALCO */ - NM_OC_BS11_TEST = 0xa6, - NM_OC_BS11_ENVABTSE = 0xa8, - NM_OC_BS11_BPORT = 0xa9, - - NM_OC_GPRS_NSE = 0xf0, - NM_OC_GPRS_CELL = 0xf1, - NM_OC_GPRS_NSVC = 0xf2, - - NM_OC_NULL = 0xff, -}; - -/* Section 9.4: Attributes */ -enum abis_nm_attr { - NM_ATT_ABIS_CHANNEL = 0x01, - NM_ATT_ADD_INFO, - NM_ATT_ADD_TEXT, - NM_ATT_ADM_STATE, - NM_ATT_ARFCN_LIST, - NM_ATT_AUTON_REPORT, - NM_ATT_AVAIL_STATUS, - NM_ATT_BCCH_ARFCN, - NM_ATT_BSIC, - NM_ATT_BTS_AIR_TIMER, - NM_ATT_CCCH_L_I_P, - NM_ATT_CCCH_L_T, - NM_ATT_CHAN_COMB, - NM_ATT_CONN_FAIL_CRIT, - NM_ATT_DEST, - /* res */ - NM_ATT_EVENT_TYPE = 0x11, /* BS11: file data ?!? */ - NM_ATT_FILE_ID, - NM_ATT_FILE_VERSION, - NM_ATT_GSM_TIME, - NM_ATT_HSN, - NM_ATT_HW_CONFIG, - NM_ATT_HW_DESC, - NM_ATT_INTAVE_PARAM, - NM_ATT_INTERF_BOUND, - NM_ATT_LIST_REQ_ATTR, - NM_ATT_MAIO, - NM_ATT_MANUF_STATE, - NM_ATT_MANUF_THRESH, - NM_ATT_MANUF_ID, - NM_ATT_MAX_TA, - NM_ATT_MDROP_LINK, /* 0x20 */ - NM_ATT_MDROP_NEXT, - NM_ATT_NACK_CAUSES, - NM_ATT_NY1, - NM_ATT_OPER_STATE, - NM_ATT_OVERL_PERIOD, - NM_ATT_PHYS_CONF, - NM_ATT_POWER_CLASS, - NM_ATT_POWER_THRESH, - NM_ATT_PROB_CAUSE, - NM_ATT_RACH_B_THRESH, - NM_ATT_LDAVG_SLOTS, - NM_ATT_RAD_SUBC, - NM_ATT_RF_MAXPOWR_R, - NM_ATT_SITE_INPUTS, - NM_ATT_SITE_OUTPUTS, - NM_ATT_SOURCE, /* 0x30 */ - NM_ATT_SPEC_PROB, - NM_ATT_START_TIME, - NM_ATT_T200, - NM_ATT_TEI, - NM_ATT_TEST_DUR, - NM_ATT_TEST_NO, - NM_ATT_TEST_REPORT, - NM_ATT_VSWR_THRESH, - NM_ATT_WINDOW_SIZE, - /* Res */ - NM_ATT_BS11_RSSI_OFFS = 0x3d, - NM_ATT_BS11_TXPWR = 0x3e, - NM_ATT_BS11_DIVERSITY = 0x3f, - /* Res */ - NM_ATT_TSC = 0x40, - NM_ATT_SW_CONFIG, - NM_ATT_SW_DESCR, - NM_ATT_SEVERITY, - NM_ATT_GET_ARI, - NM_ATT_HW_CONF_CHG, - NM_ATT_OUTST_ALARM, - NM_ATT_FILE_DATA, - NM_ATT_MEAS_RES, - NM_ATT_MEAS_TYPE, - - NM_ATT_BS11_ESN_FW_CODE_NO = 0x4c, - NM_ATT_BS11_ESN_HW_CODE_NO = 0x4f, - - NM_ATT_BS11_ESN_PCB_SERIAL = 0x55, - NM_ATT_BS11_EXCESSIVE_DISTANCE = 0x58, - - NM_ATT_BS11_ALL_TEST_CATG = 0x60, - NM_ATT_BS11_BTSLS_HOPPING, - NM_ATT_BS11_CELL_ALLOC_NR, - NM_ATT_BS11_CELL_GLOBAL_ID, - NM_ATT_BS11_ENA_INTERF_CLASS = 0x66, - NM_ATT_BS11_ENA_INT_INTEC_HANDO = 0x67, - NM_ATT_BS11_ENA_INT_INTRC_HANDO = 0x68, - NM_ATT_BS11_ENA_MS_PWR_CTRL = 0x69, - NM_ATT_BS11_ENA_PWR_BDGT_HO = 0x6a, - NM_ATT_BS11_ENA_PWR_CTRL_RLFW = 0x6b, - NM_ATT_BS11_ENA_RXLEV_HO = 0x6c, - NM_ATT_BS11_ENA_RXQUAL_HO = 0x6d, - NM_ATT_BS11_FACCH_QUAL = 0x6e, - - NM_ATT_IPACC_DST_IP = 0x80, - NM_ATT_IPACC_DST_IP_PORT = 0x81, - NM_ATT_IPACC_SSRC = 0x82, - NM_ATT_IPACC_RTP_PAYLD_TYPE = 0x83, - NM_ATT_IPACC_BASEB_ID = 0x84, - NM_ATT_IPACC_STREAM_ID = 0x85, - NM_ATT_IPACC_NV_FLAGS = 0x86, - NM_ATT_IPACC_FREQ_CTRL = 0x87, - NM_ATT_IPACC_PRIM_OML_CFG = 0x88, - NM_ATT_IPACC_SEC_OML_CFG = 0x89, - NM_ATT_IPACC_IP_IF_CFG = 0x8a, /* IP interface */ - NM_ATT_IPACC_IP_GW_CFG = 0x8b, /* IP gateway */ - NM_ATT_IPACC_IN_SERV_TIME = 0x8c, - NM_ATT_IPACC_TRX_BTS_ASS = 0x8d, - NM_ATT_IPACC_LOCATION = 0x8e, /* string describing location */ - NM_ATT_IPACC_PAGING_CFG = 0x8f, - NM_ATT_IPACC_FILE_DATA = 0x90, - NM_ATT_IPACC_UNIT_ID = 0x91, /* Site/BTS/TRX */ - NM_ATT_IPACC_PARENT_UNIT_ID = 0x92, - NM_ATT_IPACC_UNIT_NAME = 0x93, /* default: nbts- */ - NM_ATT_IPACC_SNMP_CFG = 0x94, - NM_ATT_IPACC_PRIM_OML_CFG_LIST = 0x95, - NM_ATT_IPACC_PRIM_OML_FB_TOUT = 0x96, - NM_ATT_IPACC_CUR_SW_CFG = 0x97, - NM_ATT_IPACC_TIMING_BUS = 0x98, - NM_ATT_IPACC_CGI = 0x99, - NM_ATT_IPACC_RAC = 0x9a, - NM_ATT_IPACC_OBJ_VERSION = 0x9b, - NM_ATT_IPACC_GPRS_PAGING_CFG = 0x9c, - NM_ATT_IPACC_NSEI = 0x9d, - NM_ATT_IPACC_BVCI = 0x9e, - NM_ATT_IPACC_NSVCI = 0x9f, - NM_ATT_IPACC_NS_CFG = 0xa0, - NM_ATT_IPACC_BSSGP_CFG = 0xa1, - NM_ATT_IPACC_NS_LINK_CFG = 0xa2, - NM_ATT_IPACC_RLC_CFG = 0xa3, - NM_ATT_IPACC_ALM_THRESH_LIST = 0xa4, - NM_ATT_IPACC_MONIT_VAL_LIST = 0xa5, - NM_ATT_IPACC_TIB_CONTROL = 0xa6, - NM_ATT_IPACC_SUPP_FEATURES = 0xa7, - NM_ATT_IPACC_CODING_SCHEMES = 0xa8, - NM_ATT_IPACC_RLC_CFG_2 = 0xa9, - NM_ATT_IPACC_HEARTB_TOUT = 0xaa, - NM_ATT_IPACC_UPTIME = 0xab, - NM_ATT_IPACC_RLC_CFG_3 = 0xac, - NM_ATT_IPACC_SSL_CFG = 0xad, - NM_ATT_IPACC_SEC_POSSIBLE = 0xae, - NM_ATT_IPACC_IML_SSL_STATE = 0xaf, - NM_ATT_IPACC_REVOC_DATE = 0xb0, - - - NM_ATT_BS11_RF_RES_IND_PER = 0x8f, - - NM_ATT_BS11_RX_LEV_MIN_CELL = 0x90, - NM_ATT_BS11_ABIS_EXT_TIME = 0x91, - NM_ATT_BS11_TIMER_HO_REQUEST = 0x92, - NM_ATT_BS11_TIMER_NCELL = 0x93, - NM_ATT_BS11_TSYNC = 0x94, - NM_ATT_BS11_TTRAU = 0x95, - NM_ATT_BS11_EMRG_CFG_MEMBER = 0x9b, - NM_ATT_BS11_TRX_AREA = 0x9f, - - NM_ATT_BS11_BCCH_RECONF = 0xd7, - NM_ATT_BS11_BIT_ERR_THESH = 0xa0, - NM_ATT_BS11_BOOT_SW_VERS = 0xa1, - NM_ATT_BS11_CCLK_ACCURACY = 0xa3, - NM_ATT_BS11_CCLK_TYPE = 0xa4, - NM_ATT_BS11_INP_IMPEDANCE = 0xaa, - NM_ATT_BS11_L1_PROT_TYPE = 0xab, - NM_ATT_BS11_LINE_CFG = 0xac, - NM_ATT_BS11_LI_PORT_1 = 0xad, - NM_ATT_BS11_LI_PORT_2 = 0xae, - - NM_ATT_BS11_L1_REM_ALM_TYPE = 0xb0, - NM_ATT_BS11_SW_LOAD_INTENDED = 0xbb, - NM_ATT_BS11_SW_LOAD_SAFETY = 0xbc, - NM_ATT_BS11_SW_LOAD_STORED = 0xbd, - - NM_ATT_BS11_VENDOR_NAME = 0xc1, - NM_ATT_BS11_HOPPING_MODE = 0xc5, - NM_ATT_BS11_LMT_LOGON_SESSION = 0xc6, - NM_ATT_BS11_LMT_LOGIN_TIME = 0xc7, - NM_ATT_BS11_LMT_USER_ACC_LEV = 0xc8, - NM_ATT_BS11_LMT_USER_NAME = 0xc9, - - NM_ATT_BS11_L1_CONTROL_TS = 0xd8, - NM_ATT_BS11_RADIO_MEAS_GRAN = 0xdc, /* in SACCH multiframes */ - NM_ATT_BS11_RADIO_MEAS_REP = 0xdd, - - NM_ATT_BS11_SH_LAPD_INT_TIMER = 0xe8, - - NM_ATT_BS11_BTS_STATE = 0xf0, - NM_ATT_BS11_E1_STATE = 0xf1, - NM_ATT_BS11_PLL = 0xf2, - NM_ATT_BS11_RX_OFFSET = 0xf3, - NM_ATT_BS11_ANT_TYPE = 0xf4, - NM_ATT_BS11_PLL_MODE = 0xfc, - NM_ATT_BS11_PASSWORD = 0xfd, -}; -#define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE - -/* Section 9.4.4: Administrative State */ -enum abis_nm_adm_state { - NM_STATE_LOCKED = 0x01, - NM_STATE_UNLOCKED = 0x02, - NM_STATE_SHUTDOWN = 0x03, - NM_STATE_NULL = 0xff, -}; - -/* Section 9.4.7: Administrative State */ -enum abis_nm_avail_state { - NM_AVSTATE_IN_TEST = 1, - NM_AVSTATE_POWER_OFF = 2, - NM_AVSTATE_OFF_LINE = 3, - NM_AVSTATE_DEPENDENCY = 5, - NM_AVSTATE_DEGRADED = 6, - NM_AVSTATE_NOT_INSTALLED= 7, - NM_AVSTATE_OK = 0xff, -}; - -enum abis_nm_op_state { - NM_OPSTATE_DISABLED = 1, - NM_OPSTATE_ENABLED = 2, - NM_OPSTATE_NULL = 0xff, -}; - -/* Section 9.4.13: Channel Combination */ -enum abis_nm_chan_comb { - NM_CHANC_TCHFull = 0x00, /* TCH/F + TCH/H + SACCH/TF */ - NM_CHANC_TCHHalf = 0x01, /* TCH/H(0,1) + FACCH/H(0,1) + - SACCH/TH(0,1) */ - NM_CHANC_TCHHalf2 = 0x02, /* TCH/H(0) + FACCH/H(0) + SACCH/TH(0) + - TCH/H(1) */ - NM_CHANC_SDCCH = 0x03, /* SDCCH/8 + SACCH/8 */ - NM_CHANC_mainBCCH = 0x04, /* FCCH + SCH + BCCH + CCCH */ - NM_CHANC_BCCHComb = 0x05, /* FCCH + SCH + BCCH + CCCH + SDCCH/4 + - SACCH/C4 */ - NM_CHANC_BCCH = 0x06, /* BCCH + CCCH */ - NM_CHANC_BCCH_CBCH = 0x07, /* CHANC_BCCHComb + CBCH */ - NM_CHANC_SDCCH_CBCH = 0x08, /* CHANC_SDCCH8 + CBCH */ - /* ip.access */ - NM_CHANC_IPAC_bPDCH = 0x0b, /* PBCCH + PCCCH + PDTCH/F + PACCH/F + - PTCCH/F */ - NM_CHANC_IPAC_cPDCH = 0x0c, /* PBCCH + PDTCH/F + PACCH/F + PTCCH/F */ - NM_CHANC_IPAC_PDCH = 0x0d, /* PDTCH/F + PACCH/F + PTCCH/F */ - NM_CHANC_IPAC_TCHFull_PDCH = 0x80, - NM_CHANC_IPAC_TCHFull_TCHHalf = 0x81, -}; - -/* Section 9.4.16: Event Type */ -enum abis_nm_event_type { - NM_EVT_COMM_FAIL = 0x00, - NM_EVT_QOS_FAIL = 0x01, - NM_EVT_PROC_FAIL = 0x02, - NM_EVT_EQUIP_FAIL = 0x03, - NM_EVT_ENV_FAIL = 0x04, -}; - -/* Section: 9.4.63: Perceived Severity */ -enum abis_nm_severity { - NM_SEVER_CEASED = 0x00, - NM_SEVER_CRITICAL = 0x01, - NM_SEVER_MAJOR = 0x02, - NM_SEVER_MINOR = 0x03, - NM_SEVER_WARNING = 0x04, - NM_SEVER_INDETERMINATE = 0x05, -}; - -/* Section 9.4.43: Probable Cause Type */ -enum abis_nm_pcause_type { - NM_PCAUSE_T_X721 = 0x01, - NM_PCAUSE_T_GSM = 0x02, - NM_PCAUSE_T_MANUF = 0x03, -}; - -/* Section 9.4.36: NACK Causes */ -enum abis_nm_nack_cause { - /* General Nack Causes */ - NM_NACK_INCORR_STRUCT = 0x01, - NM_NACK_MSGTYPE_INVAL = 0x02, - NM_NACK_OBJCLASS_INVAL = 0x05, - NM_NACK_OBJCLASS_NOTSUPP = 0x06, - NM_NACK_BTSNR_UNKN = 0x07, - NM_NACK_TRXNR_UNKN = 0x08, - NM_NACK_OBJINST_UNKN = 0x09, - NM_NACK_ATTRID_INVAL = 0x0c, - NM_NACK_ATTRID_NOTSUPP = 0x0d, - NM_NACK_PARAM_RANGE = 0x0e, - NM_NACK_ATTRLIST_INCONSISTENT = 0x0f, - NM_NACK_SPEC_IMPL_NOTSUPP = 0x10, - NM_NACK_CANT_PERFORM = 0x11, - /* Specific Nack Causes */ - NM_NACK_RES_NOTIMPL = 0x19, - NM_NACK_RES_NOTAVAIL = 0x1a, - NM_NACK_FREQ_NOTAVAIL = 0x1b, - NM_NACK_TEST_NOTSUPP = 0x1c, - NM_NACK_CAPACITY_RESTR = 0x1d, - NM_NACK_PHYSCFG_NOTPERFORM = 0x1e, - NM_NACK_TEST_NOTINIT = 0x1f, - NM_NACK_PHYSCFG_NOTRESTORE = 0x20, - NM_NACK_TEST_NOSUCH = 0x21, - NM_NACK_TEST_NOSTOP = 0x22, - NM_NACK_MSGINCONSIST_PHYSCFG = 0x23, - NM_NACK_FILE_INCOMPLETE = 0x25, - NM_NACK_FILE_NOTAVAIL = 0x26, - NM_NACK_FILE_NOTACTIVATE = 0x27, - NM_NACK_REQ_NOT_GRANT = 0x28, - NM_NACK_WAIT = 0x29, - NM_NACK_NOTH_REPORT_EXIST = 0x2a, - NM_NACK_MEAS_NOTSUPP = 0x2b, - NM_NACK_MEAS_NOTSTART = 0x2c, -}; - -/* Section 9.4.1 */ -struct abis_nm_channel { - uint8_t attrib; - uint8_t bts_port; - uint8_t timeslot; - uint8_t subslot; -} __attribute__ ((packed)); - -/* Siemens BS-11 specific objects in the SienemsHW (0xA5) object class */ -enum abis_bs11_objtype { - BS11_OBJ_ALCO = 0x01, - BS11_OBJ_BBSIG = 0x02, /* obj_class: 0,1 */ - BS11_OBJ_TRX1 = 0x03, /* only DEACTIVATE TRX1 */ - BS11_OBJ_CCLK = 0x04, - BS11_OBJ_GPSU = 0x06, - BS11_OBJ_LI = 0x07, - BS11_OBJ_PA = 0x09, /* obj_class: 0, 1*/ -}; - -enum abis_bs11_trx_power { - BS11_TRX_POWER_GSM_2W = 0x06, - BS11_TRX_POWER_GSM_250mW= 0x07, - BS11_TRX_POWER_GSM_80mW = 0x08, - BS11_TRX_POWER_GSM_30mW = 0x09, - BS11_TRX_POWER_DCS_3W = 0x0a, - BS11_TRX_POWER_DCS_1W6 = 0x0b, - BS11_TRX_POWER_DCS_500mW= 0x0c, - BS11_TRX_POWER_DCS_160mW= 0x0d, -}; - -enum abis_bs11_li_pll_mode { - BS11_LI_PLL_LOCKED = 2, - BS11_LI_PLL_STANDALONE = 3, -}; - -enum abis_bs11_line_cfg { - BS11_LINE_CFG_STAR = 0x00, - BS11_LINE_CFG_MULTIDROP = 0x01, - BS11_LINE_CFG_LOOP = 0x02, -}; - -enum abis_bs11_phase { - BS11_STATE_SOFTWARE_RQD = 0x01, - BS11_STATE_LOAD_SMU_INTENDED = 0x11, - BS11_STATE_LOAD_SMU_SAFETY = 0x21, - BS11_STATE_LOAD_FAILED = 0x31, - BS11_STATE_LOAD_DIAGNOSTIC = 0x41, - BS11_STATE_WARM_UP = 0x51, - BS11_STATE_WARM_UP_2 = 0x52, - BS11_STATE_WAIT_MIN_CFG = 0x62, - BS11_STATE_MAINTENANCE = 0x72, - BS11_STATE_LOAD_MBCCU = 0x92, - BS11_STATE_WAIT_MIN_CFG_2 = 0xA2, - BS11_STATE_NORMAL = 0x03, - BS11_STATE_ABIS_LOAD = 0x13, -}; - -enum abis_nm_ipacc_test_no { - NM_IPACC_TESTNO_RLOOP_ANT = 0x01, - NM_IPACC_TESTNO_RLOOP_XCVR = 0x02, - NM_IPACC_TESTNO_FUNC_OBJ = 0x03, - NM_IPACC_TESTNO_CHAN_USAGE = 0x40, - NM_IPACC_TESTNO_BCCH_CHAN_USAGE = 0x41, - NM_IPACC_TESTNO_FREQ_SYNC = 0x42, - NM_IPACC_TESTNO_BCCH_INFO = 0x43, - NM_IPACC_TESTNO_TX_BEACON = 0x44, - NM_IPACC_TESTNO_SYSINFO_MONITOR = 0x45, - NM_IPACC_TESTNO_BCCCH_MONITOR = 0x46, -}; - -/* first byte after length inside NM_ATT_TEST_REPORT */ -enum abis_nm_ipacc_test_res { - NM_IPACC_TESTRES_SUCCESS = 0, - NM_IPACC_TESTRES_TIMEOUT = 1, - NM_IPACC_TESTRES_NO_CHANS = 2, - NM_IPACC_TESTRES_PARTIAL = 3, - NM_IPACC_TESTRES_STOPPED = 4, -}; - -/* internal IE inside NM_ATT_TEST_REPORT */ -enum abis_nm_ipacc_testres_ie { - NM_IPACC_TR_IE_FREQ_ERR_LIST = 3, - NM_IPACC_TR_IE_CHAN_USAGE = 4, - NM_IPACC_TR_IE_BCCH_INFO = 6, - NM_IPACC_TR_IE_RESULT_DETAILS = 8, - NM_IPACC_TR_IE_FREQ_ERR = 18, -}; - -enum ipac_eie { - NM_IPAC_EIE_ARFCN_WHITE = 0x01, - NM_IPAC_EIE_ARFCH_BLACK = 0x02, - NM_IPAC_EIE_FREQ_ERR_LIST = 0x03, - NM_IPAC_EIE_CHAN_USE_LIST = 0x04, - NM_IPAC_EIE_BCCH_INFO_TYPE = 0x05, - NM_IPAC_EIE_BCCH_INFO = 0x06, - NM_IPAC_EIE_CONFIG = 0x07, - NM_IPAC_EIE_RES_DETAILS = 0x08, - NM_IPAC_EIE_RXLEV_THRESH = 0x09, - NM_IPAC_EIE_FREQ_SYNC_OPTS = 0x0a, - NM_IPAC_EIE_MAC_ADDR = 0x0b, - NM_IPAC_EIE_HW_SW_COMPAT_NR = 0x0c, - NM_IPAC_EIE_MANUF_SER_NR = 0x0d, - NM_IPAC_EIE_OEM_ID = 0x0e, - NM_IPAC_EIE_DATE_TIME_MANUF = 0x0f, - NM_IPAC_EIE_DATE_TIME_CALIB = 0x10, - NM_IPAC_EIE_BEACON_INFO = 0x11, - NM_IPAC_EIE_FREQ_ERR = 0x12, - /* FIXME */ - NM_IPAC_EIE_FREQ_BANDS = 0x1c, - NM_IPAC_EIE_MAX_TA = 0x1d, - NM_IPAC_EIE_CIPH_ALGOS = 0x1e, - NM_IPAC_EIE_CHAN_TYPES = 0x1f, - NM_IPAC_EIE_CHAN_MODES = 0x20, - NM_IPAC_EIE_GPRS_CODING = 0x21, - NM_IPAC_EIE_RTP_FEATURES = 0x22, - NM_IPAC_EIE_RSL_FEATURES = 0x23, - NM_IPAC_EIE_BTS_HW_CLASS = 0x24, - NM_IPAC_EIE_BTS_ID = 0x25, -}; - -enum ipac_bcch_info_type { - IPAC_BINF_RXLEV = (1 << 8), - IPAC_BINF_RXQUAL = (1 << 9), - IPAC_BINF_FREQ_ERR_QUAL = (1 << 10), - IPAC_BINF_FRAME_OFFSET = (1 << 11), - IPAC_BINF_FRAME_NR_OFFSET = (1 << 12), - IPAC_BINF_BSIC = (1 << 13), - IPAC_BINF_CGI = (1 << 14), - IPAC_BINF_NEIGH_BA_SI2 = (1 << 15), - IPAC_BINF_NEIGH_BA_SI2bis = (1 << 0), - IPAC_BINF_NEIGH_BA_SI2ter = (1 << 1), - IPAC_BINF_CELL_ALLOC = (1 << 2), -}; - -#endif /* PROTO_GSM_12_21_H */ diff --git a/include/osmocore/rate_ctr.h b/include/osmocore/rate_ctr.h deleted file mode 100644 index f887d9a7..00000000 --- a/include/osmocore/rate_ctr.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef _RATE_CTR_H -#define _RATE_CTR_H - -#include - -#include - -#define RATE_CTR_INTV_NUM 4 - -enum rate_ctr_intv { - RATE_CTR_INTV_SEC, - RATE_CTR_INTV_MIN, - RATE_CTR_INTV_HOUR, - RATE_CTR_INTV_DAY, -}; - -/* for each of the intervals, we keep the following values */ -struct rate_ctr_per_intv { - uint64_t last; - uint64_t rate; -}; - -/* for each actual value, we keep the following data */ -struct rate_ctr { - uint64_t current; - struct rate_ctr_per_intv intv[RATE_CTR_INTV_NUM]; -}; - -struct rate_ctr_desc { - const char *name; - const char *description; -}; - -/* Describe a counter group class */ -struct rate_ctr_group_desc { - /* The prefix to the name of all counters in this group */ - const char *group_name_prefix; - /* The human-readable description of the group */ - const char *group_description; - /* The number of counters in this group */ - const unsigned int num_ctr; - /* Pointer to array of counter names */ - const struct rate_ctr_desc *ctr_desc; -}; - -/* One instance of a counter group class */ -struct rate_ctr_group { - /* Linked list of all counter groups in the system */ - struct llist_head list; - /* Pointer to the counter group class */ - const struct rate_ctr_group_desc *desc; - /* The index of this ctr_group within its class */ - unsigned int idx; - /* Actual counter structures below */ - struct rate_ctr ctr[0]; -}; - -/* Allocate a new group of counters according to description */ -struct rate_ctr_group *rate_ctr_group_alloc(void *ctx, - const struct rate_ctr_group_desc *desc, - unsigned int idx); - -/* Free the memory for the specified group of counters */ -void rate_ctr_group_free(struct rate_ctr_group *grp); - -/* Add a number to the counter */ -void rate_ctr_add(struct rate_ctr *ctr, int inc); - -/* Increment the counter by 1 */ -static inline void rate_ctr_inc(struct rate_ctr *ctr) -{ - rate_ctr_add(ctr, 1); -} - -/* Initialize the counter module */ -int rate_ctr_init(void *tall_ctx); - -struct vty; -void vty_out_rate_ctr_group(struct vty *vty, const char *prefix, - struct rate_ctr_group *ctrg); -#endif /* RATE_CTR_H */ diff --git a/include/osmocore/rsl.h b/include/osmocore/rsl.h deleted file mode 100644 index 54d67032..00000000 --- a/include/osmocore/rsl.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _OSMOCORE_RSL_H -#define _OSMOCORE_RSL_H - -#include -#include -#include - -void rsl_init_rll_hdr(struct abis_rsl_rll_hdr *dh, uint8_t msg_type); - -void rsl_init_cchan_hdr(struct abis_rsl_cchan_hdr *ch, uint8_t msg_type); - -extern const struct tlv_definition rsl_att_tlvdef; -#define rsl_tlv_parse(dec, buf, len) \ - tlv_parse(dec, &rsl_att_tlvdef, buf, len, 0, 0) - -/* encode channel number as per Section 9.3.1 */ -uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot); -/* decode channel number as per Section 9.3.1 */ -int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot); -/* Turns channel number into a string */ -const char *rsl_chan_nr_str(uint8_t chan_nr); - - -const char *rsl_err_name(uint8_t err); -const char *rsl_rlm_cause_name(uint8_t err); - -/* Section 3.3.2.3 TS 05.02. I think this looks like a table */ -int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf); - -/* Push a RSL RLL header */ -void rsl_rll_push_hdr(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr, - uint8_t link_id, int transparent); - -/* Push a RSL RLL header with L3_INFO IE */ -void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr, - uint8_t link_id, int transparent); - -/* Allocate msgb and fill with simple RSL RLL header */ -struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr, - uint8_t link_id, int transparent); -#endif /* _OSMOCORE_RSL_H */ diff --git a/include/osmocore/rxlev_stat.h b/include/osmocore/rxlev_stat.h deleted file mode 100644 index 415509dc..00000000 --- a/include/osmocore/rxlev_stat.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _OSMOCORE_RXLEV_STATS_H -#define _OSMOCORE_RXLEV_STATS_H - -#define NUM_RXLEVS 32 -#define NUM_ARFCNS 1024 - -struct rxlev_stats { - /* the maximum number of ARFCN's is 1024, and there are 32 RxLevels, - * so in we keep one 1024bit-bitvec for each RxLev */ - uint8_t rxlev_buckets[NUM_RXLEVS][NUM_ARFCNS/8]; -}; - -void rxlev_stat_input(struct rxlev_stats *st, uint16_t arfcn, uint8_t rxlev); - -/* get the next ARFCN that has the specified Rxlev */ -int16_t rxlev_stat_get_next(const struct rxlev_stats *st, uint8_t rxlev, int16_t arfcn); - -void rxlev_stat_reset(struct rxlev_stats *st); - -void rxlev_stat_dump(const struct rxlev_stats *st); - -#endif /* _OSMOCORE_RXLEV_STATS_H */ diff --git a/include/osmocore/select.h b/include/osmocore/select.h deleted file mode 100644 index 2d8b3ec0..00000000 --- a/include/osmocore/select.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _BSC_SELECT_H -#define _BSC_SELECT_H - -#include "linuxlist.h" - -#define BSC_FD_READ 0x0001 -#define BSC_FD_WRITE 0x0002 -#define BSC_FD_EXCEPT 0x0004 - -struct bsc_fd { - struct llist_head list; - int fd; - unsigned int when; - int (*cb)(struct bsc_fd *fd, unsigned int what); - void *data; - unsigned int priv_nr; -}; - -int bsc_register_fd(struct bsc_fd *fd); -void bsc_unregister_fd(struct bsc_fd *fd); -int bsc_select_main(int polling); -#endif /* _BSC_SELECT_H */ diff --git a/include/osmocore/signal.h b/include/osmocore/signal.h deleted file mode 100644 index 02d83d2e..00000000 --- a/include/osmocore/signal.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef OSMOCORE_SIGNAL_H -#define OSMOCORE_SIGNAL_H - -typedef int signal_cbfn(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data); - - -/* Management */ -int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data); -void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data); - -/* Dispatch */ -void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data); - -#endif /* OSMOCORE_SIGNAL_H */ diff --git a/include/osmocore/statistics.h b/include/osmocore/statistics.h deleted file mode 100644 index 1d56054a..00000000 --- a/include/osmocore/statistics.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _STATISTICS_H -#define _STATISTICS_H - -struct counter { - struct llist_head list; - const char *name; - const char *description; - unsigned long value; -}; - -static inline void counter_inc(struct counter *ctr) -{ - ctr->value++; -} - -static inline unsigned long counter_get(struct counter *ctr) -{ - return ctr->value; -} - -static inline void counter_reset(struct counter *ctr) -{ - ctr->value = 0; -} - -struct counter *counter_alloc(const char *name); -void counter_free(struct counter *ctr); - -int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data); - -#endif /* _STATISTICS_H */ diff --git a/include/osmocore/talloc.h b/include/osmocore/talloc.h deleted file mode 100644 index f7f7643b..00000000 --- a/include/osmocore/talloc.h +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef _TALLOC_H_ -#define _TALLOC_H_ -/* - Unix SMB/CIFS implementation. - Samba temporary memory allocation functions - - Copyright (C) Andrew Tridgell 2004-2005 - Copyright (C) Stefan Metzmacher 2006 - - ** NOTE! The following LGPL license applies to the talloc - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see . -*/ - -#include -#include -#include - -#define HAVE_VA_COPY - -/* this is only needed for compatibility with the old talloc */ -typedef void TALLOC_CTX; - -/* - this uses a little trick to allow __LINE__ to be stringified -*/ -#ifndef __location__ -#define __TALLOC_STRING_LINE1__(s) #s -#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s) -#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__) -#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__ -#endif - -#ifndef TALLOC_DEPRECATED -#define TALLOC_DEPRECATED 0 -#endif - -#ifndef PRINTF_ATTRIBUTE -#if (__GNUC__ >= 3) -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif - -/* try to make talloc_set_destructor() and talloc_steal() type safe, - if we have a recent gcc */ -#if (__GNUC__ >= 3) -#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) -#define talloc_set_destructor(ptr, function) \ - do { \ - int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ - _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ - } while(0) -/* this extremely strange macro is to avoid some braindamaged warning - stupidity in gcc 4.1.x */ -#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; }) -#else -#define talloc_set_destructor(ptr, function) \ - _talloc_set_destructor((ptr), (int (*)(void *))(function)) -#define _TALLOC_TYPEOF(ptr) void * -#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)) -#endif - -#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) -#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr)) - -/* useful macros for creating type checked pointers */ -#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) -#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) -#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) - -#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) - -#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) -#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) - -#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) -#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) -#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) -#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) -#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) - -#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) -#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) - -#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) - -#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) -#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) -#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) - -#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) - -#if TALLOC_DEPRECATED -#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) -#define talloc_p(ctx, type) talloc(ctx, type) -#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) -#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) -#define talloc_destroy(ctx) talloc_free(ctx) -#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a)) -#endif - -#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) - -/* The following definitions come from talloc.c */ -void *_talloc(const void *context, size_t size); -void *talloc_pool(const void *context, size_t size); -void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); -int talloc_increase_ref_count(const void *ptr); -size_t talloc_reference_count(const void *ptr); -void *_talloc_reference(const void *context, const void *ptr); -int talloc_unlink(const void *context, void *ptr); -const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -void talloc_set_name_const(const void *ptr, const char *name); -void *talloc_named(const void *context, size_t size, - const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -void *talloc_named_const(const void *context, size_t size, const char *name); -const char *talloc_get_name(const void *ptr); -void *talloc_check_name(const void *ptr, const char *name); -void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); -void *talloc_parent(const void *ptr); -const char *talloc_parent_name(const void *ptr); -void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); -int talloc_free(void *ptr); -void talloc_free_children(void *ptr); -void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); -void *_talloc_steal(const void *new_ctx, const void *ptr); -void *_talloc_move(const void *new_ctx, const void *pptr); -size_t talloc_total_size(const void *ptr); -size_t talloc_total_blocks(const void *ptr); -void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, - void (*callback)(const void *ptr, - int depth, int max_depth, - int is_ref, - void *private_data), - void *private_data); -void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); -void talloc_report_full(const void *ptr, FILE *f); -void talloc_report(const void *ptr, FILE *f); -void talloc_enable_null_tracking(void); -void talloc_disable_null_tracking(void); -void talloc_enable_leak_report(void); -void talloc_enable_leak_report_full(void); -void *_talloc_zero(const void *ctx, size_t size, const char *name); -void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); -void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); -void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); -void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); -void *talloc_realloc_fn(const void *context, void *ptr, size_t size); -void *talloc_autofree_context(void); -size_t talloc_get_size(const void *ctx); -void *talloc_find_parent_byname(const void *ctx, const char *name); -void talloc_show_parents(const void *context, FILE *file); -int talloc_is_parent(const void *context, const void *ptr); - -char *talloc_strdup(const void *t, const char *p); -char *talloc_strdup_append(char *s, const char *a); -char *talloc_strdup_append_buffer(char *s, const char *a); - -char *talloc_strndup(const void *t, const char *p, size_t n); -char *talloc_strndup_append(char *s, const char *a, size_t n); -char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); - -char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); -char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); - -char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); - -void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); - -#endif diff --git a/include/osmocore/timer.h b/include/osmocore/timer.h deleted file mode 100644 index fee888bf..00000000 --- a/include/osmocore/timer.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * (C) 2008, 2009 by Holger Hans Peter Freyther - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef TIMER_H -#define TIMER_H - -#include - -#include "linuxlist.h" - -/** - * Timer management: - * - Create a struct timer_list - * - Fill out timeout and use add_timer or - * use schedule_timer to schedule a timer in - * x seconds and microseconds from now... - * - Use del_timer to remove the timer - * - * Internally: - * - We hook into select.c to give a timeval of the - * nearest timer. On already passed timers we give - * it a 0 to immediately fire after the select - * - update_timers will call the callbacks and remove - * the timers. - * - */ -struct timer_list { - struct llist_head entry; - struct timeval timeout; - unsigned int active : 1; - unsigned int handled : 1; - unsigned int in_list : 1; - - void (*cb)(void*); - void *data; -}; - -/** - * timer management - */ -void bsc_add_timer(struct timer_list *timer); -void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds); -void bsc_del_timer(struct timer_list *timer); -int bsc_timer_pending(struct timer_list *timer); - - -/** - * internal timer list management - */ -struct timeval *bsc_nearest_timer(); -void bsc_prepare_timers(); -int bsc_update_timers(); -int bsc_timer_check(void); - -#endif diff --git a/include/osmocore/tlv.h b/include/osmocore/tlv.h deleted file mode 100644 index 7bda9f92..00000000 --- a/include/osmocore/tlv.h +++ /dev/null @@ -1,260 +0,0 @@ -#ifndef _TLV_H -#define _TLV_H - -#include -#include - -#include - -/* Terminology / wording - tag length value (in bits) - - V - - 8 - LV - 8 N * 8 - TLV 8 8 N * 8 - TL16V 8 16 N * 8 - TLV16 8 8 N * 16 - TvLV 8 8/16 N * 8 - -*/ - -#define LV_GROSS_LEN(x) (x+1) -#define TLV_GROSS_LEN(x) (x+2) -#define TLV16_GROSS_LEN(x) ((2*x)+2) -#define TL16V_GROSS_LEN(x) (x+3) -#define L16TV_GROSS_LEN(x) (x+3) - -#define TVLV_MAX_ONEBYTE 0x7f - -static inline uint16_t TVLV_GROSS_LEN(uint16_t len) -{ - if (len <= TVLV_MAX_ONEBYTE) - return TLV_GROSS_LEN(len); - else - return TL16V_GROSS_LEN(len); -} - -/* TLV generation */ - -static inline uint8_t *lv_put(uint8_t *buf, uint8_t len, - const uint8_t *val) -{ - *buf++ = len; - memcpy(buf, val, len); - return buf + len; -} - -static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len, - const uint8_t *val) -{ - *buf++ = tag; - *buf++ = len; - memcpy(buf, val, len); - return buf + len; -} - -static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len, - const uint16_t *val) -{ - *buf++ = tag; - *buf++ = len; - memcpy(buf, val, len*2); - return buf + len*2; -} - -static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len, - const uint8_t *val) -{ - *buf++ = tag; - *buf++ = len >> 8; - *buf++ = len & 0xff; - memcpy(buf, val, len); - return buf + len*2; -} - -static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len, - const uint8_t *val) -{ - uint8_t *ret; - - if (len <= TVLV_MAX_ONEBYTE) { - ret = tlv_put(buf, tag, len, val); - buf[1] |= 0x80; - } else - ret = tl16v_put(buf, tag, len, val); - - return ret; -} - -static inline uint8_t *msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val) -{ - uint8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len)); - return tlv16_put(buf, tag, len, val); -} - -static inline uint8_t *msgb_tl16v_put(struct msgb *msg, uint8_t tag, uint16_t len, - const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len)); - return tl16v_put(buf, tag, len, val); -} - -static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len, - const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len)); - return tvlv_put(buf, tag, len, val); -} - -static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag, - const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, L16TV_GROSS_LEN(len)); - - *buf++ = len >> 8; - *buf++ = len & 0xff; - *buf++ = tag; - memcpy(buf, val, len); - return buf + len; -} - -static inline uint8_t *v_put(uint8_t *buf, uint8_t val) -{ - *buf++ = val; - return buf; -} - -static inline uint8_t *tv_put(uint8_t *buf, uint8_t tag, - uint8_t val) -{ - *buf++ = tag; - *buf++ = val; - return buf; -} - -static inline uint8_t *tv_fixed_put(uint8_t *buf, uint8_t tag, - unsigned int len, const uint8_t *val) -{ - *buf++ = tag; - memcpy(buf, val, len); - return buf + len; -} - -/* 'val' is still in host byte order! */ -static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag, - uint16_t val) -{ - *buf++ = tag; - *buf++ = val >> 8; - *buf++ = val & 0xff; - return buf; -} - -static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len)); - return lv_put(buf, len, val); -} - -static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len)); - return tlv_put(buf, tag, len, val); -} - -static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val) -{ - uint8_t *buf = msgb_put(msg, 2); - return tv_put(buf, tag, val); -} - -static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag, - unsigned int len, const uint8_t *val) -{ - uint8_t *buf = msgb_put(msg, 1+len); - return tv_fixed_put(buf, tag, len, val); -} - -static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val) -{ - uint8_t *buf = msgb_put(msg, 1); - return v_put(buf, val); -} - -static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val) -{ - uint8_t *buf = msgb_put(msg, 3); - return tv16_put(buf, tag, val); -} - -static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val) -{ - uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len)); - return tlv_put(buf, tag, len, val); -} - -static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val) -{ - uint8_t *buf = msgb_push(msg, 2); - return tv_put(buf, tag, val); -} - -static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val) -{ - uint8_t *buf = msgb_push(msg, 3); - return tv16_put(buf, tag, val); -} - -static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len, - const uint8_t *val) -{ - uint8_t *buf = msgb_push(msg, TVLV_GROSS_LEN(len)); - return tvlv_put(buf, tag, len, val); -} - -/* TLV parsing */ - -struct tlv_p_entry { - uint16_t len; - const uint8_t *val; -}; - -enum tlv_type { - TLV_TYPE_NONE, - TLV_TYPE_FIXED, - TLV_TYPE_T, - TLV_TYPE_TV, - TLV_TYPE_TLV, - TLV_TYPE_TL16V, - TLV_TYPE_TvLV, - TLV_TYPE_SINGLE_TV -}; - -struct tlv_def { - enum tlv_type type; - uint8_t fixed_len; -}; - -struct tlv_definition { - struct tlv_def def[0xff]; -}; - -struct tlv_parsed { - struct tlv_p_entry lv[0xff]; -}; - -extern struct tlv_definition tvlv_att_def; - -int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val, - const struct tlv_definition *def, - const uint8_t *buf, int buf_len); -int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def, - const uint8_t *buf, int buf_len, uint8_t lv_tag, uint8_t lv_tag2); -/* take a master (src) tlvdev and fill up all empty slots in 'dst' */ -void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src); - -#define TLVP_PRESENT(x, y) ((x)->lv[y].val) -#define TLVP_LEN(x, y) (x)->lv[y].len -#define TLVP_VAL(x, y) (x)->lv[y].val - -#endif /* _TLV_H */ diff --git a/include/osmocore/utils.h b/include/osmocore/utils.h deleted file mode 100644 index 0cdf03b8..00000000 --- a/include/osmocore/utils.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef OSMOCORE_UTIL_H -#define OSMOCORE_UTIL_H - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -#include - -struct value_string { - unsigned int value; - const char *str; -}; - -const char *get_value_string(const struct value_string *vs, uint32_t val); -int get_string_value(const struct value_string *vs, const char *str); - -char bcd2char(uint8_t bcd); -/* only works for numbers in ascci */ -uint8_t char2bcd(char c); - -int hexparse(const char *str, uint8_t *b, int max_len); -char *hexdump(const unsigned char *buf, int len); -char *hexdump_nospc(const unsigned char *buf, int len); -char *ubit_dump(const uint8_t *bits, unsigned int len); - -#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; - -void osmo_str2lower(char *out, const char *in); -void osmo_str2upper(char *out, const char *in); - -#endif diff --git a/include/osmocore/write_queue.h b/include/osmocore/write_queue.h deleted file mode 100644 index ef244c32..00000000 --- a/include/osmocore/write_queue.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Generic write queue implementation */ -/* - * (C) 2010 by Holger Hans Peter Freyther - * (C) 2010 by On-Waves - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef write_queue_h -#define write_queue_h - -#include "select.h" -#include "msgb.h" - -struct write_queue { - struct bsc_fd bfd; - unsigned int max_length; - unsigned int current_length; - - struct llist_head msg_queue; - - int (*read_cb)(struct bsc_fd *fd); - int (*write_cb)(struct bsc_fd *fd, struct msgb *msg); - int (*except_cb)(struct bsc_fd *fd); -}; - -void write_queue_init(struct write_queue *queue, int max_length); -void write_queue_clear(struct write_queue *queue); -int write_queue_enqueue(struct write_queue *queue, struct msgb *data); -int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what); - -#endif diff --git a/src/backtrace.c b/src/backtrace.c index 42394453..ecd6b9c5 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include "config.h" #ifdef HAVE_EXECINFO_H diff --git a/src/bits.c b/src/bits.c index fcdf5cc3..ff5d176c 100644 --- a/src/bits.c +++ b/src/bits.c @@ -1,7 +1,7 @@ #include -#include +#include /* convert unpacked bits to packed bits, return length in bytes */ int osmo_ubit2pbit(pbit_t *out, const ubit_t *in, unsigned int num_bits) diff --git a/src/bitvec.c b/src/bitvec.c index 95d78a5c..4984af22 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -24,7 +24,7 @@ #include #include -#include +#include #define BITNUM_FROM_COMP(byte, bit) ((byte*8)+bit) diff --git a/src/crc16.c b/src/crc16.c index 8ac8031e..3a0d0ddb 100644 --- a/src/crc16.c +++ b/src/crc16.c @@ -8,7 +8,7 @@ * Version 2. See the file COPYING for more details. */ -#include +#include /** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */ uint16_t const crc16_table[256] = { diff --git a/src/gsm/gprs_cipher_core.c b/src/gsm/gprs_cipher_core.c index 6174bd72..0ff85e2d 100644 --- a/src/gsm/gprs_cipher_core.c +++ b/src/gsm/gprs_cipher_core.c @@ -23,9 +23,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index b6b345cb..b9b3ed97 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -22,13 +22,13 @@ * */ -#include -#include +#include +#include -#include +#include -#include -#include +#include +#include #include diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index dc450cc4..1640adc8 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -18,9 +18,9 @@ * */ -#include -#include -#include +#include +#include +#include #include diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c index daec4f39..436bf14b 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -28,11 +28,11 @@ #include -#include -#include -#include +#include +#include +#include -#include +#include const struct tlv_definition gsm48_att_tlvdef = { .def = { diff --git a/src/gsm/gsm48_ie.c b/src/gsm/gsm48_ie.c index 0e270881..efcf2816 100644 --- a/src/gsm/gsm48_ie.c +++ b/src/gsm/gsm48_ie.c @@ -27,12 +27,12 @@ #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include static const char bcd_num_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c index 54a13ad8..377705d9 100644 --- a/src/gsm/gsm_utils.c +++ b/src/gsm/gsm_utils.c @@ -23,8 +23,8 @@ */ //#include -#include -#include +#include +#include #include #include @@ -33,7 +33,7 @@ #include #include -#include "../config.h" +#include "../../config.h" /* ETSI GSM 03.38 6.2.1 and 6.2.1.1 default alphabet * Greek symbols at hex positions 0x10 and 0x12-0x1a diff --git a/src/gsm/rsl.c b/src/gsm/rsl.c index 3bfeffb9..12ac0cfb 100644 --- a/src/gsm/rsl.c +++ b/src/gsm/rsl.c @@ -25,8 +25,8 @@ #include #include -#include -#include +#include +#include #define RSL_ALLOC_SIZE 200 #define RSL_ALLOC_HEADROOM 56 diff --git a/src/gsm/rxlev_stat.c b/src/gsm/rxlev_stat.c index b474aaa8..626aaffb 100644 --- a/src/gsm/rxlev_stat.c +++ b/src/gsm/rxlev_stat.c @@ -27,8 +27,8 @@ #include #include -#include -#include +#include +#include int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val) { diff --git a/src/gsm/tlv_parser.c b/src/gsm/tlv_parser.c index bbef7a9a..1e4c6b5f 100644 --- a/src/gsm/tlv_parser.c +++ b/src/gsm/tlv_parser.c @@ -1,7 +1,7 @@ #include #include -#include -#include +#include +#include struct tlv_definition tvlv_att_def; diff --git a/src/gsmtap_util.c b/src/gsmtap_util.c index abee4dac..6d02d58f 100644 --- a/src/gsmtap_util.c +++ b/src/gsmtap_util.c @@ -24,13 +24,13 @@ #ifdef HAVE_SYS_SELECT_H -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include diff --git a/src/logging.c b/src/logging.c index 89ca6ced..653c80db 100644 --- a/src/logging.c +++ b/src/logging.c @@ -34,9 +34,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include /* for LOGGING_STR. */ diff --git a/src/logging_syslog.c b/src/logging_syslog.c index b558fc0b..4f043b1d 100644 --- a/src/logging_syslog.c +++ b/src/logging_syslog.c @@ -33,9 +33,9 @@ #include #endif -#include -#include -#include +#include +#include +#include static const int logp2syslog_level(unsigned int level) { diff --git a/src/msgb.c b/src/msgb.c index 12a839a9..86720064 100644 --- a/src/msgb.c +++ b/src/msgb.c @@ -24,9 +24,9 @@ #include #include -#include +#include //#include -#include +#include //#include void *tall_msgb_ctx; diff --git a/src/msgfile.c b/src/msgfile.c index 68f05813..ec4434a5 100644 --- a/src/msgfile.c +++ b/src/msgfile.c @@ -21,8 +21,8 @@ * */ -#include -#include +#include +#include #include #include diff --git a/src/panic.c b/src/panic.c index 21e8fd56..588a5fe0 100644 --- a/src/panic.c +++ b/src/panic.c @@ -20,9 +20,9 @@ * */ -#include -#include -#include +#include +#include +#include #include "../config.h" diff --git a/src/plugin.c b/src/plugin.c index 3ba2d431..4924e950 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -31,7 +31,7 @@ #include #include -#include +#include int plugin_load_all(const char *directory) { diff --git a/src/rate_ctr.c b/src/rate_ctr.c index 80ef55b2..dd56e806 100644 --- a/src/rate_ctr.c +++ b/src/rate_ctr.c @@ -23,11 +23,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include static LLIST_HEAD(rate_ctr_groups); diff --git a/src/select.c b/src/select.c index 5aa2beb5..adf36194 100644 --- a/src/select.c +++ b/src/select.c @@ -22,9 +22,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include "../config.h" diff --git a/src/signal.c b/src/signal.c index c7ca86c4..bb5c38e1 100644 --- a/src/signal.c +++ b/src/signal.c @@ -18,9 +18,9 @@ * */ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/src/statistics.c b/src/statistics.c index 34e6a408..183005df 100644 --- a/src/statistics.c +++ b/src/statistics.c @@ -23,9 +23,9 @@ #include -#include -#include -#include +#include +#include +#include static LLIST_HEAD(counters); diff --git a/src/talloc.c b/src/talloc.c index 98c2ee09..60d7927d 100644 --- a/src/talloc.c +++ b/src/talloc.c @@ -55,7 +55,7 @@ #define __USE_GNU #include #undef __USE_GNU -#include +#include #define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* not _TALLOC_SAMBA3 */ diff --git a/src/timer.c b/src/timer.c index 37d7d166..9b2dd9e9 100644 --- a/src/timer.c +++ b/src/timer.c @@ -20,7 +20,7 @@ #include #include -#include +#include static LLIST_HEAD(timer_list); static struct timeval s_nearest_time; diff --git a/src/utils.c b/src/utils.c index 354fce57..af1829c9 100644 --- a/src/utils.c +++ b/src/utils.c @@ -4,7 +4,7 @@ #include #include -#include +#include static char namebuf[255]; const char *get_value_string(const struct value_string *vs, uint32_t val) diff --git a/src/vty/buffer.c b/src/vty/buffer.c index a5655b93..e385f9fd 100644 --- a/src/vty/buffer.c +++ b/src/vty/buffer.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include diff --git a/src/vty/command.c b/src/vty/command.c index 0f65224f..5dc1dd45 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -38,7 +38,7 @@ Boston, MA 02111-1307, USA. */ #include #include -#include +#include #define CONFIGFILE_MASK 022 diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 1b356c9f..4cab22a3 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -24,9 +24,9 @@ #include "../../config.h" -#include -#include -#include +#include +#include +#include //#include diff --git a/src/vty/telnet_interface.c b/src/vty/telnet_interface.c index 098fa2e6..0d45d614 100644 --- a/src/vty/telnet_interface.c +++ b/src/vty/telnet_interface.c @@ -25,9 +25,9 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include diff --git a/src/vty/utils.c b/src/vty/utils.c index e163526e..7797e62d 100644 --- a/src/vty/utils.c +++ b/src/vty/utils.c @@ -23,10 +23,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include diff --git a/src/vty/vector.c b/src/vty/vector.c index 0343163f..4012f24b 100644 --- a/src/vty/vector.c +++ b/src/vty/vector.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include void *tall_vty_vec_ctx; diff --git a/src/vty/vty.c b/src/vty/vty.c index c1a9b3af..a1f0304b 100644 --- a/src/vty/vty.c +++ b/src/vty/vty.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include #define SYSCONFDIR "/usr/local/etc" diff --git a/src/write_queue.c b/src/write_queue.c index 7295569a..0642aad6 100644 --- a/src/write_queue.c +++ b/src/write_queue.c @@ -21,7 +21,7 @@ * */ -#include +#include int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what) { diff --git a/tests/msgfile/msgfile_test.c b/tests/msgfile/msgfile_test.c index a82ac516..4637ceab 100644 --- a/tests/msgfile/msgfile_test.c +++ b/tests/msgfile/msgfile_test.c @@ -19,7 +19,7 @@ * */ -#include +#include #include diff --git a/tests/sms/sms_test.c b/tests/sms/sms_test.c index 9d87b5bc..f5d82b99 100644 --- a/tests/sms/sms_test.c +++ b/tests/sms/sms_test.c @@ -23,9 +23,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include struct test_case { const uint8_t *input; diff --git a/tests/smscb/smscb_test.c b/tests/smscb/smscb_test.c index 627d5a13..e10e12d8 100644 --- a/tests/smscb/smscb_test.c +++ b/tests/smscb/smscb_test.c @@ -18,7 +18,7 @@ * */ -#include +#include #include diff --git a/tests/timer/timer_test.c b/tests/timer/timer_test.c index 1b458d81..30b08ad0 100644 --- a/tests/timer/timer_test.c +++ b/tests/timer/timer_test.c @@ -20,8 +20,8 @@ #include -#include -#include +#include +#include #include "../../config.h" diff --git a/tests/ussd/ussd_test.c b/tests/ussd/ussd_test.c index bddbbcb7..6d2a8c9b 100644 --- a/tests/ussd/ussd_test.c +++ b/tests/ussd/ussd_test.c @@ -19,7 +19,7 @@ * */ -#include +#include #include #include #include -- cgit v1.2.3 From d6643d5fcf627d64cc3d7c385ba1cdd3981a8663 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Sun, 27 Mar 2011 11:35:40 +0200 Subject: core/bits: Make sbit_t a signed type (so that the math works) Signed-off-by: Sylvain Munaut --- include/osmocom/core/bits.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h index 8d4a0789..eb22d07c 100644 --- a/include/osmocom/core/bits.h +++ b/include/osmocom/core/bits.h @@ -3,7 +3,7 @@ #include -typedef uint8_t sbit_t; /* soft bit (-127...127) */ +typedef int8_t sbit_t; /* soft bit (-127...127) */ typedef uint8_t ubit_t; /* unpacked bit (0 or 1) */ typedef uint8_t pbit_t; /* packed bis (8 bits in a byte) */ -- cgit v1.2.3 From 36bdf2cb73a82548cc1a6a9e332a4e646a5868b2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 28 Mar 2011 19:24:19 +0200 Subject: bitvec: add bitvec_find_first_bit_pos() from gsm/rxlev_stat.c This patch adds bitvec_find_bit_pos() to bitvec.c where it really belongs to. Before this patch used to be part of gsm/rxlev_stat.c --- include/osmocom/core/bitvec.h | 2 ++ src/bitvec.c | 14 ++++++++++++++ src/gsm/rxlev_stat.c | 12 ------------ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/include/osmocom/core/bitvec.h b/include/osmocom/core/bitvec.h index 42977fb2..bbe1641b 100644 --- a/include/osmocom/core/bitvec.h +++ b/include/osmocom/core/bitvec.h @@ -68,6 +68,8 @@ int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count); /* get multiple bits (based on numeric value) from current pos */ int bitvec_get_uint(struct bitvec *bv, int num_bits); +/* find the first bit set in bit vector */ +int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val); /* Pad the bit vector up to a certain bit position */ int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit); diff --git a/src/bitvec.c b/src/bitvec.c index 4984af22..4fd38349 100644 --- a/src/bitvec.c +++ b/src/bitvec.c @@ -217,3 +217,17 @@ int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit) return 0; } + +/* find first bit set in bit vector */ +int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, + enum bit_value val) +{ + unsigned int i; + + for (i = n; i < bv->data_len*8; i++) { + if (bitvec_get_bit_pos(bv, i) == val) + return i; + } + + return -1; +} diff --git a/src/gsm/rxlev_stat.c b/src/gsm/rxlev_stat.c index 626aaffb..d226861e 100644 --- a/src/gsm/rxlev_stat.c +++ b/src/gsm/rxlev_stat.c @@ -30,18 +30,6 @@ #include #include -int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val) -{ - unsigned int i; - - for (i = n; i < bv->data_len*8; i++) { - if (bitvec_get_bit_pos(bv, i) == val) - return i; - } - - return -1; -} - void rxlev_stat_input(struct rxlev_stats *st, uint16_t arfcn, uint8_t rxlev) { struct bitvec bv; -- cgit v1.2.3 From dc35dbee9534f832f629e99ee6a8a11d234cdd3d Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 28 Mar 2011 19:24:20 +0200 Subject: write_queue: use full path of includes in osmocom/core/write_queue.h --- include/osmocom/core/write_queue.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/osmocom/core/write_queue.h b/include/osmocom/core/write_queue.h index ef244c32..3b730c77 100644 --- a/include/osmocom/core/write_queue.h +++ b/include/osmocom/core/write_queue.h @@ -23,8 +23,8 @@ #ifndef write_queue_h #define write_queue_h -#include "select.h" -#include "msgb.h" +#include +#include struct write_queue { struct bsc_fd bfd; -- cgit v1.2.3 From 70004fcc6dcd5dd979c10143872b2a136371e371 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 28 Mar 2011 19:24:21 +0200 Subject: vty: move vty_out_rate_ctr_group prototype to osmocom/vty/misc.h Before this patch, it was in osmocom/core/rate_ctr.h --- include/osmocom/core/rate_ctr.h | 3 --- include/osmocom/vty/Makefile.am | 2 +- include/osmocom/vty/misc.h | 10 ++++++++++ 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 include/osmocom/vty/misc.h diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h index dba573d9..9efc23db 100644 --- a/include/osmocom/core/rate_ctr.h +++ b/include/osmocom/core/rate_ctr.h @@ -75,7 +75,4 @@ static inline void rate_ctr_inc(struct rate_ctr *ctr) /* Initialize the counter module */ int rate_ctr_init(void *tall_ctx); -struct vty; -void vty_out_rate_ctr_group(struct vty *vty, const char *prefix, - struct rate_ctr_group *ctrg); #endif /* RATE_CTR_H */ diff --git a/include/osmocom/vty/Makefile.am b/include/osmocom/vty/Makefile.am index d2f0616d..83d00107 100644 --- a/include/osmocom/vty/Makefile.am +++ b/include/osmocom/vty/Makefile.am @@ -1,4 +1,4 @@ osmovty_HEADERS = buffer.h command.h vector.h vty.h \ - telnet_interface.h logging.h + telnet_interface.h logging.h misc.h osmovtydir = $(includedir)/osmocom/vty diff --git a/include/osmocom/vty/misc.h b/include/osmocom/vty/misc.h new file mode 100644 index 00000000..707f82fa --- /dev/null +++ b/include/osmocom/vty/misc.h @@ -0,0 +1,10 @@ +#ifndef OSMO_VTY_MISC_H +#define OSMO_VTY_MISC_H + +#include +#include + +void vty_out_rate_ctr_group(struct vty *vty, const char *prefix, + struct rate_ctr_group *ctrg); + +#endif -- cgit v1.2.3 From 3abad6a6f9ae4cfa65c9f6d5f15208790449eefe Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 28 Mar 2011 19:24:22 +0200 Subject: utils: move OSMO_SNPRINT_RET() macro definition to osmocom/core/utils.h This is used by the logging to vty conversion functions by now, but it may be of help for other functions that plan to use snprintf(). --- include/osmocom/core/utils.h | 9 +++++++++ src/logging.c | 26 ++++++++------------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index 0cdf03b8..252228de 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -27,4 +27,13 @@ char *ubit_dump(const uint8_t *bits, unsigned int len); void osmo_str2lower(char *out, const char *in); void osmo_str2upper(char *out, const char *in); +#define OSMO_SNPRINTF_RET(ret, rem, offset, len) \ +do { \ + len += ret; \ + if (ret > rem) \ + ret = rem; \ + offset += ret; \ + rem -= ret; \ +} while (0) + #endif diff --git a/src/logging.c b/src/logging.c index 653c80db..2c24f2fb 100644 --- a/src/logging.c +++ b/src/logging.c @@ -434,16 +434,6 @@ int log_target_file_reopen(struct log_target *target) return 0; } -/* This can go into some header file so others can benefit from it. */ -#define SNPRINTF_FAILURE(ret, rem, offset, len) \ -do { \ - len += ret; \ - if (ret > rem) \ - ret = rem; \ - offset += ret; \ - rem -= ret; \ -} while (0) - /* This generates the logging command string for VTY. */ const char *log_vty_command_string(const struct log_info *info) { @@ -465,7 +455,7 @@ const char *log_vty_command_string(const struct log_info *info) ret = snprintf(str + offset, rem, "logging level ("); if (ret < 0) goto err; - SNPRINTF_FAILURE(ret, rem, offset, len); + OSMO_SNPRINTF_RET(ret, rem, offset, len); for (i = 0; i < info->num_cat; i++) { int j, name_len = strlen(info->cat[i].name)+1; @@ -478,7 +468,7 @@ const char *log_vty_command_string(const struct log_info *info) ret = snprintf(str + offset, rem, "%s|", name+1); if (ret < 0) goto err; - SNPRINTF_FAILURE(ret, rem, offset, len); + OSMO_SNPRINTF_RET(ret, rem, offset, len); } offset--; /* to remove the trailing | */ rem++; @@ -486,7 +476,7 @@ const char *log_vty_command_string(const struct log_info *info) ret = snprintf(str + offset, rem, ") ("); if (ret < 0) goto err; - SNPRINTF_FAILURE(ret, rem, offset, len); + OSMO_SNPRINTF_RET(ret, rem, offset, len); for (i = 0; i < LOGLEVEL_DEFS; i++) { int j, loglevel_str_len = strlen(loglevel_strs[i].str)+1; @@ -499,7 +489,7 @@ const char *log_vty_command_string(const struct log_info *info) ret = snprintf(str + offset, rem, "%s|", loglevel_str); if (ret < 0) goto err; - SNPRINTF_FAILURE(ret, rem, offset, len); + OSMO_SNPRINTF_RET(ret, rem, offset, len); } offset--; /* to remove the trailing | */ rem++; @@ -507,7 +497,7 @@ const char *log_vty_command_string(const struct log_info *info) ret = snprintf(str + offset, rem, ")"); if (ret < 0) goto err; - SNPRINTF_FAILURE(ret, rem, offset, len); + OSMO_SNPRINTF_RET(ret, rem, offset, len); err: return str; } @@ -536,21 +526,21 @@ const char *log_vty_command_description(const struct log_info *info) "Set the log level for a specified category\n"); if (ret < 0) goto err; - SNPRINTF_FAILURE(ret, rem, offset, len); + OSMO_SNPRINTF_RET(ret, rem, offset, len); for (i = 0; i < info->num_cat; i++) { ret = snprintf(str + offset, rem, "%s\n", info->cat[i].description); if (ret < 0) goto err; - SNPRINTF_FAILURE(ret, rem, offset, len); + OSMO_SNPRINTF_RET(ret, rem, offset, len); } for (i = 0; i < LOGLEVEL_DEFS; i++) { ret = snprintf(str + offset, rem, "%s\n", loglevel_descriptions[i]); if (ret < 0) goto err; - SNPRINTF_FAILURE(ret, rem, offset, len); + OSMO_SNPRINTF_RET(ret, rem, offset, len); } err: return str; -- cgit v1.2.3 From ff0670edf399882329daa242247523d5f250f9a5 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 24 Feb 2011 14:20:41 +0100 Subject: vty: Fix a memory leak in the vty description command Before assigning a new string, free the previous one. This assume that it was allocated with talloc which should be true for the osmocom users. --- src/vty/logging_vty.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 4cab22a3..b037a5bc 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -269,6 +269,8 @@ gDEFUN(cfg_description, cfg_description_cmd, return CMD_WARNING; } + if (*dptr) + talloc_free(*dptr); *dptr = argv_concat(argv, argc, 0); if (!dptr) return CMD_WARNING; -- cgit v1.2.3 From 952a18ed19f531b82e26108f8c46ef225fddef43 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 29 Mar 2011 17:03:56 +0200 Subject: logging: Add the 'all' category back to the log level command This is required to be able to set a global log level. The all command is emitted by the VTY logging code. --- src/logging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging.c b/src/logging.c index 2c24f2fb..77c8a50d 100644 --- a/src/logging.c +++ b/src/logging.c @@ -452,7 +452,7 @@ const char *log_vty_command_string(const struct log_info *info) if (!str) return NULL; - ret = snprintf(str + offset, rem, "logging level ("); + ret = snprintf(str + offset, rem, "logging level (all|"); if (ret < 0) goto err; OSMO_SNPRINTF_RET(ret, rem, offset, len); -- cgit v1.2.3 From 2d42ddeba37ed7e0d54bf10dc66b7549ad43bc5b Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Fri, 8 Apr 2011 10:46:18 +0200 Subject: Add functions to search for rate counters by name * rate_ctr_get_group_by_name_idx, rate_ctr_get_by_name --- include/osmocom/core/rate_ctr.h | 2 ++ src/rate_ctr.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h index 9efc23db..63baa322 100644 --- a/include/osmocom/core/rate_ctr.h +++ b/include/osmocom/core/rate_ctr.h @@ -75,4 +75,6 @@ static inline void rate_ctr_inc(struct rate_ctr *ctr) /* Initialize the counter module */ int rate_ctr_init(void *tall_ctx); +struct rate_ctr_group *rate_ctr_get_group_by_name_idx(const char *name, const unsigned int idx); +struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name); #endif /* RATE_CTR_H */ diff --git a/src/rate_ctr.c b/src/rate_ctr.c index dd56e806..a7fc9496 100644 --- a/src/rate_ctr.c +++ b/src/rate_ctr.c @@ -125,3 +125,37 @@ int rate_ctr_init(void *tall_ctx) return 0; } + +struct rate_ctr_group *rate_ctr_get_group_by_name_idx(const char *name, const unsigned int idx) +{ + struct rate_ctr_group *ctrg; + + llist_for_each_entry(ctrg, &rate_ctr_groups, list) { + if (!ctrg->desc) + continue; + + if (!strcmp(ctrg->desc->group_name_prefix, name) && + ctrg->idx == idx) { + return ctrg; + } + } + return NULL; +} + +struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name) +{ + int i; + struct rate_ctr_desc *ctr_desc; + + if (!ctrg->desc) + return NULL; + + for (i = 0; i < ctrg->desc->num_ctr; i++) { + ctr_desc = &ctrg->desc->ctr_desc[i]; + + if (!strcmp(ctr_desc->name, name)) { + return &ctrg->ctr[i]; + } + } + return NULL; +} -- cgit v1.2.3 From 334c8e178008f3184382aae6c2cd13b9652169e2 Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Fri, 8 Apr 2011 10:46:19 +0200 Subject: Add a function to search for a counter by name --- include/osmocom/core/statistics.h | 2 ++ src/statistics.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/osmocom/core/statistics.h b/include/osmocom/core/statistics.h index 1d56054a..2c159657 100644 --- a/include/osmocom/core/statistics.h +++ b/include/osmocom/core/statistics.h @@ -28,4 +28,6 @@ void counter_free(struct counter *ctr); int counters_for_each(int (*handle_counter)(struct counter *, void *), void *data); +struct counter *counter_get_by_name(const char *name); + #endif /* _STATISTICS_H */ diff --git a/src/statistics.c b/src/statistics.c index 183005df..d1ffe526 100644 --- a/src/statistics.c +++ b/src/statistics.c @@ -64,3 +64,13 @@ int counters_for_each(int (*handle_counter)(struct counter *, void *), void *dat return rc; } +struct counter *counter_get_by_name(const char *name) +{ + struct counter *ctr; + + llist_for_each_entry(ctr, &counters, list) { + if (!strcmp(ctr->name, name)) + return ctr; + } + return NULL; +} -- cgit v1.2.3 From a9f526a1abb1d2bfa68c611f1676fea2d89bc9d9 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 18 Apr 2011 16:45:45 +0200 Subject: stats: Fix the compiler warnings Do not remove the const, include strings.h for strcmp --- include/osmocom/core/rate_ctr.h | 2 +- src/rate_ctr.c | 4 ++-- src/statistics.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h index 63baa322..ebb8646c 100644 --- a/include/osmocom/core/rate_ctr.h +++ b/include/osmocom/core/rate_ctr.h @@ -76,5 +76,5 @@ static inline void rate_ctr_inc(struct rate_ctr *ctr) int rate_ctr_init(void *tall_ctx); struct rate_ctr_group *rate_ctr_get_group_by_name_idx(const char *name, const unsigned int idx); -struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name); +const struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name); #endif /* RATE_CTR_H */ diff --git a/src/rate_ctr.c b/src/rate_ctr.c index a7fc9496..a0e18148 100644 --- a/src/rate_ctr.c +++ b/src/rate_ctr.c @@ -142,10 +142,10 @@ struct rate_ctr_group *rate_ctr_get_group_by_name_idx(const char *name, const un return NULL; } -struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name) +const struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name) { int i; - struct rate_ctr_desc *ctr_desc; + const struct rate_ctr_desc *ctr_desc; if (!ctrg->desc) return NULL; diff --git a/src/statistics.c b/src/statistics.c index d1ffe526..a6121401 100644 --- a/src/statistics.c +++ b/src/statistics.c @@ -20,8 +20,8 @@ * */ - #include +#include #include #include -- cgit v1.2.3 From 28dbfe9bf7a799ab1da2563fd5e007d007b54168 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 18 Apr 2011 16:52:55 +0200 Subject: misc: Remove the sys/types.h include from various files We used this include for the u_int{8,16,32}_t types but we do not need this anymore. --- src/msgb.c | 1 - src/msgfile.c | 1 - src/plugin.c | 1 - src/process.c | 1 - src/statistics.c | 1 - src/talloc.c | 1 - tests/sms/sms_test.c | 1 - 7 files changed, 7 deletions(-) diff --git a/src/msgb.c b/src/msgb.c index 86720064..d2c167aa 100644 --- a/src/msgb.c +++ b/src/msgb.c @@ -22,7 +22,6 @@ #include #include #include -#include #include //#include diff --git a/src/msgfile.c b/src/msgfile.c index ec4434a5..c13df51d 100644 --- a/src/msgfile.c +++ b/src/msgfile.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/src/plugin.c b/src/plugin.c index 4924e950..4d9fd314 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -24,7 +24,6 @@ #if HAVE_DLFCN_H -#include #include #include #include diff --git a/src/process.c b/src/process.c index 180efa51..7f4f12cb 100644 --- a/src/process.c +++ b/src/process.c @@ -23,7 +23,6 @@ #include #include #include -#include #include int osmo_daemonize(void) diff --git a/src/statistics.c b/src/statistics.c index a6121401..83bb6ed3 100644 --- a/src/statistics.c +++ b/src/statistics.c @@ -20,7 +20,6 @@ * */ -#include #include #include diff --git a/src/talloc.c b/src/talloc.c index 60d7927d..d3a0690f 100644 --- a/src/talloc.c +++ b/src/talloc.c @@ -48,7 +48,6 @@ #ifndef _TALLOC_SAMBA3 //#include "replace.h" -#include #include #include #include diff --git a/tests/sms/sms_test.c b/tests/sms/sms_test.c index f5d82b99..b4ed631f 100644 --- a/tests/sms/sms_test.c +++ b/tests/sms/sms_test.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3