Merge libosmocore commit '972b502ecaf3b919b7e89c13257dd6ec97aaafb7' into master

this updates libosmocore to the current libosmocore.git master, mainly to import
the msgb_get() / msgb_pull() fixes.
This commit is contained in:
Harald Welte 2012-09-08 20:44:55 +02:00
commit d08b949c2b
139 changed files with 7008 additions and 414 deletions

View File

@ -1,6 +1,7 @@
Makefile
Makefile.in
.deps
.dirstamp
.libs
*.o
*.lo
@ -60,7 +61,8 @@ utils/osmo-auc-gen
doc/codec
doc/core
doc/vty
doc/vty/latex
doc/vty/html
doc/gsm
doc/html.tar

View File

@ -1,11 +1,11 @@
AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
ACLOCAL_AMFLAGS = -I m4
INCLUDES = $(all_includes) -I$(top_srcdir)/include
SUBDIRS = include src tests utils
SUBDIRS = include src src/vty src/codec src/gsm src/gb tests utils
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libosmocore.pc libosmocodec.pc libosmovty.pc libosmogsm.pc
pkgconfig_DATA = libosmocore.pc libosmocodec.pc libosmovty.pc libosmogsm.pc \
libosmogb.pc
BUILT_SOURCES = $(top_srcdir)/.version
$(top_srcdir)/.version:
@ -17,12 +17,9 @@ EXTRA_DIST = git-version-gen
if HAVE_DOXYGEN
pkgdocdir=$(docdir)/$(PACKAGE)-$(VERSION)
doc_htmldir=$(pkgdocdir)/html
html_DATA = $(top_builddir)/doc/html.tar
doc_html_DATA = $(top_builddir)/doc/html.tar
$(doc_html_DATA): $(top_builddir)/doc/core/html/index.html \
$(html_DATA): $(top_builddir)/doc/core/html/index.html \
$(top_builddir)/doc/gsm/html/index.html \
$(top_builddir)/doc/vty/html/index.html \
$(top_builddir)/doc/codec/html/index.html
@ -39,8 +36,7 @@ $(top_builddir)/doc/gsm/html/index.html: $(SOURCES) Doxyfile.gsm
$(DOXYGEN) Doxyfile.gsm
$(top_builddir)/doc/vty/html/index.html: $(SOURCES) Doxyfile.vty
@rm -rf doc/vty
mkdir -p doc/vty
@rm -rf doc/vty/{html,latex}
$(DOXYGEN) Doxyfile.vty
$(top_builddir)/doc/codec/html/index.html: $(SOURCES) Doxyfile.codec
@ -49,10 +45,10 @@ $(top_builddir)/doc/codec/html/index.html: $(SOURCES) Doxyfile.codec
$(DOXYGEN) Doxyfile.codec
install-data-hook:
cd $(DESTDIR)$(doc_htmldir) && tar xf html.tar && rm -f html.tar
cd $(DESTDIR)$(htmldir) && tar xf html.tar && rm -f html.tar
uninstall-hook:
cd $(DESTDIR)$(doc_htmldir) && rm -rf {core,gsm,vty,codec}
cd $(DESTDIR)$(htmldir) && rm -rf {core,gsm,vty,codec}
DX_CLEAN = doc/{core,gsm,vty,codec}/{html,latex}/* doc/html.tar
endif

View File

@ -2,7 +2,7 @@ AC_INIT([libosmocore],
m4_esyscmd([./git-version-gen .tarball-version]),
[openbsc@lists.osmocom.org])
AM_INIT_AUTOMAKE([dist-bzip2])
AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip 1.6])
AC_CONFIG_TESTDIR(tests)
dnl kernel style compile messages
@ -10,10 +10,10 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl checks for programs
AC_PROG_MAKE_SET
AC_PROG_MKDIR_P
AC_PROG_CC
AC_PROG_INSTALL
LT_INIT
AC_PROG_LIBTOOL
LT_INIT([pic-only])
AC_CONFIG_MACRO_DIR([m4])
@ -39,6 +39,31 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
CFLAGS="$saved_CFLAGS"
AC_SUBST(SYMBOL_VISIBILITY)
AC_DEFUN([CHECK_TM_INCLUDES_TM_GMTOFF], [
AC_CACHE_CHECK(
[whether struct tm has tm_gmtoff member],
osmo_cv_tm_includes_tm_gmtoff,
[AC_LINK_IFELSE([
AC_LANG_PROGRAM([
#include <time.h>
], [
time_t t = time(NULL);
struct tm* lt = localtime(&t);
int off = lt->tm_gmtoff;
])
],
osmo_cv_tm_includes_tm_gmtoff=yes,
osmo_cv_tm_includes_tm_gmtoff=no
)]
)
if test "x$osmo_cv_tm_includes_tm_gmtoff" = xyes; then
AC_DEFINE(HAVE_TM_GMTOFF_IN_TM, 1,
[Define if struct tm has tm_gmtoff member.])
fi
])
CHECK_TM_INCLUDES_TM_GMTOFF
dnl Generate the output
AM_CONFIG_HEADER(config.h)
@ -58,14 +83,6 @@ AC_ARG_ENABLE(plugin,
[enable_plugin=$enableval], [enable_plugin="yes"])
AM_CONDITIONAL(ENABLE_PLUGIN, test x"$enable_plugin" = x"yes")
AC_ARG_ENABLE(tests,
[AS_HELP_STRING(
[--disable-tests],
[Disable building test programs]
)],
[enable_tests=$enableval], [enable_tests="yes"])
AM_CONDITIONAL(ENABLE_TESTS, test x"$enable_tests" = x"yes")
AC_ARG_ENABLE(vty,
[AS_HELP_STRING(
[--disable-vty],
@ -129,7 +146,6 @@ AC_ARG_ENABLE(embedded,
if test x"$embedded" = x"yes"
then
AC_DEFINE([EMBEDDED],[1],[Select building for embedded use])
AM_CONDITIONAL(ENABLE_TESTS, false)
AM_CONDITIONAL(ENABLE_PLUGIN, false)
AM_CONDITIONAL(ENABLE_MSGFILE, false)
AM_CONDITIONAL(ENABLE_SERIAL, false)
@ -145,30 +161,14 @@ AC_OUTPUT(
libosmocodec.pc
libosmovty.pc
libosmogsm.pc
include/osmocom/Makefile
include/osmocom/vty/Makefile
include/osmocom/codec/Makefile
include/osmocom/crypt/Makefile
include/osmocom/gsm/Makefile
include/osmocom/gsm/protocol/Makefile
include/osmocom/core/Makefile
libosmogb.pc
include/Makefile
src/Makefile
src/vty/Makefile
src/codec/Makefile
src/gsm/Makefile
src/gb/Makefile
tests/Makefile
tests/timer/Makefile
tests/sms/Makefile
tests/msgfile/Makefile
tests/ussd/Makefile
tests/smscb/Makefile
tests/bits/Makefile
tests/a5/Makefile
tests/auth/Makefile
tests/conv/Makefile
tests/lapd/Makefile
tests/gsm0808/Makefile
utils/Makefile
Doxyfile.core
Doxyfile.gsm

View File

@ -1,3 +1,15 @@
libosmocore (0.5.3+git1-1) precise; urgency=low
* Fix issue with package version.
-- Eric Butler <eric@codebutler.com> Tue, 14 Aug 2012 20:43:17 -0700
libosmocore (0.5.3+git1) precise; urgency=low
* Updated debian package.
-- Eric Butler <eric@codebutler.com> Tue, 14 Aug 2012 16:53:56 -0700
libosmocore (0.3.0) natty; urgency=low
* New upstream version of libosmocore

View File

@ -2,7 +2,7 @@ Source: libosmocore
Section: libs
Priority: optional
Maintainer: Harald Welte <laforge@gnumonks.org>
Build-Depends: debhelper (>= 7.0.50~), autotools-dev, autoconf, automake, libtool, dh-autoreconf
Build-Depends: debhelper (>= 7.0.50~), autotools-dev, autoconf, automake, libtool, dh-autoreconf, libdpkg-perl, git
Standards-Version: 3.8.4
Homepage: http://bb.osmocom.org/trac/wiki/libosmocore
Vcs-Git: git://git.osmocom.org/libosmocore.git

View File

@ -1,6 +0,0 @@
dh_auto_configure
dh_auto_build
dh_auto_test
dh_prep
dh_installdirs
dh_auto_install

View File

@ -9,11 +9,22 @@
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
CFLAGS = -Wall -g
%:
dh --with autoreconf $@
dh --with autoreconf $@ --fail-missing
#override_dh_strip:
# dh_strip --dbg-package=libosmocore-dbg
override_dh_autoreconf:
echo $(VERSION) > .tarball-version
dh_autoreconf
override_dh_auto_test:
# tests are broken...

View File

@ -1 +1 @@
3.0 (git)
3.0 (native)

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<vtydoc xmlns="urn:osmocom:xml:libosmocore:vty:doc:1.0">
<!-- test a nested hierachy -->
<node id="mgcp" name="MGCP Node">
<!-- define a command -->
<command id="foo_cmd">
<doc>General docs</doc>
<params>
<param name="do" doc="Explain do" />
<param name="fo" doc="Explain foo" />
</params>
</command>
<command id="foo_cmd">
<doc>General docs</doc>
<params>
<param name="do" doc="Explain do" />
<param name="fo" doc="Explain foo" />
</params>
</command>
</node>
</vtydoc>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:vty="urn:osmocom:xml:libosmocore:vty:doc:1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- Copy the name of the node -->
<xsl:template match="vty:node">
<xsl:variable name="info" select="document($with)/vty:vtydoc/vty:node[@id=current()/@id]/." />
<xsl:if test="not($info/vty:hide)">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<xsl:for-each select="$info/*">
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:if>
</xsl:template>
<!-- Copy command and add nodes -->
<xsl:template match="vty:command">
<xsl:variable name="info" select="document($with)/vty:vtydoc/vty:node[@id=current()/../@id]/vty:command[@id=current()/@id]/." />
<xsl:variable name="info_generic" select="document($with)/vty:vtydoc/vty:common/vty:command[@id=current()/@id]/." />
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
<!-- Copy the specific issue... -->
<xsl:for-each select="$info/*">
<xsl:copy-of select="." />
</xsl:for-each>
<xsl:if test="not($info)">
<xsl:for-each select="$info_generic/*">
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:transform>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns="urn:osmocom:xml:libosmocore:vty:doc:1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:osmocom:xml:libosmocore:vty:doc:1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="ParamType">
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="doc" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="ParamsType">
<xs:sequence>
<xs:element name="param" type="ParamType" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="CommandType">
<xs:sequence>
<xs:element name="doc" type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="params" type="ParamsType" minOccurs="1" maxOccurs="1"/>
<xs:element name="enter" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="NodeType">
<xs:sequence>
<xs:element name="command" type="CommandType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="id" type="xs:anyURI"/>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
<!-- the main entry -->
<xs:element name="vtydoc">
<xs:complexType>
<xs:sequence>
<xs:element name="node" type="NodeType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@ -1 +1,103 @@
SUBDIRS = osmocom
nobase_include_HEADERS = \
osmocom/codec/codec.h \
osmocom/core/application.h \
osmocom/core/backtrace.h \
osmocom/core/bits.h \
osmocom/core/bitvec.h \
osmocom/core/conv.h \
osmocom/core/crc16.h \
osmocom/core/crc16gen.h \
osmocom/core/crc32gen.h \
osmocom/core/crc64gen.h \
osmocom/core/crc8gen.h \
osmocom/core/crcgen.h \
osmocom/core/gsmtap.h \
osmocom/core/gsmtap_util.h \
osmocom/core/linuxlist.h \
osmocom/core/linuxrbtree.h \
osmocom/core/logging.h \
osmocom/core/msgb.h \
osmocom/core/panic.h \
osmocom/core/prim.h \
osmocom/core/process.h \
osmocom/core/rate_ctr.h \
osmocom/core/select.h \
osmocom/core/signal.h \
osmocom/core/socket.h \
osmocom/core/statistics.h \
osmocom/core/timer.h \
osmocom/core/utils.h \
osmocom/core/write_queue.h \
osmocom/crypt/auth.h \
osmocom/crypt/gprs_cipher.h \
osmocom/gprs/gprs_bssgp.h \
osmocom/gprs/gprs_msgb.h \
osmocom/gprs/gprs_ns.h \
osmocom/gprs/gprs_ns_frgre.h \
osmocom/gprs/protocol/gsm_08_16.h \
osmocom/gprs/protocol/gsm_08_18.h \
osmocom/gsm/a5.h \
osmocom/gsm/abis_nm.h \
osmocom/gsm/comp128.h \
osmocom/gsm/gan.h \
osmocom/gsm/gsm0411_smc.h \
osmocom/gsm/gsm0411_smr.h \
osmocom/gsm/gsm0411_utils.h \
osmocom/gsm/gsm0480.h \
osmocom/gsm/gsm0502.h \
osmocom/gsm/gsm0808.h \
osmocom/gsm/gsm48.h \
osmocom/gsm/gsm48_ie.h \
osmocom/gsm/gsm_utils.h \
osmocom/gsm/lapd_core.h \
osmocom/gsm/lapdm.h \
osmocom/gsm/mncc.h \
osmocom/gsm/prim.h \
osmocom/gsm/protocol/gsm_03_41.h \
osmocom/gsm/protocol/gsm_04_08.h \
osmocom/gsm/protocol/gsm_04_11.h \
osmocom/gsm/protocol/gsm_04_12.h \
osmocom/gsm/protocol/gsm_04_80.h \
osmocom/gsm/protocol/gsm_08_08.h \
osmocom/gsm/protocol/gsm_08_58.h \
osmocom/gsm/protocol/gsm_12_21.h \
osmocom/gsm/protocol/gsm_44_318.h \
osmocom/gsm/protocol/ipaccess.h \
osmocom/gsm/rsl.h \
osmocom/gsm/rxlev_stat.h \
osmocom/gsm/sysinfo.h \
osmocom/gsm/tlv.h
if ENABLE_PLUGIN
nobase_include_HEADERS += osmocom/core/plugin.h
endif
if ENABLE_TALLOC
nobase_include_HEADERS += osmocom/core/talloc.h
endif
if ENABLE_MSGFILE
nobase_include_HEADERS += osmocom/core/msgfile.h
endif
if ENABLE_SERIAL
nobase_include_HEADERS += osmocom/core/serial.h
endif
if ENABLE_VTY
nobase_include_HEADERS += \
osmocom/vty/buffer.h \
osmocom/vty/command.h \
osmocom/vty/logging.h \
osmocom/vty/misc.h \
osmocom/vty/telnet_interface.h \
osmocom/vty/vector.h \
osmocom/vty/vty.h
endif
noinst_HEADERS = osmocom/core/timer_compat.h
osmocom/core/crc%gen.h: osmocom/core/crcXXgen.h.tpl
$(AM_V_GEN)$(MKDIR_P) $(notdir $@)
$(AM_V_GEN)sed -e's/XX/$*/g' $< > $@

View File

@ -1,5 +0,0 @@
if ENABLE_VTY
SUBDIRS = vty codec crypt gsm core
else
SUBDIRS = codec crypt gsm core
endif

View File

@ -1,3 +0,0 @@
osmocodec_HEADERS = codec.h
osmocodecdir = $(includedir)/osmocom/codec

View File

@ -3,18 +3,18 @@
#include <stdint.h>
extern uint16_t gsm610_bitorder[]; /* FR */
extern uint16_t gsm620_unvoiced_bitorder[]; /* HR unvoiced */
extern uint16_t gsm620_voiced_bitorder[]; /* HR voiced */
extern uint16_t gsm660_bitorder[]; /* EFR */
extern const uint16_t gsm610_bitorder[]; /* FR */
extern const uint16_t gsm620_unvoiced_bitorder[]; /* HR unvoiced */
extern const uint16_t gsm620_voiced_bitorder[]; /* HR voiced */
extern const uint16_t gsm660_bitorder[]; /* EFR */
extern uint16_t gsm690_12_2_bitorder[]; /* AMR 12.2 kbits */
extern uint16_t gsm690_10_2_bitorder[]; /* AMR 10.2 kbits */
extern uint16_t gsm690_7_95_bitorder[]; /* AMR 7.95 kbits */
extern uint16_t gsm690_7_4_bitorder[]; /* AMR 7.4 kbits */
extern uint16_t gsm690_6_7_bitorder[]; /* AMR 6.7 kbits */
extern uint16_t gsm690_5_9_bitorder[]; /* AMR 5.9 kbits */
extern uint16_t gsm690_5_15_bitorder[]; /* AMR 5.15 kbits */
extern uint16_t gsm690_4_75_bitorder[]; /* AMR 4.75 kbits */
extern const uint16_t gsm690_12_2_bitorder[]; /* AMR 12.2 kbits */
extern const uint16_t gsm690_10_2_bitorder[]; /* AMR 10.2 kbits */
extern const uint16_t gsm690_7_95_bitorder[]; /* AMR 7.95 kbits */
extern const uint16_t gsm690_7_4_bitorder[]; /* AMR 7.4 kbits */
extern const uint16_t gsm690_6_7_bitorder[]; /* AMR 6.7 kbits */
extern const uint16_t gsm690_5_9_bitorder[]; /* AMR 5.9 kbits */
extern const uint16_t gsm690_5_15_bitorder[]; /* AMR 5.15 kbits */
extern const uint16_t gsm690_4_75_bitorder[]; /* AMR 4.75 kbits */
#endif /* _OSMOCOM_CODEC_H */

View File

@ -1,31 +0,0 @@
osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h bits.h \
bitvec.h statistics.h utils.h socket.h \
gsmtap.h write_queue.h prim.h \
logging.h rate_ctr.h gsmtap_util.h \
crc16.h panic.h process.h linuxrbtree.h \
backtrace.h conv.h application.h \
crcgen.h crc8gen.h crc16gen.h crc32gen.h crc64gen.h
noinst_HEADERS = timer_compat.h
if ENABLE_PLUGIN
osmocore_HEADERS += plugin.h
endif
if ENABLE_TALLOC
osmocore_HEADERS += talloc.h
endif
if ENABLE_MSGFILE
osmocore_HEADERS += msgfile.h
endif
if ENABLE_SERIAL
osmocore_HEADERS += serial.h
endif
osmocoredir = $(includedir)/osmocom/core
crc%gen.h: crcXXgen.h.tpl
@echo " SED $< -> $@"
@sed -e's/XX/$*/g' $< > $@

View File

@ -2,5 +2,6 @@
#define _OSMO_BACKTRACE_H_
void osmo_generate_backtrace(void);
void osmo_log_backtrace(int subsys, int level);
#endif

View File

@ -73,6 +73,6 @@ uint32_t osmo_revbytebits_8(uint8_t x);
/* \brief reverse the bits of each byte in a given buffer */
void osmo_revbytebits_buf(uint8_t *buf, int len);
/*! }@ */
/*! @} */
#endif /* _OSMO_BITS_H */

View File

@ -65,6 +65,6 @@ int bitvec_get_uint(struct bitvec *bv, int num_bits);
int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n, enum bit_value val);
int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
/*! }@ */
/*! @} */
#endif /* _BITVEC_H */

View File

@ -141,6 +141,6 @@ int osmo_conv_decode(const struct osmo_conv_code *code,
const sbit_t *input, ubit_t *output);
/*! }@ */
/*! @} */
#endif /* __OSMO_CONV_H__ */

View File

@ -52,7 +52,7 @@ void osmo_crcXXgen_set_bits(const struct osmo_crcXXgen_code *code,
const ubit_t *in, int len, ubit_t *crc_bits);
/*! }@ */
/*! @} */
#endif /* __OSMO_CRCXXGEN_H__ */

View File

@ -36,6 +36,6 @@
#include <osmocom/core/crc32gen.h>
#include <osmocom/core/crc64gen.h>
/*! }@ */
/*! @} */
#endif /* __OSMO_CRCGEN_H__ */

View File

@ -41,6 +41,9 @@
#define GSMTAP_TYPE_GB_LLC 0x08 /* GPRS Gb interface: LLC */
#define GSMTAP_TYPE_GB_SNDCP 0x09 /* GPRS Gb interface: SNDCP */
#define GSMTAP_TYPE_GMR1_UM 0x0a /* GMR-1 L2 packets */
#define GSMTAP_TYPE_UMTS_RLC_MAC 0x0b
#define GSMTAP_TYPE_UMTS_RRC 0x0c
/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
@ -128,6 +131,10 @@
/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
#define GSMTAP_UMTS_CH_PCCH 0x01
#define GSMTAP_UMTS_CH_CCCH 0x02
#define GSMTAP_UMTS_CH_DCCH 0x03
/* flags for the ARFCN */
#define GSMTAP_ARFCN_F_PCS 0x8000
#define GSMTAP_ARFCN_F_UPLINK 0x4000

View File

@ -145,7 +145,7 @@ extern struct rb_node *rb_first(const struct rb_root *);
extern struct rb_node *rb_last(const struct rb_root *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
extern void rb_replace_node(struct rb_node *victim, struct rb_node *_new,
struct rb_root *root);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,

View File

@ -28,10 +28,10 @@
#endif
void osmo_vlogp(int subsys, int level, char *file, int line,
void osmo_vlogp(int subsys, int level, const char *file, int line,
int cont, const char *format, va_list ap);
void logp(int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
void logp(int subsys, const char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
/*! \brief Log a new message through the Osmocom logging framework
* \param[in] ss logging subsystem (e.g. \ref DLGLOBAL)
@ -165,7 +165,7 @@ struct log_target {
};
/* use the above macros */
void logp2(int subsys, unsigned int level, char *file,
void logp2(int subsys, unsigned int level, const char *file,
int line, int cont, const char *format, ...)
__attribute__ ((format (printf, 6, 7)));
int log_init(const struct log_info *inf, void *talloc_ctx);
@ -206,6 +206,6 @@ 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 */

View File

@ -72,6 +72,7 @@ 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);
uint16_t msgb_length(const struct msgb *msg);
#ifdef MSGB_DEBUG
#include <osmocom/core/panic.h>
@ -226,8 +227,11 @@ static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
*/
static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
{
unsigned char *tmp = msgb->data;
msgb->data += len;
unsigned char *tmp = msgb->data - len;
if (msgb_length(msgb) < len)
MSGB_ABORT(msgb, "msgb too small to get %u (len %u)\n",
len, msgb_length(msgb));
msgb->tail -= len;
msgb->len -= len;
return tmp;
}
@ -295,6 +299,34 @@ static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
return msgb->data += len;
}
/*! \brief remove uint8 from front of message
* \param[in] msgb message buffer
* \returns 8bit value taken from end of msgb
*/
static inline uint8_t msgb_pull_u8(struct msgb *msgb)
{
uint8_t *space = msgb_pull(msgb, 1);
return space[0];
}
/*! \brief remove uint16 from front of message
* \param[in] msgb message buffer
* \returns 16bit value taken from end of msgb
*/
static inline uint16_t msgb_pull_u16(struct msgb *msgb)
{
uint8_t *space = msgb_pull(msgb, 2);
return space[0] << 8 | space[1];
}
/*! \brief remove uint32 from front of message
* \param[in] msgb message buffer
* \returns 32bit value taken from end of msgb
*/
static inline uint32_t msgb_pull_u32(struct msgb *msgb)
{
uint8_t *space = msgb_pull(msgb, 4);
return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
}
/*! \brief Increase headroom of empty msgb, reducing the tailroom
* \param[in] msg message buffer
* \param[in] len amount of extra octets to be reserved as headroom
@ -362,9 +394,8 @@ static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
/* non inline functions to ease binding */
uint8_t *msgb_data(const struct msgb *msg);
uint16_t msgb_length(const struct msgb *msg);
void msgb_set_talloc_ctx(void *ctx);
/*! }@ */
/*! @} */
#endif /* _MSGB_H */

View File

@ -84,5 +84,5 @@ 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);
const struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name);
/*! }@ */
/*! @} */
#endif /* RATE_CTR_H */

View File

@ -40,6 +40,6 @@ int osmo_fd_register(struct osmo_fd *fd);
void osmo_fd_unregister(struct osmo_fd *fd);
int osmo_select_main(int polling);
/*! }@ */
/*! @} */
#endif /* _BSC_SELECT_H */

View File

@ -38,6 +38,6 @@ int osmo_serial_set_baudrate(int fd, speed_t baudrate);
int osmo_serial_set_custom_baudrate(int fd, int baudrate);
int osmo_serial_clear_custom_baudrate(int fd);
/*! }@ */
/*! @} */
#endif /* __OSMO_SERIAL_H__ */

View File

@ -18,6 +18,7 @@
enum {
SS_L_GLOBAL = OSMO_SIGNAL_SS_RESERVED,
SS_L_INPUT,
SS_L_NS,
};
/* application-defined signal types. */
@ -40,6 +41,6 @@ void osmo_signal_unregister_handler(unsigned int subsys, osmo_signal_cbfn *cbfn,
/* Dispatch */
void osmo_signal_dispatch(unsigned int subsys, unsigned int signal, void *signal_data);
/*! }@ */
/*! @} */
#endif /* OSMO_SIGNAL_H */

View File

@ -30,6 +30,6 @@ int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen);
/*! }@ */
/*! @} */
#endif /* _OSMOCORE_SOCKET_H */

View File

@ -73,7 +73,9 @@ void osmo_timer_del(struct osmo_timer_list *timer);
int osmo_timer_pending(struct osmo_timer_list *timer);
int osmo_timer_remaining(const struct osmo_timer_list *timer,
const struct timeval *now,
struct timeval *remaining);
/*
* internal timer list management
*/
@ -82,6 +84,6 @@ void osmo_timers_prepare(void);
int osmo_timers_update(void);
int osmo_timers_check(void);
/*! }@ */
/*! @} */
#endif

View File

@ -74,6 +74,6 @@
#endif
/*! }@ */
/*! @} */
#endif /* TIMER_COMPAT_H */

View File

@ -10,9 +10,9 @@
/*! \brief Determine number of elements in an array of static size */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/*! \brief Return the maximum of two specified values */
#define OSMO_MAX(a, b) (a) >= (b) ? (a) : (b)
#define OSMO_MAX(a, b) ((a) >= (b) ? (a) : (b))
/*! \brief Return the minimum of two specified values */
#define OSMO_MIN(a, b) (a) >= (b) ? (b) : (a)
#define OSMO_MIN(a, b) ((a) >= (b) ? (b) : (a))
#include <stdint.h>
@ -51,6 +51,6 @@ do { \
rem -= ret; \
} while (0)
/*! }@ */
/*! @} */
#endif

View File

@ -58,6 +58,6 @@ void osmo_wqueue_clear(struct osmo_wqueue *queue);
int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data);
int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what);
/*! }@ */
/*! @} */
#endif

View File

@ -1,3 +0,0 @@
osmocrypt_HEADERS = gprs_cipher.h auth.h
osmocryptdir = $(includedir)/osmocom/crypt

View File

@ -1,11 +1,17 @@
#ifndef _OSMOCRYPTO_AUTH_H
#define _OSMOCRYPTO_AUTH_H
/*! \addtogroup auth
* @{
*/
/*! \file auth.h */
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
/*! \brief Authentication Type */
/*! \brief Authentication Type (GSM/UMTS) */
enum osmo_sub_auth_type {
OSMO_AUTH_TYPE_NONE = 0x00,
OSMO_AUTH_TYPE_GSM = 0x01,
@ -29,42 +35,44 @@ struct osmo_sub_auth_data {
enum osmo_auth_algo algo;
union {
struct {
uint8_t opc[16];
uint8_t k[16];
uint8_t opc[16]; /*!< operator invariant value */
uint8_t k[16]; /*!< secret key of the subscriber */
uint8_t amf[2];
uint64_t sqn;
int opc_is_op;
uint64_t sqn; /*!< sequence number */
int opc_is_op; /*!< is the OPC field OPC (0) or OP (1) ? */
} umts;
struct {
uint8_t ki[16];
uint8_t ki[16]; /*!< secret key */
} gsm;
} u;
};
/* data structure describing a computed auth vector, generated by AuC */
struct osmo_auth_vector {
uint8_t rand[16];
uint8_t autn[16];
uint8_t ck[16];
uint8_t ik[16];
uint8_t res[16];
uint8_t res_len;
uint8_t kc[8];
uint8_t sres[4];
uint8_t rand[16]; /*!< random challenge */
uint8_t autn[16]; /*!< authentication nonce */
uint8_t ck[16]; /*!< ciphering key */
uint8_t ik[16]; /*!< integrity key */
uint8_t res[16]; /*!< authentication result */
uint8_t res_len; /*!< length (in bytes) of res */
uint8_t kc[8]; /*!< Kc for GSM encryption (A5) */
uint8_t sres[4]; /*!< authentication result for GSM */
uint32_t auth_types; /*!< bitmask of OSMO_AUTH_TYPE_* */
};
/* \brief An implementation of an authentication algorithm */
struct osmo_auth_impl {
struct llist_head list;
enum osmo_auth_algo algo;
const char *name;
unsigned int priority;
enum osmo_auth_algo algo; /*!< algorithm we implement */
const char *name; /*!< name of the implementation */
unsigned int priority; /*!< priority value (resp. othe implementations */
/*! \brief callback for generate authentication vectors */
int (*gen_vec)(struct osmo_auth_vector *vec,
struct osmo_sub_auth_data *aud,
const uint8_t *_rand);
/* \brief callback for generationg auth vectors + re-sync */
int (*gen_vec_auts)(struct osmo_auth_vector *vec,
struct osmo_sub_auth_data *aud,
const uint8_t *rand_auts, const uint8_t *auts,
@ -89,3 +97,5 @@ const char *osmo_auth_alg_name(enum osmo_auth_algo alg);
enum osmo_auth_algo osmo_auth_alg_parse(const char *name);
#endif /* _OSMOCRYPTO_AUTH_H */
/* @} */

View File

@ -0,0 +1,211 @@
#ifndef _GPRS_BSSGP_H
#define _GPRS_BSSGP_H
#include <stdint.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/prim.h>
#include <osmocom/gprs/protocol/gsm_08_18.h>
/* gprs_bssgp_util.c */
extern struct gprs_ns_inst *bssgp_nsi;
struct msgb *bssgp_msgb_alloc(void);
const char *bssgp_cause_str(enum gprs_bssgp_cause cause);
/* Transmit a simple response such as BLOCK/UNBLOCK/RESET ACK/NACK */
int bssgp_tx_simple_bvci(uint8_t pdu_type, uint16_t nsei,
uint16_t bvci, uint16_t ns_bvci);
/* Chapter 10.4.14: Status */
int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg);
enum bssgp_prim {
PRIM_BSSGP_DL_UD,
PRIM_BSSGP_UL_UD,
PRIM_BSSGP_PTM_UD,
PRIM_BSSGP_GMM_SUSPEND,
PRIM_BSSGP_GMM_RESUME,
PRIM_BSSGP_GMM_PAGING,
PRIM_NM_FLUSH_LL,
PRIM_NM_LLC_DISCARDED,
PRIM_NM_BVC_RESET,
PRIM_NM_BVC_BLOCK,
PRIM_NM_BVC_UNBLOCK,
};
struct osmo_bssgp_prim {
struct osmo_prim_hdr oph;
/* common fields */
uint16_t nsei;
uint16_t bvci;
uint32_t tlli;
struct tlv_parsed *tp;
struct gprs_ra_id *ra_id;
/* specific fields */
union {
struct {
uint8_t suspend_ref;
} resume;
} u;
};
/* gprs_bssgp.c */
/*! \brief BSSGP flow control (SGSN side) According to Section 8.2 */
struct bssgp_flow_control {
uint32_t bucket_size_max; /*!< maximum size of the bucket (octets) */
uint32_t bucket_leak_rate; /*!< leak rate of the bucket (octets/sec) */
uint32_t bucket_counter; /*!< number of tokens in the bucket */
struct timeval time_last_pdu; /*!< timestamp of last PDU sent */
/* the built-in queue */
uint32_t max_queue_depth; /*!< how many packets to queue (mgs) */
uint32_t queue_depth; /*!< current length of queue (msgs) */
struct llist_head queue; /*!< linked list of msgb's */
struct osmo_timer_list timer; /*!< timer-based dequeueing */
/*! callback to be called at output of flow control */
int (*out_cb)(struct bssgp_flow_control *fc, struct msgb *msg,
uint32_t llc_pdu_len, void *priv);
};
#define BVC_S_BLOCKED 0x0001
/* The per-BTS context that we keep on the SGSN side of the BSSGP link */
struct bssgp_bvc_ctx {
struct llist_head list;
struct gprs_ra_id ra_id; /*!< parsed RA ID of the remote BTS */
uint16_t cell_id; /*!< Cell ID of the remote BTS */
/* NSEI and BVCI of underlying Gb link. Together they
* uniquely identify a link to a BTS (5.4.4) */
uint16_t bvci;
uint16_t nsei;
uint32_t state;
struct rate_ctr_group *ctrg;
struct bssgp_flow_control *fc;
/*! default maximum size of per-MS bucket in octets */
uint32_t bmax_default_ms;
/*! default bucket leak rate of per-MS bucket in octests/s */
uint32_t r_default_ms;
/* we might want to add this as a shortcut later, avoiding the NSVC
* lookup for every packet, similar to a routing cache */
//struct gprs_nsvc *nsvc;
};
extern struct llist_head bssgp_bvc_ctxts;
/* Find a BTS Context based on parsed RA ID and Cell ID */
struct bssgp_bvc_ctx *btsctx_by_raid_cid(const struct gprs_ra_id *raid, uint16_t cid);
/* Find a BTS context based on BVCI+NSEI tuple */
struct bssgp_bvc_ctx *btsctx_by_bvci_nsei(uint16_t bvci, uint16_t nsei);
#define BVC_F_BLOCKED 0x0001
enum bssgp_ctr {
BSSGP_CTR_PKTS_IN,
BSSGP_CTR_PKTS_OUT,
BSSGP_CTR_BYTES_IN,
BSSGP_CTR_BYTES_OUT,
BSSGP_CTR_BLOCKED,
BSSGP_CTR_DISCARDED,
};
#include <osmocom/gsm/tlv.h>
#include <osmocom/gprs/gprs_msgb.h>
/* BSSGP-UL-UNITDATA.ind */
int bssgp_rcvmsg(struct msgb *msg);
/* BSSGP-DL-UNITDATA.req */
struct bssgp_lv {
uint16_t len;
uint8_t *v;
};
/* parameters for BSSGP downlink userdata transmission */
struct bssgp_dl_ud_par {
uint32_t *tlli;
char *imsi;
struct bssgp_flow_control *fc;
uint16_t drx_parms;
/* FIXME: priority */
struct bssgp_lv ms_ra_cap;
uint8_t qos_profile[3];
};
int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
struct bssgp_dl_ud_par *dup);
uint16_t bssgp_parse_cell_id(struct gprs_ra_id *raid, const uint8_t *buf);
int bssgp_create_cell_id(uint8_t *buf, const struct gprs_ra_id *raid,
uint16_t cid);
/* Wrapper around TLV parser to parse BSSGP IEs */
static inline int bssgp_tlv_parse(struct tlv_parsed *tp, uint8_t *buf, int len)
{
return tlv_parse(tp, &tvlv_att_def, buf, len, 0, 0);
}
/*! \brief BSSGP Paging mode */
enum bssgp_paging_mode {
BSSGP_PAGING_PS,
BSSGP_PAGING_CS,
};
/*! \brief BSSGP Paging scope */
enum bssgp_paging_scope {
BSSGP_PAGING_BSS_AREA, /*!< all cells in BSS */
BSSGP_PAGING_LOCATION_AREA, /*!< all cells in LA */
BSSGP_PAGING_ROUTEING_AREA, /*!< all cells in RA */
BSSGP_PAGING_BVCI, /*!< one cell */
};
/*! \brief BSSGP paging information */
struct bssgp_paging_info {
enum bssgp_paging_mode mode; /*!< CS or PS paging */
enum bssgp_paging_scope scope; /*!< bssgp_paging_scope */
struct gprs_ra_id raid; /*!< RA Identifier */
uint16_t bvci; /*!< BVCI */
char *imsi; /*!< IMSI, if any */
uint32_t *ptmsi; /*!< P-TMSI, if any */
uint16_t drx_params; /*!< DRX parameters */
uint8_t qos[3]; /*!< QoS parameters */
};
/* Send a single GMM-PAGING.req to a given NSEI/NS-BVCI */
int bssgp_tx_paging(uint16_t nsei, uint16_t ns_bvci,
struct bssgp_paging_info *pinfo);
void bssgp_fc_init(struct bssgp_flow_control *fc,
uint32_t bucket_size_max, uint32_t bucket_leak_rate,
uint32_t max_queue_depth,
int (*out_cb)(struct bssgp_flow_control *fc, struct msgb *msg,
uint32_t llc_pdu_len, void *priv));
/* input function of the flow control implementation, called first
* for the MM flow control, and then as the MM flow control output
* callback in order to perform BVC flow control */
int bssgp_fc_in(struct bssgp_flow_control *fc, struct msgb *msg,
uint32_t llc_pdu_len, void *priv);
/* Initialize the Flow Control parameters for a new MS according to
* default values for the BVC specified by BVCI and NSEI */
int bssgp_fc_ms_init(struct bssgp_flow_control *fc_ms, uint16_t bvci,
uint16_t nsei, uint32_t max_queue_depth);
/* gprs_bssgp_vty.c */
int bssgp_vty_init(void);
void bssgp_set_log_ss(int ss);
int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
#endif /* _GPRS_BSSGP_H */

View File

@ -0,0 +1,37 @@
#ifndef _LIBGB_MSGB_H
#define _LIBGB_MSGB_H
#include <stdint.h>
/* the data structure stored in msgb->cb for libgb apps */
struct libgb_msgb_cb {
unsigned char *bssgph;
unsigned char *llch;
/* Cell Identifier */
unsigned char *bssgp_cell_id;
/* Identifiers of a BTS, equal to 'struct bssgp_bts_ctx' */
uint16_t nsei;
uint16_t bvci;
/* Identifier of a MS (inside BTS), equal to 'struct sgsn_mm_ctx' */
uint32_t tlli;
} __attribute__((packed));
#define LIBGB_MSGB_CB(__msgb) ((struct libgb_msgb_cb *)&((__msgb)->cb[0]))
#define msgb_tlli(__x) LIBGB_MSGB_CB(__x)->tlli
#define msgb_nsei(__x) LIBGB_MSGB_CB(__x)->nsei
#define msgb_bvci(__x) LIBGB_MSGB_CB(__x)->bvci
#define msgb_gmmh(__x) (__x)->l3h
#define msgb_bssgph(__x) LIBGB_MSGB_CB(__x)->bssgph
#define msgb_bssgp_len(__x) ((__x)->tail - (uint8_t *)msgb_bssgph(__x))
#define msgb_bcid(__x) LIBGB_MSGB_CB(__x)->bssgp_cell_id
#define msgb_llch(__x) LIBGB_MSGB_CB(__x)->llch
/* logging contexts */
#define GPRS_CTX_NSVC 0
#define GPRS_CTX_BVC 1
#include <osmocom/core/logging.h>
int gprs_log_filter_fn(const struct log_context *ctx,
struct log_target *tar);
#endif

View File

@ -0,0 +1,189 @@
#ifndef _GPRS_NS_H
#define _GPRS_NS_H
#include <stdint.h>
/* Our Implementation */
#include <netinet/in.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/select.h>
#include <osmocom/gprs/gprs_msgb.h>
#include <osmocom/gprs/protocol/gsm_08_16.h>
#define NS_TIMERS_COUNT 7
#define NS_TIMERS "(tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries)"
#define NS_TIMERS_HELP \
"(un)blocking Timer (Tns-block) timeout\n" \
"(un)blocking Timer (Tns-block) number of retries\n" \
"Reset Timer (Tns-reset) timeout\n" \
"Reset Timer (Tns-reset) number of retries\n" \
"Test Timer (Tns-test) timeout\n" \
"Alive Timer (Tns-alive) timeout\n" \
"Alive Timer (Tns-alive) number of retries\n"
enum ns_timeout {
NS_TOUT_TNS_BLOCK,
NS_TOUT_TNS_BLOCK_RETRIES,
NS_TOUT_TNS_RESET,
NS_TOUT_TNS_RESET_RETRIES,
NS_TOUT_TNS_TEST,
NS_TOUT_TNS_ALIVE,
NS_TOUT_TNS_ALIVE_RETRIES,
};
#define NSE_S_BLOCKED 0x0001
#define NSE_S_ALIVE 0x0002
/*! \brief Osmocom NS link layer types */
enum gprs_ns_ll {
GPRS_NS_LL_UDP, /*!< NS/UDP/IP */
GPRS_NS_LL_E1, /*!< NS/E1 */
GPRS_NS_LL_FR_GRE, /*!< NS/FR/GRE/IP */
};
/*! \brief Osmoco NS events */
enum gprs_ns_evt {
GPRS_NS_EVT_UNIT_DATA,
};
struct gprs_nsvc;
/*! \brief Osmocom GPRS callback function type */
typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
struct msgb *msg, uint16_t bvci);
/*! \brief An instance of the NS protocol stack */
struct gprs_ns_inst {
/*! \brief callback to the user for incoming UNIT DATA IND */
gprs_ns_cb_t *cb;
/*! \brief linked lists of all NSVC in this instance */
struct llist_head gprs_nsvcs;
/*! \brief a NSVC object that's needed to deal with packets for
* unknown NSVC */
struct gprs_nsvc *unknown_nsvc;
uint16_t timeout[NS_TIMERS_COUNT];
/*! \brief NS-over-IP specific bits */
struct {
struct osmo_fd fd;
uint32_t local_ip;
uint16_t local_port;
} nsip;
/*! \brief NS-over-FR-over-GRE-over-IP specific bits */
struct {
struct osmo_fd fd;
uint32_t local_ip;
unsigned int enabled:1;
} frgre;
};
enum nsvc_timer_mode {
/* standard timers */
NSVC_TIMER_TNS_TEST,
NSVC_TIMER_TNS_ALIVE,
NSVC_TIMER_TNS_RESET,
_NSVC_TIMER_NR,
};
/*! \brief Structure representing a single NS-VC */
struct gprs_nsvc {
/*! \brief list of NS-VCs within NS Instance */
struct llist_head list;
/*! \brief pointer to NS Instance */
struct gprs_ns_inst *nsi;
uint16_t nsei; /*! \brief end-to-end significance */
uint16_t nsvci; /*! \brief uniquely identifies NS-VC at SGSN */
uint32_t state;
uint32_t remote_state;
struct osmo_timer_list timer;
enum nsvc_timer_mode timer_mode;
int alive_retries;
unsigned int remote_end_is_sgsn:1;
unsigned int persistent:1;
struct rate_ctr_group *ctrg;
/*! \brief which link-layer are we based on? */
enum gprs_ns_ll ll;
union {
struct {
struct sockaddr_in bts_addr;
} ip;
struct {
struct sockaddr_in bts_addr;
} frgre;
};
};
/* Create a new NS protocol instance */
struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb, void *ctx);
/* Destroy a NS protocol instance */
void gprs_ns_destroy(struct gprs_ns_inst *nsi);
/* Listen for incoming GPRS packets via NS/UDP */
int gprs_ns_nsip_listen(struct gprs_ns_inst *nsi);
/* Establish a connection (from the BSS) to the SGSN */
struct gprs_nsvc *gprs_ns_nsip_connect(struct gprs_ns_inst *nsi,
struct sockaddr_in *dest,
uint16_t nsei, uint16_t nsvci);
struct sockaddr_in;
/* main function for higher layers (BSSGP) to send NS messages */
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause);
int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause);
int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc);
/* Listen for incoming GPRS packets via NS/FR/GRE */
int gprs_ns_frgre_listen(struct gprs_ns_inst *nsi);
struct gprs_nsvc *gprs_nsvc_create(struct gprs_ns_inst *nsi, uint16_t nsvci);
void gprs_nsvc_delete(struct gprs_nsvc *nsvc);
struct gprs_nsvc *gprs_nsvc_by_nsei(struct gprs_ns_inst *nsi, uint16_t nsei);
struct gprs_nsvc *gprs_nsvc_by_nsvci(struct gprs_ns_inst *nsi, uint16_t nsvci);
/* Initiate a RESET procedure (including timer start, ...)*/
void gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause);
/* Add NS-specific VTY stuff */
int gprs_ns_vty_init(struct gprs_ns_inst *nsi);
#define NS_ALLOC_SIZE 2048
#define NS_ALLOC_HEADROOM 20
static inline struct msgb *gprs_ns_msgb_alloc(void)
{
return msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM, "GPRS/NS");
}
enum signal_ns {
S_NS_RESET,
S_NS_BLOCK,
S_NS_UNBLOCK,
S_NS_ALIVE_EXP, /* Tns-alive expired more than N times */
};
struct ns_signal_data {
struct gprs_nsvc *nsvc;
uint8_t cause;
};
void gprs_ns_set_log_ss(int ss);
/*! }@ */
#endif

View File

@ -0,0 +1,6 @@
#ifndef _GPRS_NS_FRGRE_H
#define _GPRS_NS_FRGRE_H
int gprs_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg);
#endif

View File

@ -0,0 +1,85 @@
#ifndef _OSMO_08_16_H
#define _OSMO_08_16_H
/* GPRS Networks Service (NS) messages on the Gb interface
* 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05)
* 3GPP TS 48.016 version 6.5.0 Release 6 / ETSI TS 148 016 V6.5.0 (2005-11) */
#include <stdint.h>
/*! \addtogroup libgb
* @{
*/
/*! \file gprs_ns.h */
/*! \brief Common header of GPRS NS */
struct gprs_ns_hdr {
uint8_t pdu_type; /*!< NS PDU type */
uint8_t data[0]; /*!< variable-length payload */
} __attribute__((packed));
/*! \brief NS PDU Type (TS 08.16, Section 10.3.7, Table 14) */
enum ns_pdu_type {
NS_PDUT_UNITDATA = 0x00,
NS_PDUT_RESET = 0x02,
NS_PDUT_RESET_ACK = 0x03,
NS_PDUT_BLOCK = 0x04,
NS_PDUT_BLOCK_ACK = 0x05,
NS_PDUT_UNBLOCK = 0x06,
NS_PDUT_UNBLOCK_ACK = 0x07,
NS_PDUT_STATUS = 0x08,
NS_PDUT_ALIVE = 0x0a,
NS_PDUT_ALIVE_ACK = 0x0b,
/* TS 48.016 Section 10.3.7, Table 10.3.7.1 */
SNS_PDUT_ACK = 0x0c,
SNS_PDUT_ADD = 0x0d,
SNS_PDUT_CHANGE_WEIGHT = 0x0e,
SNS_PDUT_CONFIG = 0x0f,
SNS_PDUT_CONFIG_ACK = 0x10,
SNS_PDUT_DELETE = 0x11,
SNS_PDUT_SIZE = 0x12,
SNS_PDUT_SIZE_ACK = 0x13,
};
/*! \brief NS Control IE (TS 08.16, Section 10.3, Table 12) */
enum ns_ctrl_ie {
NS_IE_CAUSE = 0x00,
NS_IE_VCI = 0x01,
NS_IE_PDU = 0x02,
NS_IE_BVCI = 0x03,
NS_IE_NSEI = 0x04,
/* TS 48.016 Section 10.3, Table 10.3.1 */
NS_IE_IPv4_LIST = 0x05,
NS_IE_IPv6_LIST = 0x06,
NS_IE_MAX_NR_NSVC = 0x07,
NS_IE_IPv4_EP_NR = 0x08,
NS_IE_IPv6_EP_NR = 0x09,
NS_IE_RESET_FLAG = 0x0a,
NS_IE_IP_ADDR = 0x0b,
};
/*! \brief NS Cause (TS 08.16, Section 10.3.2, Table 13) */
enum ns_cause {
NS_CAUSE_TRANSIT_FAIL = 0x00,
NS_CAUSE_OM_INTERVENTION = 0x01,
NS_CAUSE_EQUIP_FAIL = 0x02,
NS_CAUSE_NSVC_BLOCKED = 0x03,
NS_CAUSE_NSVC_UNKNOWN = 0x04,
NS_CAUSE_BVCI_UNKNOWN = 0x05,
NS_CAUSE_SEM_INCORR_PDU = 0x08,
NS_CAUSE_PDU_INCOMP_PSTATE = 0x0a,
NS_CAUSE_PROTO_ERR_UNSPEC = 0x0b,
NS_CAUSE_INVAL_ESSENT_IE = 0x0c,
NS_CAUSE_MISSING_ESSENT_IE = 0x0d,
/* TS 48.016 Section 10.3.2, Table 10.3.2.1 */
NS_CAUSE_INVAL_NR_IPv4_EP = 0x0e,
NS_CAUSE_INVAL_NR_IPv6_EP = 0x0f,
NS_CAUSE_INVAL_NR_NS_VC = 0x10,
NS_CAUSE_INVAL_WEIGH = 0x11,
NS_CAUSE_UNKN_IP_EP = 0x12,
NS_CAUSE_UNKN_IP_ADDR = 0x13,
NS_CAUSE_UNKN_IP_TEST_FAILED = 0x14,
};
#endif

View File

@ -0,0 +1,144 @@
#ifndef _OSMO_08_18_H
#define _OSMO_08_18_H
#include <stdint.h>
/*! \brief Fixed BVCI definitions (Section 5.4.1) */
#define BVCI_SIGNALLING 0x0000
#define BVCI_PTM 0x0001
/*! \brief BSSGP PDU types (Section 11.3.26 / Table 11.27) */
enum bssgp_pdu_type {
/* PDUs between RL and BSSGP SAPs */
BSSGP_PDUT_DL_UNITDATA = 0x00,
BSSGP_PDUT_UL_UNITDATA = 0x01,
BSSGP_PDUT_RA_CAPABILITY = 0x02,
BSSGP_PDUT_PTM_UNITDATA = 0x03,
/* PDUs between GMM SAPs */
BSSGP_PDUT_PAGING_PS = 0x06,
BSSGP_PDUT_PAGING_CS = 0x07,
BSSGP_PDUT_RA_CAPA_UDPATE = 0x08,
BSSGP_PDUT_RA_CAPA_UPDATE_ACK = 0x09,
BSSGP_PDUT_RADIO_STATUS = 0x0a,
BSSGP_PDUT_SUSPEND = 0x0b,
BSSGP_PDUT_SUSPEND_ACK = 0x0c,
BSSGP_PDUT_SUSPEND_NACK = 0x0d,
BSSGP_PDUT_RESUME = 0x0e,
BSSGP_PDUT_RESUME_ACK = 0x0f,
BSSGP_PDUT_RESUME_NACK = 0x10,
/* PDus between NM SAPs */
BSSGP_PDUT_BVC_BLOCK = 0x20,
BSSGP_PDUT_BVC_BLOCK_ACK = 0x21,
BSSGP_PDUT_BVC_RESET = 0x22,
BSSGP_PDUT_BVC_RESET_ACK = 0x23,
BSSGP_PDUT_BVC_UNBLOCK = 0x24,
BSSGP_PDUT_BVC_UNBLOCK_ACK = 0x25,
BSSGP_PDUT_FLOW_CONTROL_BVC = 0x26,
BSSGP_PDUT_FLOW_CONTROL_BVC_ACK = 0x27,
BSSGP_PDUT_FLOW_CONTROL_MS = 0x28,
BSSGP_PDUT_FLOW_CONTROL_MS_ACK = 0x29,
BSSGP_PDUT_FLUSH_LL = 0x2a,
BSSGP_PDUT_FLUSH_LL_ACK = 0x2b,
BSSGP_PDUT_LLC_DISCARD = 0x2c,
BSSGP_PDUT_SGSN_INVOKE_TRACE = 0x40,
BSSGP_PDUT_STATUS = 0x41,
/* PDUs between PFM SAP's */
BSSGP_PDUT_DOWNLOAD_BSS_PFC = 0x50,
BSSGP_PDUT_CREATE_BSS_PFC = 0x51,
BSSGP_PDUT_CREATE_BSS_PFC_ACK = 0x52,
BSSGP_PDUT_CREATE_BSS_PFC_NACK = 0x53,
BSSGP_PDUT_MODIFY_BSS_PFC = 0x54,
BSSGP_PDUT_MODIFY_BSS_PFC_ACK = 0x55,
BSSGP_PDUT_DELETE_BSS_PFC = 0x56,
BSSGP_PDUT_DELETE_BSS_PFC_ACK = 0x57,
};
/*! \brief BSSGP User-Data header (Section 10.2.1 and 10.2.2) */
struct bssgp_ud_hdr {
uint8_t pdu_type; /*!< BSSGP PDU type */
uint32_t tlli; /*!< Temporary Link-Local Identifier */
uint8_t qos_profile[3]; /*!< QoS profile */
uint8_t data[0]; /* optional/conditional IEs as TLVs */
} __attribute__((packed));
/*! \brief BSSGP normal header */
struct bssgp_normal_hdr {
uint8_t pdu_type; /*!< BSSGP PDU type */
uint8_t data[0]; /*!< optional/conditional IEs as TLVs */
};
/*! \brief BSSGP Information Element Identifiers */
enum bssgp_iei_type {
BSSGP_IE_ALIGNMENT = 0x00,
BSSGP_IE_BMAX_DEFAULT_MS = 0x01,
BSSGP_IE_BSS_AREA_ID = 0x02,
BSSGP_IE_BUCKET_LEAK_RATE = 0x03,
BSSGP_IE_BVCI = 0x04,
BSSGP_IE_BVC_BUCKET_SIZE = 0x05,
BSSGP_IE_BVC_MEASUREMENT = 0x06,
BSSGP_IE_CAUSE = 0x07,
BSSGP_IE_CELL_ID = 0x08,
BSSGP_IE_CHAN_NEEDED = 0x09,
BSSGP_IE_DRX_PARAMS = 0x0a,
BSSGP_IE_EMLPP_PRIO = 0x0b,
BSSGP_IE_FLUSH_ACTION = 0x0c,
BSSGP_IE_IMSI = 0x0d,
BSSGP_IE_LLC_PDU = 0x0e,
BSSGP_IE_LLC_FRAMES_DISCARDED = 0x0f,
BSSGP_IE_LOCATION_AREA = 0x10,
BSSGP_IE_MOBILE_ID = 0x11,
BSSGP_IE_MS_BUCKET_SIZE = 0x12,
BSSGP_IE_MS_RADIO_ACCESS_CAP = 0x13,
BSSGP_IE_OMC_ID = 0x14,
BSSGP_IE_PDU_IN_ERROR = 0x15,
BSSGP_IE_PDU_LIFETIME = 0x16,
BSSGP_IE_PRIORITY = 0x17,
BSSGP_IE_QOS_PROFILE = 0x18,
BSSGP_IE_RADIO_CAUSE = 0x19,
BSSGP_IE_RA_CAP_UPD_CAUSE = 0x1a,
BSSGP_IE_ROUTEING_AREA = 0x1b,
BSSGP_IE_R_DEFAULT_MS = 0x1c,
BSSGP_IE_SUSPEND_REF_NR = 0x1d,
BSSGP_IE_TAG = 0x1e,
BSSGP_IE_TLLI = 0x1f,
BSSGP_IE_TMSI = 0x20,
BSSGP_IE_TRACE_REFERENC = 0x21,
BSSGP_IE_TRACE_TYPE = 0x22,
BSSGP_IE_TRANSACTION_ID = 0x23,
BSSGP_IE_TRIGGER_ID = 0x24,
BSSGP_IE_NUM_OCT_AFF = 0x25,
BSSGP_IE_LSA_ID_LIST = 0x26,
BSSGP_IE_LSA_INFORMATION = 0x27,
BSSGP_IE_PACKET_FLOW_ID = 0x28,
BSSGP_IE_PACKET_FLOW_TIMER = 0x29,
BSSGP_IE_AGG_BSS_QOS_PROFILE = 0x3a,
BSSGP_IE_FEATURE_BITMAP = 0x3b,
BSSGP_IE_BUCKET_FULL_RATIO = 0x3c,
BSSGP_IE_SERVICE_UTRAN_CCO = 0x3d,
};
/*! \brief Cause coding (Section 11.3.8 / Table 11.10) */
enum gprs_bssgp_cause {
BSSGP_CAUSE_PROC_OVERLOAD = 0x00,
BSSGP_CAUSE_EQUIP_FAIL = 0x01,
BSSGP_CAUSE_TRASIT_NET_FAIL = 0x02,
BSSGP_CAUSE_CAPA_GREATER_0KPBS = 0x03,
BSSGP_CAUSE_UNKNOWN_MS = 0x04,
BSSGP_CAUSE_UNKNOWN_BVCI = 0x05,
BSSGP_CAUSE_CELL_TRAF_CONG = 0x06,
BSSGP_CAUSE_SGSN_CONG = 0x07,
BSSGP_CAUSE_OML_INTERV = 0x08,
BSSGP_CAUSE_BVCI_BLOCKED = 0x09,
BSSGP_CAUSE_PFC_CREATE_FAIL = 0x0a,
BSSGP_CAUSE_SEM_INCORR_PDU = 0x20,
BSSGP_CAUSE_INV_MAND_INF = 0x21,
BSSGP_CAUSE_MISSING_MAND_IE = 0x22,
BSSGP_CAUSE_MISSING_COND_IE = 0x23,
BSSGP_CAUSE_UNEXP_COND_IE = 0x24,
BSSGP_CAUSE_COND_IE_ERR = 0x25,
BSSGP_CAUSE_PDU_INCOMP_STATE = 0x26,
BSSGP_CAUSE_PROTO_ERR_UNSPEC = 0x27,
BSSGP_CAUSE_PDU_INCOMP_FEAT = 0x28,
};
#endif

View File

@ -1,8 +0,0 @@
osmogsm_HEADERS = a5.h comp128.h gsm0808.h gsm48_ie.h mncc.h rxlev_stat.h \
gsm0480.h gsm48.h gsm_utils.h rsl.h tlv.h abis_nm.h \
sysinfo.h prim.h gsm0502.h lapd_core.h lapdm.h \
gsm0411_utils.h gsm0411_smc.h gsm0411_smr.h
SUBDIRS = protocol
osmogsmdir = $(includedir)/osmocom/gsm

View File

@ -58,6 +58,6 @@ void osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
void osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
void osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
/*! }@ */
/*! @} */
#endif /* __OSMO_A5_H__ */

View File

@ -35,6 +35,6 @@ void abis_nm_debugp_foh(int ss, struct abis_om_fom_hdr *foh);
int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan);
enum abis_nm_chan_comb abis_nm_pchan4chcomb(uint8_t chcomb);
/*! }@ */
/*! @} */
#endif /* _OSMO_GSM_ABIS_NM_H */

View File

@ -0,0 +1,9 @@
#ifndef _OSMO_GSM_GAN_H
#define _OSMO_GSM_GAN_H
#include <osmocom/core/utils.h>
extern const struct value_string gan_msgt_vals[];
static const struct value_string gan_pdisc_vals[];
#endif

View File

@ -8,7 +8,7 @@
#define MAX_LEN_USSD_STRING 31
struct ussd_request {
uint8_t text[MAX_LEN_USSD_STRING + 1];
char text[MAX_LEN_USSD_STRING + 1];
uint8_t transaction_id;
uint8_t invoke_id;
};

View File

@ -20,6 +20,8 @@ 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);
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
uint16_t *mnc, uint16_t *lac);
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);

View File

@ -143,6 +143,7 @@ enum gsm_chan_t {
GSM_LCHAN_TCH_H,
GSM_LCHAN_UNKNOWN,
GSM_LCHAN_CCCH,
GSM_LCHAN_PDTCH,
_GSM_LCHAN_MAX
};

View File

@ -157,6 +157,6 @@ void lapdm_channel_set_flags(struct lapdm_channel *lc, unsigned int flags);
int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp);
/*! }@ */
/*! @} */
#endif /* _OSMOCOM_LAPDM_H */

View File

@ -1,6 +1,8 @@
#ifndef _OSMOCORE_MNCC_H
#define _OSMOCORE_MNCC_H
#include <osmocom/gsm/protocol/gsm_04_08.h>
#define GSM_MAX_FACILITY 128
#define GSM_MAX_SSVERSION 128
#define GSM_MAX_USERUSER 128
@ -13,6 +15,18 @@ struct gsm_mncc_bearer_cap {
int radio; /* Radio Channel Requirement */
int speech_ctm; /* CTM text telephony indication */
int speech_ver[8]; /* Speech version indication */
struct {
enum gsm48_bcap_ra rate_adaption;
enum gsm48_bcap_sig_access sig_access;
int async;
int nr_stop_bits;
int nr_data_bits;
enum gsm48_bcap_user_rate user_rate;
enum gsm48_bcap_parity parity;
enum gsm48_bcap_interm_rate interm_rate;
enum gsm48_bcap_transp transp;
enum gsm48_bcap_modem_type modem_type;
} data;
};
struct gsm_mncc_number {

View File

@ -8,6 +8,11 @@ enum osmo_gsm_sap {
SAP_GSM_PH = _SAP_GSM_BASE,
SAP_GSM_DL,
SAP_GSM_MDL,
SAP_BSSGP_GMM,
SAP_BSSGP_LL,
SAP_BSSGP_NM,
SAP_BSSGP_PFM,
};
#endif

View File

@ -1,6 +0,0 @@
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_44_318.h \
gsm_12_21.h ipaccess.h
osmogsm_protodir = $(includedir)/osmocom/gsm/protocol

View File

@ -1246,6 +1246,80 @@ enum gsm48_bcap_rrq {
GSM48_BCAP_RRQ_DUAL_FR = 3,
};
/* GSM 04.08 Bearer Capability: Rate Adaption */
enum gsm48_bcap_ra {
GSM48_BCAP_RA_NONE = 0,
GSM48_BCAP_RA_V110_X30 = 1,
GSM48_BCAP_RA_X31 = 2,
GSM48_BCAP_RA_OTHER = 3,
};
/* GSM 04.08 Bearer Capability: Signalling access protocol */
enum gsm48_bcap_sig_access {
GSM48_BCAP_SA_I440_I450 = 1,
GSM48_BCAP_SA_X21 = 2,
GSM48_BCAP_SA_X28_DP_IN = 3,
GSM48_BCAP_SA_X28_DP_UN = 4,
GSM48_BCAP_SA_X28_NDP = 5,
GSM48_BCAP_SA_X32 = 6,
};
/* GSM 04.08 Bearer Capability: User Rate */
enum gsm48_bcap_user_rate {
GSM48_BCAP_UR_300 = 1,
GSM48_BCAP_UR_1200 = 2,
GSM48_BCAP_UR_2400 = 3,
GSM48_BCAP_UR_4800 = 4,
GSM48_BCAP_UR_9600 = 5,
GSM48_BCAP_UR_12000 = 6,
GSM48_BCAP_UR_1200_75 = 7,
};
/* GSM 04.08 Bearer Capability: Parity */
enum gsm48_bcap_parity {
GSM48_BCAP_PAR_ODD = 0,
GSM48_BCAP_PAR_EVEN = 2,
GSM48_BCAP_PAR_NONE = 3,
GSM48_BCAP_PAR_ZERO = 4,
GSM48_BCAP_PAR_ONE = 5,
};
/* GSM 04.08 Bearer Capability: Intermediate Rate */
enum gsm48_bcap_interm_rate {
GSM48_BCAP_IR_8k = 2,
GSM48_BCAP_IR_16k = 3,
};
/* GSM 04.08 Bearer Capability: Transparency */
enum gsm48_bcap_transp {
GSM48_BCAP_TR_TRANSP = 0,
GSM48_BCAP_TR_RLP = 1,
GSM48_BCAP_TR_TR_PREF = 2,
GSM48_BCAP_TR_RLP_PREF = 3,
};
/* GSM 04.08 Bearer Capability: Modem Type */
enum gsm48_bcap_modem_type {
GSM48_BCAP_MT_NONE = 0,
GSM48_BCAP_MT_V21 = 1,
GSM48_BCAP_MT_V22 = 2,
GSM48_BCAP_MT_V22bis = 3,
GSM48_BCAP_MT_V23 = 4,
GSM48_BCAP_MT_V26ter = 5,
GSM48_BCAP_MT_V32 = 6,
GSM48_BCAP_MT_UNDEF = 7,
GSM48_BCAP_MT_AUTO_1 = 8,
};
/* GSM 04.08 Bearer Capability: Speech Version Indication */
enum gsm48_bcap_speech_ver {
GSM48_BCAP_SV_FR = 0,
GSM48_BCAP_SV_HR = 1,
GSM48_BCAP_SV_EFR = 2,
GSM48_BCAP_SV_AMR_F = 4,
GSM48_BCAP_SV_AMR_H = 5,
};
#define GSM48_TMSI_LEN 5
#define GSM48_MID_TMSI_LEN (GSM48_TMSI_LEN + 2)
#define GSM48_MI_SIZE 32

View File

@ -338,10 +338,26 @@ enum rsl_cmod_spd {
#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
/* non-transparent data */
#define RSL_CMOD_CSD_NT_43k5 0x74
#define RSL_CMOD_CSD_NT_28k8 0x71
#define RSL_CMOD_CSD_NT_14k5 0x58
#define RSL_CMOD_CSD_NT_12k0 0x50
#define RSL_CMOD_CSD_NT_6k0 0x51
/* legacy #defines with wrong name */
#define RSL_CMOD_SP_NT_14k5 RSL_CMOD_CSD_NT_14k5
#define RSL_CMOD_SP_NT_12k0 RSL_CMOD_CSD_NT_12k0
#define RSL_CMOD_SP_NT_6k0 RSL_CMOD_CSD_NT_6k0
/* transparent data */
#define RSL_CMOD_CSD_T_32000 0x38
#define RSL_CMOD_CSD_T_29000 0x39
#define RSL_CMOD_CSD_T_14400 0x18
#define RSL_CMOD_CSD_T_9600 0x10
#define RSL_CMOD_CSD_T_4800 0x11
#define RSL_CMOD_CSD_T_2400 0x12
#define RSL_CMOD_CSD_T_1200 0x13
#define RSL_CMOD_CSD_T_600 0x14
#define RSL_CMOD_CSD_T_1200_75 0x15
/*! \brief RSL Channel Identification IE (Chapter 9.3.5) */
struct rsl_ie_chan_ident {
@ -556,6 +572,6 @@ enum rsl_mrpci_phase {
RSL_MRPCI_PHASE_2PLUS = 3,
};
/*! }@ */
/*! @} */
#endif /* PROTO_GSM_08_58_H */

View File

@ -743,6 +743,6 @@ enum ipac_bcch_info_type {
IPAC_BINF_CELL_ALLOC = (1 << 2),
};
/*! }@ */
/*! @} */
#endif /* PROTO_GSM_12_21_H */

View File

@ -5,6 +5,13 @@
/* Definitions according to 3GPP TS 44.318 6.8.0 Release 6 */
/* Table 11.1.1.2.1: Protocol Discriminator */
enum gan_pdisc {
GA_PDISC_RC = 0,
GA_PDISC_CSR = 1,
GA_PDISC_PSR = 2,
};
/* Table 11.1.1.4.1: Message types for URR */
enum gan_msg_type {
@ -51,6 +58,9 @@ enum gan_msg_type {
GA_MT_RC_KEEPALIVE = 0x74,
GA_MT_CSR_CM_ENQ = 0x75,
GA_MT_CSR_CM_CHANGE = 0x76,
GA_MT_PSR_GPRS_SUSPEND_REQ = 0x77,
GA_RC_SYNC_INFO = 0x78,
GA_CSR_UTRAN_CM_CHG = 0x79,
GA_MT_CSR_REQUEST = 0x80,
GA_MT_CSR_REQUEST_ACCEPT = 0x81,
@ -94,9 +104,9 @@ enum gan_iei {
GA_IE_TLLI = 34,
GA_IE_PFI = 35,
GA_IE_SUSP_CAUSE = 36,
GA_IE_TU3820_TIMER = 37,
GA_IE_TU3920_TIMER = 37,
GA_IE_REQD_QOS = 38,
GA_IE_P_DEACT_CAUSE = 39
GA_IE_P_DEACT_CAUSE = 39,
GA_IE_REQD_UL_RATE = 40,
GA_IE_RAC = 41,
GA_IE_AP_LOCATION = 42,
@ -134,7 +144,7 @@ enum gan_iei {
GA_IE_DEF_GANC_IP = 97,
GA_IE_DEF_GANC_FQDN = 98,
GA_IE_GPRS_IP_ADDR = 99,
GA_IE_GPRS_UDP_PORT = 100
GA_IE_GPRS_UDP_PORT = 100,
GA_IE_GANC_TCP_PORT = 103,
GA_IE_RTP_UDP_PORT = 104,
GA_IE_RTCP_UDP_PORT = 105,
@ -148,6 +158,43 @@ struct gan_rc_csr_hdr {
uint8_t pdisc:4,
skip_ind:4;
uint8_t msg_type;
uint8_t data[0];
} __attribute__((packed));
/* 11.2.14.1: GAN Control Channel Description IE */
struct gan_cch_desc_ie {
uint8_t spare:1,
ecmc:1,
nmo:2,
gprs:1,
dtm:1,
att:1,
mscr:1;
#if 0
uint8_t mscr:1,
att:1,
dtm:1,
gprs:1,
nmo:2,
ecmc:1,
spare:1;
#endif
uint8_t t3212;
uint8_t rac;
uint8_t sgsnr:1,
ecmp:1,
re:1,
pfcfm:1,
tgecs:2,
spare2:2;
#if 0
uint8_t spare2:2,
tgecs:2,
pfcfm:1,
re:1,
ecmp:1,
sgsnr:1;
#endif
uint8_t access_class[2];
} __attribute__((packed));
#endif /* PROTO_GSM_44_318_H */

View File

@ -50,6 +50,6 @@ void rsl_rll_push_l3(struct msgb *msg, uint8_t msg_type, uint8_t chan_nr,
struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
uint8_t link_id, int transparent);
/*! }@ */
/*! @} */
#endif /* _OSMOCORE_RSL_H */

View File

@ -20,6 +20,7 @@
TL16V 8 16 N * 8
TLV16 8 8 N * 16
TvLV 8 8/16 N * 8
vTvLV 8/16 8/16 N * 8
*/
@ -46,6 +47,36 @@ static inline uint16_t TVLV_GROSS_LEN(uint16_t len)
return TL16V_GROSS_LEN(len);
}
/*! \brief gross length of vTvL header (tag+len) */
static inline uint16_t VTVL_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
{
uint16_t ret = 2;
if (tag > TVLV_MAX_ONEBYTE)
ret++;
if (len > TVLV_MAX_ONEBYTE)
ret++;
return ret;
}
/*! \brief gross length of vTvLV (tag+len+val) */
static inline uint16_t VTVLV_GAN_GROSS_LEN(uint16_t tag, uint16_t len)
{
uint16_t ret;
if (len <= TVLV_MAX_ONEBYTE)
return TLV_GROSS_LEN(len);
else
return TL16V_GROSS_LEN(len);
if (tag > TVLV_MAX_ONEBYTE)
ret += 1;
return ret;
}
/* TLV generation */
/*! \brief put (append) a LV field */
@ -103,6 +134,42 @@ static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len,
return ret;
}
/*! \brief put (append) a variable-length tag or variable-length length * */
static inline uint8_t *vt_gan_put(uint8_t *buf, uint16_t tag)
{
if (tag > TVLV_MAX_ONEBYTE) {
/* two-byte TAG */
*buf++ = 0x80 | (tag >> 8);
*buf++ = (tag & 0xff);
} else
*buf++ = tag;
return buf;
}
/* \brief put (append) vTvL (GAN) field (tag + length)*/
static inline uint8_t *vtvl_gan_put(uint8_t *buf, uint16_t tag, uint16_t len)
{
uint8_t *ret;
ret = vt_gan_put(buf, tag);
return vt_gan_put(ret, len);
}
/* \brief put (append) vTvLV (GAN) field (tag + length + val) */
static inline uint8_t *vtvlv_gan_put(uint8_t *buf, uint16_t tag, uint16_t len,
const uint8_t *val)
{
uint8_t *ret;
ret = vtvl_gan_put(buf, tag, len );
memcpy(ret, val, len);
ret = buf + len;
return ret;
}
/*! \brief put (append) a TLV16 field to \ref msgb */
static inline uint8_t *msgb_tlv16_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint16_t *val)
{
@ -126,6 +193,14 @@ static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len
return tvlv_put(buf, tag, len, val);
}
/*! \brief put (append) a vTvLV field to \ref msgb */
static inline uint8_t *msgb_vtvlv_gan_put(struct msgb *msg, uint16_t tag,
uint16_t len, const uint8_t *val)
{
uint8_t *buf = msgb_put(msg, VTVLV_GAN_GROSS_LEN(tag, len));
return vtvlv_gan_put(buf, tag, len, val);
}
/*! \brief put (append) a L16TV field to \ref msgb */
static inline uint8_t *msgb_l16tv_put(struct msgb *msg, uint16_t len, uint8_t tag,
const uint8_t *val)
@ -264,6 +339,25 @@ static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t le
return buf;
}
/* \brief push (prepend) a vTvL header to a \ref msgb
*/
static inline uint8_t *msgb_vtvl_gan_push(struct msgb *msg, uint16_t tag,
uint16_t len)
{
uint8_t *buf = msgb_push(msg, VTVL_GAN_GROSS_LEN(tag, len));
vtvl_gan_put(buf, tag, len);
return buf;
}
static inline uint8_t *msgb_vtvlv_gan_push(struct msgb *msg, uint16_t tag,
uint16_t len, const uint8_t *val)
{
uint8_t *buf = msgb_push(msg, VTVLV_GAN_GROSS_LEN(tag, len));
vtvlv_gan_put(buf, tag, len, val);
return buf;
}
/* TLV parsing */
/*! \brief Entry in a TLV parser array */
@ -281,7 +375,8 @@ enum tlv_type {
TLV_TYPE_TLV, /*!< \brief tag-length-value */
TLV_TYPE_TL16V, /*!< \brief tag, 16 bit length, value */
TLV_TYPE_TvLV, /*!< \brief tag, variable length, value */
TLV_TYPE_SINGLE_TV /*!< \brief tag and value (both 4 bit) in 1 byte */
TLV_TYPE_SINGLE_TV, /*!< \brief tag and value (both 4 bit) in 1 byte */
TLV_TYPE_vTvLV_GAN, /*!< \brief variable-length tag, variable-length length */
};
/*! \brief Definition of a single IE (Information Element) */
@ -301,6 +396,7 @@ struct tlv_parsed {
};
extern struct tlv_definition tvlv_att_def;
extern struct tlv_definition vtvlv_gan_att_def;
int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
const struct tlv_definition *def,
@ -314,6 +410,6 @@ void tlv_def_patch(struct tlv_definition *dst, const struct tlv_definition *src)
#define TLVP_LEN(x, y) (x)->lv[y].len
#define TLVP_VAL(x, y) (x)->lv[y].val
/*! }@ */
/*! @} */
#endif /* _TLV_H */

View File

@ -1,4 +0,0 @@
osmovty_HEADERS = buffer.h command.h vector.h vty.h \
telnet_interface.h logging.h misc.h
osmovtydir = $(includedir)/osmocom/vty

View File

@ -26,7 +26,6 @@
#include <stdio.h>
#include <sys/types.h>
#include "vector.h"
#include "vty.h"
/*! \defgroup command VTY Command
* @{
@ -82,10 +81,14 @@ enum node_type {
L_E1INP_NODE, /*!< \brief E1 line in libosmo-abis. */
L_IPA_NODE, /*!< \brief IPA proxying commands in libosmo-abis. */
L_NS_NODE, /*!< \brief NS node in libosmo-gb. */
L_BSSGP_NODE, /*!< \brief BSSGP node in libosmo-gb. */
_LAST_OSMOVTY_NODE
};
#include "vty.h"
/*! \brief Node which has some commands and prompt string and
* configuration function pointer . */
struct cmd_node {
@ -366,5 +369,5 @@ void print_version(int print_copyright);
extern void *tall_vty_cmd_ctx;
/*! }@ */
/*! @} */
#endif /* _ZEBRA_COMMAND_H */

View File

@ -4,6 +4,11 @@
#include <osmocom/vty/vty.h>
#include <osmocom/core/rate_ctr.h>
#define VTY_DO_LOWER 1
char *vty_cmd_string_from_valstr(void *ctx, const struct value_string *vals,
const char *prefix, const char *sep,
const char *end, int do_lower);
void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
struct rate_ctr_group *ctrg);

View File

@ -51,6 +51,6 @@ int telnet_init_dynif(void *tall_ctx, void *priv, const char *ip, int port);
void telnet_exit(void);
/*! }@ */
/*! @} */
#endif /* TELNET_INTERFACE_H */

View File

@ -40,6 +40,13 @@ enum event {
#endif /* VTYSH */
};
enum vty_type {
VTY_TERM,
VTY_FILE,
VTY_SHELL,
VTY_SHELL_SERV
};
/*! Internal representation of a single VTY */
struct vty {
/*! \brief underlying file (if any) */
@ -52,7 +59,7 @@ struct vty {
int fd;
/*! \brief Is this vty connect to file or not */
enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type;
enum vty_type type;
/*! \brief Node status of this vty */
int node;
@ -134,7 +141,7 @@ struct vty {
/* Small macro to determine newline is newline only or linefeed needed. */
#define VTY_NEWLINE ((vty->type == VTY_TERM) ? "\r\n" : "\n")
static inline char *vty_newline(struct vty *vty)
static inline const char *vty_newline(struct vty *vty)
{
return VTY_NEWLINE;
}
@ -183,6 +190,6 @@ extern void *tall_vty_ctx;
extern struct cmd_element cfg_description_cmd;
extern struct cmd_element cfg_no_description_cmd;
/*! }@ */
/*! @} */
#endif

View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: Osmocom GPRS Gb Library
Description: Osmocom GPRS Gb Interface (NS/BSSGP) Library
Version: @VERSION@
Libs: -L${libdir} -losmogb -losmovty
Cflags: -I${includedir}/ -fno-strict-aliasing

View File

@ -1,11 +1,9 @@
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
LIBVERSION=4:0:0
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include
AM_CFLAGS = -fPIC -Wall
AM_CFLAGS = -Wall
lib_LTLIBRARIES = libosmocore.la
@ -17,6 +15,8 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c bits.c \
conv.c application.c rbtree.c \
crc8gen.c crc16gen.c crc32gen.c crc64gen.c
BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
if ENABLE_PLUGIN
libosmocore_la_SOURCES += plugin.c
libosmocore_la_LDFLAGS = -version-info $(LIBVERSION) $(LIBRARY_DL)
@ -39,5 +39,4 @@ libosmocore_la_SOURCES += serial.c
endif
crc%gen.c: crcXXgen.c.tpl
@echo " SED $< -> $@"
@sed -e's/XX/$*/g' $< > $@
$(AM_V_GEN)sed -e's/XX/$*/g' $< > $@

View File

@ -1,8 +1,6 @@
/*
* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by Nico Golde <nico@ngolde.de>
* (C) 2012 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@ -29,36 +27,64 @@
#include <stdio.h>
#include <stdlib.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/logging.h>
#include "config.h"
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
/*! \brief Generate and print a call back-trace
*
* This function will generate a function call back-trace of the
* current process and print it to stdout
*/
void osmo_generate_backtrace(void)
static void _osmo_backtrace(int use_printf, int subsys, int level)
{
int i, nptrs;
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, ARRAY_SIZE(buffer));
printf("backtrace() returned %d addresses\n", nptrs);
if (use_printf)
printf("backtrace() returned %d addresses\n", nptrs);
else
LOGP(subsys, level, "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]);
for (i = 1; i < nptrs; i++) {
if (use_printf)
printf("%s\n", strings[i]);
else
LOGP(subsys, level, "\t%s\n", strings[i]);
}
free(strings);
}
/*! \brief Generate and print a call back-trace
*
* This function will generate a function call back-trace of the
* current process and print it to stdout. */
void osmo_generate_backtrace(void)
{
_osmo_backtrace(1, 0, 0);
}
/*! \brief Generate and log a call back-trace
*
* This function will generate a function call back-trace of the
* current process and log it to the specified subsystem and
* level using the libosmocore logging subsystem */
void osmo_log_backtrace(int subsys, int level)
{
_osmo_backtrace(0, subsys, level);
}
#else
void osmo_generate_backtrace(void)
{
fprintf(stderr, "This platform has no backtrace function\n");
}
void osmo_log_backtrace(int subsys, int level)
{
LOGP(subsys, level, "This platform has no backtrace function\n");
}
#endif

View File

@ -185,4 +185,4 @@ void osmo_revbytebits_buf(uint8_t *buf, int len)
}
}
/*! }@ */
/*! @} */

View File

@ -261,4 +261,4 @@ int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n,
return -1;
}
/*! }@ */
/*! @} */

View File

@ -3,9 +3,9 @@
LIBVERSION=0:0:0
INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -fPIC -Wall
AM_CFLAGS = -Wall
lib_LTLIBRARIES = libosmocodec.la
libosmocodec_la_SOURCES = gsm610.c gsm620.c gsm660.c gsm690.c
libosmocodec_la_LDFALGS = -version-info $(LIBVERSION)
libosmocodec_la_LDFLAGS = -version-info $(LIBVERSION)

View File

@ -30,7 +30,7 @@
* It converts between serial parameter output by the encoder and the
* order needed before channel encoding.
*/
uint16_t gsm610_bitorder[260] = {
const uint16_t gsm610_bitorder[260] = {
0, /* LARc0:5 */
47, /* Xmaxc0:5 */
103, /* Xmaxc1:5 */

View File

@ -27,7 +27,7 @@
/* This array encode mapping between GSM 05.03 Table 3a (bits
* ordering before channel coding on TCH) and GSM 06.20 Table B.1
* (bit ordering on A-bis */
uint16_t gsm620_unvoiced_bitorder[112] = {
const uint16_t gsm620_unvoiced_bitorder[112] = {
3, /* R0:1 */
25, /* LPC 3:7 */
52, /* GSP 0-1:2 */
@ -146,7 +146,7 @@ uint16_t gsm620_unvoiced_bitorder[112] = {
/* This array encode mapping between GSM 05.03 Table 3b (bits
* ordering before channel coding on TCH) and GSM 06.20 Table B.2
* (bit ordering on A-bis */
uint16_t gsm620_voiced_bitorder[112] = {
const uint16_t gsm620_voiced_bitorder[112] = {
13, /* LPC 1:2 */
14, /* LPC 1:1 */
20, /* LPC 2:4 */

View File

@ -32,7 +32,7 @@
* applied prior to this table, as in GSM 05.03 3.1.1, to get 260
* bits from a 244 bits raw EFR frame.
*/
uint16_t gsm660_bitorder[260] = {
const uint16_t gsm660_bitorder[260] = {
38, 39, 40, 41, 42, 43, /* 0 -> LTP-LAG 1: b8..b3 */
145, 146, 147, 148, 149, 150, /* 6 -> LTP-LAG 3: b8..b3 */
93, 94, /* 12 -> LTP-LAG 2: b5..b4 */

View File

@ -33,7 +33,7 @@
/* This array encodes GSM 05.03 Table 7
* It's also TS 26.101 Table B.8
*/
uint16_t gsm690_12_2_bitorder[244] = {
const uint16_t gsm690_12_2_bitorder[244] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 23, 15, 16, 17, 18,
19, 20, 21, 22, 24, 25, 26, 27, 28, 38,
@ -65,7 +65,7 @@ uint16_t gsm690_12_2_bitorder[244] = {
/* This array encodes GSM 05.03 Table 8
* It's also TS 26.101 Table B.7
*/
uint16_t gsm690_10_2_bitorder[204] = {
const uint16_t gsm690_10_2_bitorder[204] = {
7, 6, 5, 4, 3, 2, 1, 0, 16, 15,
14, 13, 12, 11, 10, 9, 8, 26, 27, 28,
29, 30, 31, 115, 116, 117, 118, 119, 120, 72,
@ -93,7 +93,7 @@ uint16_t gsm690_10_2_bitorder[204] = {
/* This array encodes GSM 05.03 Table 9
* It's also TS 26.101 Table B.6
*/
uint16_t gsm690_7_95_bitorder[159] = {
const uint16_t gsm690_7_95_bitorder[159] = {
8, 7, 6, 5, 4, 3, 2, 14, 16, 9,
10, 12, 13, 15, 11, 17, 20, 22, 24, 23,
19, 18, 21, 56, 88, 122, 154, 57, 89, 123,
@ -116,7 +116,7 @@ uint16_t gsm690_7_95_bitorder[159] = {
/* This array encodes GSM 05.03 Table 10
* It's also TS 26.101 Table B.5
*/
uint16_t gsm690_7_4_bitorder[148] = {
const uint16_t gsm690_7_4_bitorder[148] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 26, 87, 27,
88, 28, 89, 29, 90, 30, 91, 51, 80, 112,
@ -138,7 +138,7 @@ uint16_t gsm690_7_4_bitorder[148] = {
/* This array encodes GSM 05.03 Table 11
* It's also TS 26.101 Table B.4
*/
uint16_t gsm690_6_7_bitorder[134] = {
const uint16_t gsm690_6_7_bitorder[134] = {
0, 1, 4, 3, 5, 6, 13, 7, 2, 8,
9, 11, 15, 12, 14, 10, 28, 82, 29, 83,
27, 81, 26, 80, 30, 84, 16, 55, 109, 56,
@ -159,7 +159,7 @@ uint16_t gsm690_6_7_bitorder[134] = {
/* This array encodes GSM 05.03 Table 12
* It's also TS 26.101 Table B.3
*/
uint16_t gsm690_5_9_bitorder[118] = {
const uint16_t gsm690_5_9_bitorder[118] = {
0, 1, 4, 5, 3, 6, 7, 2, 13, 15,
8, 9, 11, 12, 14, 10, 16, 28, 74, 29,
75, 27, 73, 26, 72, 30, 76, 51, 97, 50,
@ -178,7 +178,7 @@ uint16_t gsm690_5_9_bitorder[118] = {
/* This array encodes GSM 05.03 Table 13
* It's also TS 26.101 Table B.2
*/
uint16_t gsm690_5_15_bitorder[103] = {
const uint16_t gsm690_5_15_bitorder[103] = {
7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
13, 12, 11, 10, 9, 8, 23, 24, 25, 26,
27, 46, 65, 84, 45, 44, 43, 64, 63, 62,
@ -196,7 +196,7 @@ uint16_t gsm690_5_15_bitorder[103] = {
/* This array encodes GSM 05.03 Table 14
* It's also TS 26.101 Table B.1
*/
uint16_t gsm690_4_75_bitorder[95] = {
const uint16_t gsm690_4_75_bitorder[95] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 23, 24, 25, 26,
27, 28, 48, 49, 61, 62, 82, 83, 47, 46,

View File

@ -628,4 +628,4 @@ osmo_conv_decode(const struct osmo_conv_code *code,
return rv;
}
/*! }@ */
/*! @} */

View File

@ -115,6 +115,6 @@ osmo_crcXXgen_set_bits(const struct osmo_crcXXgen_code *code,
crc_bits[i] = ((crc >> (code->bits-i-1)) & 1);
}
/*! }@ */
/*! @} */
/* vim: set syntax=c: */

View File

@ -0,0 +1,24 @@
# 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=2:0:0
INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -Wall ${GCC_FVISIBILITY_HIDDEN} -fno-strict-aliasing
# FIXME: this should eventually go into a milenage/Makefile.am
noinst_HEADERS = common_vty.h
lib_LTLIBRARIES = libosmogb.la
libosmogb_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libosmogb.map -version-info $(LIBVERSION)
libosmogb_la_LIBADD = \
$(top_builddir)/src/libosmocore.la \
$(top_builddir)/src/vty/libosmovty.la \
$(top_builddir)/src/gsm/libosmogsm.la
libosmogb_la_SOURCES = gprs_ns.c gprs_ns_frgre.c gprs_ns_vty.c \
gprs_bssgp.c gprs_bssgp_util.c gprs_bssgp_vty.c \
gprs_bssgp_bss.c common_vty.c
EXTRA_DIST = libosmogb.map

View File

@ -0,0 +1,90 @@
/* OpenBSC VTY common helpers */
/* (C) 2009-2012 by Harald Welte <laforge@gnumonks.org>
* (C) 2009-2010 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 Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdlib.h>
#include <string.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/logging.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/buffer.h>
#include <osmocom/vty/vty.h>
#include <osmocom/gprs/gprs_msgb.h>
#include "common_vty.h"
/* Down vty node level. */
gDEFUN(libgb_exit,
libgb_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
{
switch (vty->node) {
case L_NS_NODE:
case L_BSSGP_NODE:
vty->node = CONFIG_NODE;
vty->index = NULL;
break;
default:
break;
}
return CMD_SUCCESS;
}
/* End of configuration. */
gDEFUN(libgb_end,
libgb_end_cmd, "end", "End current mode and change to enable mode.")
{
switch (vty->node) {
case L_NS_NODE:
case L_BSSGP_NODE:
vty_config_unlock(vty);
vty->node = ENABLE_NODE;
vty->index = NULL;
vty->index_sub = NULL;
break;
default:
break;
}
return CMD_SUCCESS;
}
int gprs_log_filter_fn(const struct log_context *ctx,
struct log_target *tar)
{
const struct gprs_nsvc *nsvc = ctx->ctx[GPRS_CTX_NSVC];
const struct gprs_bvc *bvc = ctx->ctx[GPRS_CTX_BVC];
/* Filter on the NS Virtual Connection */
if ((tar->filter_map & (1 << FLT_NSVC)) != 0
&& nsvc && (nsvc == tar->filter_data[FLT_NSVC]))
return 1;
/* Filter on the NS Virtual Connection */
if ((tar->filter_map & (1 << FLT_BVC)) != 0
&& bvc && (bvc == tar->filter_data[FLT_BVC]))
return 1;
return 0;
}
int DNS, DBSSGP;

View File

@ -0,0 +1,14 @@
#include <osmocom/vty/command.h>
#include <osmocom/core/logging.h>
extern int DNS, DBSSGP;
enum log_filter {
_FLT_ALL = LOG_FILTER_ALL, /* libosmocore */
FLT_NSVC = 1,
FLT_BVC = 2,
};
extern struct cmd_element libgb_exit_cmd;
extern struct cmd_element libgb_end_cmd;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,425 @@
/* GPRS BSSGP protocol implementation as per 3GPP TS 08.18 */
/* (C) 2009-2012 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <errno.h>
#include <stdint.h>
#include <netinet/in.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_ns.h>
#include "common_vty.h"
uint8_t *bssgp_msgb_tlli_put(struct msgb *msg, uint32_t tlli)
{
uint32_t _tlli = htonl(tlli);
return msgb_tvlv_put(msg, BSSGP_IE_TLLI, 4, (uint8_t *) &_tlli);
}
/*! \brief GMM-SUSPEND.req (Chapter 10.3.6) */
int bssgp_tx_suspend(uint16_t nsei, uint32_t tlli,
const struct gprs_ra_id *ra_id)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
uint8_t ra[6];
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP (BVCI=0) Tx SUSPEND (TLLI=0x%04x)\n",
tlli);
msgb_nsei(msg) = nsei;
msgb_bvci(msg) = 0; /* Signalling */
bgph->pdu_type = BSSGP_PDUT_SUSPEND;
bssgp_msgb_tlli_put(msg, tlli);
gsm48_construct_ra(ra, ra_id);
msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/*! \brief GMM-RESUME.req (Chapter 10.3.9) */
int bssgp_tx_resume(uint16_t nsei, uint32_t tlli,
const struct gprs_ra_id *ra_id, uint8_t suspend_ref)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
uint8_t ra[6];
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP (BVCI=0) Tx RESUME (TLLI=0x%04x)\n",
tlli);
msgb_nsei(msg) = nsei;
msgb_bvci(msg) = 0; /* Signalling */
bgph->pdu_type = BSSGP_PDUT_RESUME;
bssgp_msgb_tlli_put(msg, tlli);
gsm48_construct_ra(ra, ra_id);
msgb_tvlv_put(msg, BSSGP_IE_ROUTEING_AREA, 6, ra);
msgb_tvlv_put(msg, BSSGP_IE_SUSPEND_REF_NR, 1, &suspend_ref);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/*! \brief Transmit RA-CAPABILITY-UPDATE (10.3.3) */
int bssgp_tx_ra_capa_upd(struct bssgp_bvc_ctx *bctx, uint32_t tlli, uint8_t tag)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP (BVCI=%u) Tx RA-CAPA-UPD (TLLI=0x%04x)\n",
bctx->bvci, tlli);
/* set NSEI and BVCI in msgb cb */
msgb_nsei(msg) = bctx->nsei;
msgb_bvci(msg) = bctx->bvci;
bgph->pdu_type = BSSGP_PDUT_RA_CAPA_UDPATE;
bssgp_msgb_tlli_put(msg, tlli);
msgb_tvlv_put(msg, BSSGP_IE_TAG, 1, &tag);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/* first common part of RADIO-STATUS */
static struct msgb *common_tx_radio_status(struct bssgp_bvc_ctx *bctx)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP (BVCI=%u) Tx RADIO-STATUS ",
bctx->bvci);
/* set NSEI and BVCI in msgb cb */
msgb_nsei(msg) = bctx->nsei;
msgb_bvci(msg) = bctx->bvci;
bgph->pdu_type = BSSGP_PDUT_RADIO_STATUS;
return msg;
}
/* second common part of RADIO-STATUS */
static int common_tx_radio_status2(struct msgb *msg, uint8_t cause)
{
msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause);
LOGPC(DBSSGP, LOGL_NOTICE, "CAUSE=%u\n", cause);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/*! \brief Transmit RADIO-STATUS for TLLI (10.3.5) */
int bssgp_tx_radio_status_tlli(struct bssgp_bvc_ctx *bctx, uint8_t cause,
uint32_t tlli)
{
struct msgb *msg = common_tx_radio_status(bctx);
if (!msg)
return -ENOMEM;
bssgp_msgb_tlli_put(msg, tlli);
LOGPC(DBSSGP, LOGL_NOTICE, "TLLI=0x%08x ", tlli);
return common_tx_radio_status2(msg, cause);
}
/*! \brief Transmit RADIO-STATUS for TMSI (10.3.5) */
int bssgp_tx_radio_status_tmsi(struct bssgp_bvc_ctx *bctx, uint8_t cause,
uint32_t tmsi)
{
struct msgb *msg = common_tx_radio_status(bctx);
uint32_t _tmsi = htonl(tmsi);
if (!msg)
return -ENOMEM;
msgb_tvlv_put(msg, BSSGP_IE_TMSI, 4, (uint8_t *)&_tmsi);
LOGPC(DBSSGP, LOGL_NOTICE, "TMSI=0x%08x ", tmsi);
return common_tx_radio_status2(msg, cause);
}
/*! \brief Transmit RADIO-STATUS for IMSI (10.3.5) */
int bssgp_tx_radio_status_imsi(struct bssgp_bvc_ctx *bctx, uint8_t cause,
const char *imsi)
{
struct msgb *msg = common_tx_radio_status(bctx);
uint8_t mi[10];
int imsi_len = gsm48_generate_mid_from_imsi(mi, imsi);
if (!msg)
return -ENOMEM;
/* strip the MI type and length values (2 bytes) */
if (imsi_len > 2)
msgb_tvlv_put(msg, BSSGP_IE_IMSI, imsi_len-2, mi+2);
LOGPC(DBSSGP, LOGL_NOTICE, "IMSI=%s ", imsi);
return common_tx_radio_status2(msg, cause);
}
/*! \brief Transmit FLUSH-LL-ACK (Chapter 10.4.2) */
int bssgp_tx_flush_ll_ack(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
uint8_t action, uint16_t bvci_new,
uint32_t num_octets)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
uint16_t _bvci_new = htons(bvci_new);
uint32_t _oct_aff = htonl(num_octets & 0xFFFFFF);
msgb_nsei(msg) = bctx->nsei;
msgb_bvci(msg) = 0; /* Signalling */
bgph->pdu_type = BSSGP_PDUT_FLUSH_LL_ACK;
bssgp_msgb_tlli_put(msg, tlli);
msgb_tvlv_put(msg, BSSGP_IE_FLUSH_ACTION, 1, &action);
if (action == 1) /* transferred */
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci_new);
msgb_tvlv_put(msg, BSSGP_IE_NUM_OCT_AFF, 3, (uint8_t *) &_oct_aff);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/*! \brief Transmit LLC-DISCARDED (Chapter 10.4.3) */
int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
uint8_t num_frames, uint32_t num_octets)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
uint16_t _bvci = htons(bctx->bvci);
uint32_t _oct_aff = htonl(num_octets & 0xFFFFFF);
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP (BVCI=%u) Tx LLC-DISCARDED "
"TLLI=0x%04x, FRAMES=%u, OCTETS=%u\n", bctx->bvci, tlli,
num_frames, num_octets);
msgb_nsei(msg) = bctx->nsei;
msgb_bvci(msg) = 0; /* Signalling */
bgph->pdu_type = BSSGP_PDUT_LLC_DISCARD;
bssgp_msgb_tlli_put(msg, tlli);
msgb_tvlv_put(msg, BSSGP_IE_LLC_FRAMES_DISCARDED, 1, &num_frames);
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
msgb_tvlv_put(msg, BSSGP_IE_NUM_OCT_AFF, 3, ((uint8_t *) &_oct_aff) + 1);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/*! \brief Transmit a BVC-BLOCK message (Chapter 10.4.8) */
int bssgp_tx_bvc_block(struct bssgp_bvc_ctx *bctx, uint8_t cause)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
uint16_t _bvci = htons(bctx->bvci);
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP (BVCI=%u) Tx BVC-BLOCK "
"CAUSE=%u\n", bctx->bvci, cause);
msgb_nsei(msg) = bctx->nsei;
msgb_bvci(msg) = 0; /* Signalling */
bgph->pdu_type = BSSGP_PDUT_BVC_BLOCK;
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/*! \brief Transmit a BVC-UNBLOCK message (Chapter 10.4.10) */
int bssgp_tx_bvc_unblock(struct bssgp_bvc_ctx *bctx)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
uint16_t _bvci = htons(bctx->bvci);
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP (BVCI=%u) Tx BVC-BLOCK\n", bctx->bvci);
msgb_nsei(msg) = bctx->nsei;
msgb_bvci(msg) = 0; /* Signalling */
bgph->pdu_type = BSSGP_PDUT_BVC_UNBLOCK;
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/*! \brief Transmit a BVC-RESET message (Chapter 10.4.12) */
int bssgp_tx_bvc_reset(struct bssgp_bvc_ctx *bctx, uint16_t bvci, uint8_t cause)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
uint16_t _bvci = htons(bvci);
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP (BVCI=%u) Tx BVC-RESET "
"CAUSE=%u\n", bvci, cause);
msgb_nsei(msg) = bctx->nsei;
msgb_bvci(msg) = 0; /* Signalling */
bgph->pdu_type = BSSGP_PDUT_BVC_RESET;
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause);
if (bvci != BVCI_PTM) {
uint8_t bssgp_cid[8];
bssgp_create_cell_id(bssgp_cid, &bctx->ra_id, bctx->cell_id);
msgb_tvlv_put(msg, BSSGP_IE_CELL_ID, sizeof(bssgp_cid), bssgp_cid);
}
/* Optional: Feature Bitmap */
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/*! \brief RL-UL-UNITDATA.req (Chapter 10.2.2) */
int bssgp_tx_ul_ud(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
const uint8_t *qos_profile, struct msgb *llc_pdu)
{
struct msgb *msg = llc_pdu;
uint8_t bssgp_cid[8];
struct bssgp_ud_hdr *budh;
/* FIXME: First push alignment octets, if rqd */
/* FIXME: Optional LSA Identifier List, PFI */
/* Cell Identifier */
bssgp_create_cell_id(bssgp_cid, &bctx->ra_id, bctx->cell_id);
msgb_tvlv_push(msg, BSSGP_IE_CELL_ID, sizeof(bssgp_cid), bssgp_cid);
/* User Data Header */
budh = (struct bssgp_ud_hdr *) msgb_push(msg, sizeof(*budh));
budh->tlli = htonl(tlli);
memcpy(budh->qos_profile, qos_profile, 3);
budh->pdu_type = BSSGP_PDUT_UL_UNITDATA;
/* set NSEI and BVCI in msgb cb */
msgb_nsei(msg) = bctx->nsei;
msgb_bvci(msg) = bctx->bvci;
rate_ctr_inc(&bctx->ctrg->ctr[BSSGP_CTR_PKTS_OUT]);
rate_ctr_add(&bctx->ctrg->ctr[BSSGP_CTR_BYTES_OUT], msg->len);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/* Parse a single GMM-PAGING.req to a given NSEI/NS-BVCI */
int bssgp_rx_paging(struct bssgp_paging_info *pinfo,
struct msgb *msg)
{
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_bssgph(msg);
struct tlv_parsed tp;
uint8_t ra[6];
int rc, data_len;
memset(ra, 0, sizeof(ra));
data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
rc = bssgp_tlv_parse(&tp, bgph->data, data_len);
if (rc < 0)
goto err_mand_ie;
switch (bgph->pdu_type) {
case BSSGP_PDUT_PAGING_PS:
pinfo->mode = BSSGP_PAGING_PS;
break;
case BSSGP_PDUT_PAGING_CS:
pinfo->mode = BSSGP_PAGING_CS;
break;
default:
return -EINVAL;
}
/* IMSI */
if (!TLVP_PRESENT(&tp, BSSGP_IE_IMSI))
goto err_mand_ie;
if (!pinfo->imsi)
pinfo->imsi = talloc_zero_size(pinfo, 16);
gsm48_mi_to_string(pinfo->imsi, sizeof(pinfo->imsi),
TLVP_VAL(&tp, BSSGP_IE_IMSI),
TLVP_LEN(&tp, BSSGP_IE_IMSI));
/* DRX Parameters */
if (!TLVP_PRESENT(&tp, BSSGP_IE_DRX_PARAMS))
goto err_mand_ie;
pinfo->drx_params = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_DRX_PARAMS));
/* Scope */
if (TLVP_PRESENT(&tp, BSSGP_IE_BSS_AREA_ID)) {
pinfo->scope = BSSGP_PAGING_BSS_AREA;
} else if (TLVP_PRESENT(&tp, BSSGP_IE_LOCATION_AREA)) {
pinfo->scope = BSSGP_PAGING_LOCATION_AREA;
memcpy(ra, TLVP_VAL(&tp, BSSGP_IE_LOCATION_AREA),
TLVP_LEN(&tp, BSSGP_IE_LOCATION_AREA));
gsm48_parse_ra(&pinfo->raid, ra);
} else if (TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA)) {
pinfo->scope = BSSGP_PAGING_ROUTEING_AREA;
memcpy(ra, TLVP_VAL(&tp, BSSGP_IE_ROUTEING_AREA),
TLVP_LEN(&tp, BSSGP_IE_ROUTEING_AREA));
gsm48_parse_ra(&pinfo->raid, ra);
} else if (TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) {
pinfo->scope = BSSGP_PAGING_BVCI;
pinfo->bvci = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI));
} else
return -EINVAL;
/* QoS profile mandatory for PS */
if (pinfo->mode == BSSGP_PAGING_PS) {
if (!TLVP_PRESENT(&tp, BSSGP_IE_QOS_PROFILE))
goto err_cond_ie;
if (TLVP_LEN(&tp, BSSGP_IE_QOS_PROFILE) < 3)
goto err;
memcpy(&pinfo->qos, TLVP_VAL(&tp, BSSGP_IE_QOS_PROFILE),
3);
}
/* Optional (P-)TMSI */
if (TLVP_PRESENT(&tp, BSSGP_IE_TMSI) &&
TLVP_LEN(&tp, BSSGP_IE_TMSI) >= 4)
if (!pinfo->ptmsi)
pinfo->ptmsi = talloc_zero_size(pinfo, sizeof(uint32_t));
*(pinfo->ptmsi) = ntohl(*(uint32_t *)
TLVP_VAL(&tp, BSSGP_IE_TMSI));
return 0;
err_mand_ie:
err_cond_ie:
err:
/* FIXME */
return 0;
}

View File

@ -0,0 +1,117 @@
/* GPRS BSSGP protocol implementation as per 3GPP TS 08.18 */
/* (C) 2009-2012 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <errno.h>
#include <stdint.h>
#include <netinet/in.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_ns.h>
#include "common_vty.h"
struct gprs_ns_inst *bssgp_nsi;
/* BSSGP Protocol specific, not implementation specific */
/* FIXME: This needs to go into libosmocore after finished */
/* Chapter 11.3.9 / Table 11.10: Cause coding */
static const struct value_string bssgp_cause_strings[] = {
{ BSSGP_CAUSE_PROC_OVERLOAD, "Processor overload" },
{ BSSGP_CAUSE_EQUIP_FAIL, "Equipment Failure" },
{ BSSGP_CAUSE_TRASIT_NET_FAIL, "Transit netowkr service failure" },
{ BSSGP_CAUSE_CAPA_GREATER_0KPBS,"Transmission capacity modified" },
{ BSSGP_CAUSE_UNKNOWN_MS, "Unknown MS" },
{ BSSGP_CAUSE_UNKNOWN_BVCI, "Unknown BVCI" },
{ BSSGP_CAUSE_CELL_TRAF_CONG, "Cell traffic congestion" },
{ BSSGP_CAUSE_SGSN_CONG, "SGSN congestion" },
{ BSSGP_CAUSE_OML_INTERV, "O&M intervention" },
{ BSSGP_CAUSE_BVCI_BLOCKED, "BVCI blocked" },
{ BSSGP_CAUSE_PFC_CREATE_FAIL, "PFC create failure" },
{ BSSGP_CAUSE_SEM_INCORR_PDU, "Semantically incorrect PDU" },
{ BSSGP_CAUSE_INV_MAND_INF, "Invalid mandatory information" },
{ BSSGP_CAUSE_MISSING_MAND_IE, "Missing mandatory IE" },
{ BSSGP_CAUSE_MISSING_COND_IE, "Missing conditional IE" },
{ BSSGP_CAUSE_UNEXP_COND_IE, "Unexpected conditional IE" },
{ BSSGP_CAUSE_COND_IE_ERR, "Conditional IE error" },
{ BSSGP_CAUSE_PDU_INCOMP_STATE, "PDU incompatible with protocol state" },
{ BSSGP_CAUSE_PROTO_ERR_UNSPEC, "Protocol error - unspecified" },
{ BSSGP_CAUSE_PDU_INCOMP_FEAT, "PDU not compatible with feature set" },
{ 0, NULL },
};
const char *bssgp_cause_str(enum gprs_bssgp_cause cause)
{
return get_value_string(bssgp_cause_strings, cause);
}
struct msgb *bssgp_msgb_alloc(void)
{
return msgb_alloc_headroom(4096, 128, "BSSGP");
}
/* Transmit a simple response such as BLOCK/UNBLOCK/RESET ACK/NACK */
int bssgp_tx_simple_bvci(uint8_t pdu_type, uint16_t nsei,
uint16_t bvci, uint16_t ns_bvci)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
uint16_t _bvci;
msgb_nsei(msg) = nsei;
msgb_bvci(msg) = ns_bvci;
bgph->pdu_type = pdu_type;
_bvci = htons(bvci);
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
return gprs_ns_sendmsg(bssgp_nsi, msg);
}
/* Chapter 10.4.14: Status */
int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg)
{
struct msgb *msg = bssgp_msgb_alloc();
struct bssgp_normal_hdr *bgph =
(struct bssgp_normal_hdr *) msgb_put(msg, sizeof(*bgph));
LOGP(DBSSGP, LOGL_NOTICE, "BSSGP BVCI=%u Tx STATUS, cause=%s\n",
bvci ? *bvci : 0, bssgp_cause_str(cause));
msgb_nsei(msg) = msgb_nsei(orig_msg);
msgb_bvci(msg) = 0;
bgph->pdu_type = BSSGP_PDUT_STATUS;
msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause);
if (bvci) {
uint16_t _bvci = htons(*bvci);
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
}
msgb_tvlv_put(msg, BSSGP_IE_PDU_IN_ERROR,
msgb_bssgp_len(orig_msg), msgb_bssgph(orig_msg));
return gprs_ns_sendmsg(bssgp_nsi, msg);
}

View File

@ -0,0 +1,198 @@
/* VTY interface for our GPRS BSS Gateway Protocol (BSSGP) implementation */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/misc.h>
#include "common_vty.h"
/* FIXME: this should go to some common file as it is copied
* in vty_interface.c of the BSC */
static const struct value_string gprs_bssgp_timer_strs[] = {
{ 0, NULL }
};
static void log_set_bvc_filter(struct log_target *target,
struct bssgp_bvc_ctx *bctx)
{
if (bctx) {
target->filter_map |= (1 << FLT_BVC);
target->filter_data[FLT_BVC] = bctx;
} else if (target->filter_data[FLT_NSVC]) {
target->filter_map = ~(1 << FLT_BVC);
target->filter_data[FLT_BVC] = NULL;
}
}
static struct cmd_node bssgp_node = {
L_BSSGP_NODE,
"%s(bssgp)#",
1,
};
static int config_write_bssgp(struct vty *vty)
{
vty_out(vty, "bssgp%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN(cfg_bssgp, cfg_bssgp_cmd,
"bssgp",
"Configure the GPRS BSS Gateway Protocol")
{
vty->node = L_BSSGP_NODE;
return CMD_SUCCESS;
}
static void dump_bvc(struct vty *vty, struct bssgp_bvc_ctx *bvc, int stats)
{
vty_out(vty, "NSEI %5u, BVCI %5u, RA-ID: %u-%u-%u-%u, CID: %u, "
"STATE: %s%s", bvc->nsei, bvc->bvci, bvc->ra_id.mcc,
bvc->ra_id.mnc, bvc->ra_id.lac, bvc->ra_id.rac, bvc->cell_id,
bvc->state & BVC_S_BLOCKED ? "BLOCKED" : "UNBLOCKED",
VTY_NEWLINE);
if (stats) {
struct bssgp_flow_control *fc = bvc->fc;
vty_out_rate_ctr_group(vty, " ", bvc->ctrg);
if (fc)
vty_out(vty, "FC-BVC(bucket_max: %uoct, leak_rate: "
"%uoct/s, cur_tokens: %uoct, max_q_d: %u, "
"cur_q_d: %u)\n", fc->bucket_size_max,
fc->bucket_leak_rate, fc->bucket_counter,
fc->max_queue_depth, fc->queue_depth);
}
}
static void dump_bssgp(struct vty *vty, int stats)
{
struct bssgp_bvc_ctx *bvc;
llist_for_each_entry(bvc, &bssgp_bvc_ctxts, list) {
dump_bvc(vty, bvc, stats);
}
}
#define BSSGP_STR "Show information about the BSSGP protocol\n"
DEFUN(show_bssgp, show_bssgp_cmd, "show bssgp",
SHOW_STR BSSGP_STR)
{
dump_bssgp(vty, 0);
return CMD_SUCCESS;
}
DEFUN(show_bssgp_stats, show_bssgp_stats_cmd, "show bssgp stats",
SHOW_STR BSSGP_STR
"Include statistics\n")
{
dump_bssgp(vty, 1);
return CMD_SUCCESS;
}
DEFUN(show_bvc, show_bvc_cmd, "show bssgp nsei <0-65535> [stats]",
SHOW_STR BSSGP_STR
"Show all BVCs on one NSE\n"
"The NSEI\n" "Include Statistics\n")
{
struct bssgp_bvc_ctx *bvc;
uint16_t nsei = atoi(argv[1]);
int show_stats = 0;
if (argc >= 2)
show_stats = 1;
llist_for_each_entry(bvc, &bssgp_bvc_ctxts, list) {
if (bvc->nsei != nsei)
continue;
dump_bvc(vty, bvc, show_stats);
}
return CMD_SUCCESS;
}
DEFUN(logging_fltr_bvc,
logging_fltr_bvc_cmd,
"logging filter bvc nsei <0-65535> bvci <0-65535>",
LOGGING_STR FILTER_STR
"Filter based on BSSGP Virtual Connection\n"
"NSEI of the BVC to be filtered\n"
"Network Service Entity Identifier (NSEI)\n"
"BVCI of the BVC to be filtered\n"
"BSSGP Virtual Connection Identifier (BVCI)\n")
{
struct log_target *tgt = osmo_log_vty2tgt(vty);
struct bssgp_bvc_ctx *bvc;
uint16_t nsei = atoi(argv[0]);
uint16_t bvci = atoi(argv[1]);
if (!tgt)
return CMD_WARNING;
bvc = btsctx_by_bvci_nsei(bvci, nsei);
if (!bvc) {
vty_out(vty, "No BVC by that identifier%s", VTY_NEWLINE);
return CMD_WARNING;
}
log_set_bvc_filter(tgt, bvc);
return CMD_SUCCESS;
}
int bssgp_vty_init(void)
{
install_element_ve(&show_bssgp_cmd);
install_element_ve(&show_bssgp_stats_cmd);
install_element_ve(&show_bvc_cmd);
install_element_ve(&logging_fltr_bvc_cmd);
install_element(CFG_LOG_NODE, &logging_fltr_bvc_cmd);
install_element(CONFIG_NODE, &cfg_bssgp_cmd);
install_node(&bssgp_node, config_write_bssgp);
install_default(L_BSSGP_NODE);
install_element(L_BSSGP_NODE, &libgb_exit_cmd);
install_element(L_BSSGP_NODE, &libgb_end_cmd);
//install_element(L_BSSGP_NODE, &cfg_bssgp_timer_cmd);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,346 @@
/* GPRS Networks Service (NS) messages on the Gb interface
* 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05) */
/* NS-over-FR-over-GRE implementation */
/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <osmocom/core/select.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/socket.h>
#include <osmocom/gprs/gprs_ns.h>
#include "common_vty.h"
#define GRE_PTYPE_FR 0x6559
#define GRE_PTYPE_IPv4 0x0800
#define GRE_PTYPE_KAR 0x0000 /* keepalive response */
struct gre_hdr {
uint16_t flags;
uint16_t ptype;
} __attribute__ ((packed));
#if defined(__FreeBSD__)
/**
* On BSD the IPv4 struct is called struct ip and instead of iXX
* the members are called ip_XX. One could change this code to use
* struct ip but that would require to define _BSD_SOURCE and that
* might have other complications. Instead make sure struct iphdr
* is present on FreeBSD. The below is taken from GLIBC.
*
* The GNU C 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 2.1 of the License, or (at your option) any later version.
*/
struct iphdr
{
#if BYTE_ORDER == LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
#elif BYTE_ORDER == BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
/*The options start here. */
};
#endif
/* IPv4 messages inside the GRE tunnel might be GRE keepalives */
static int handle_rx_gre_ipv4(struct osmo_fd *bfd, struct msgb *msg,
struct iphdr *iph, struct gre_hdr *greh)
{
struct gprs_ns_inst *nsi = bfd->data;
int gre_payload_len;
struct iphdr *inner_iph;
struct gre_hdr *inner_greh;
struct sockaddr_in daddr;
struct in_addr ia;
gre_payload_len = msg->len - (iph->ihl*4 + sizeof(*greh));
inner_iph = (struct iphdr *) ((uint8_t *)greh + sizeof(*greh));
if (gre_payload_len < inner_iph->ihl*4 + sizeof(*inner_greh)) {
LOGP(DNS, LOGL_ERROR, "GRE keepalive too short\n");
return -EIO;
}
if (inner_iph->saddr != iph->daddr ||
inner_iph->daddr != iph->saddr) {
LOGP(DNS, LOGL_ERROR,
"GRE keepalive with wrong tunnel addresses\n");
return -EIO;
}
if (inner_iph->protocol != IPPROTO_GRE) {
LOGP(DNS, LOGL_ERROR, "GRE keepalive with wrong protocol\n");
return -EIO;
}
inner_greh = (struct gre_hdr *) ((uint8_t *)inner_iph + iph->ihl*4);
if (inner_greh->ptype != htons(GRE_PTYPE_KAR)) {
LOGP(DNS, LOGL_ERROR, "GRE keepalive inner GRE type != 0\n");
return -EIO;
}
/* Actually send the response back */
daddr.sin_family = AF_INET;
daddr.sin_addr.s_addr = inner_iph->daddr;
daddr.sin_port = IPPROTO_GRE;
ia.s_addr = iph->saddr;
LOGP(DNS, LOGL_DEBUG, "GRE keepalive from %s, responding\n",
inet_ntoa(ia));
return sendto(nsi->frgre.fd.fd, inner_greh,
gre_payload_len - inner_iph->ihl*4, 0,
(struct sockaddr *)&daddr, sizeof(daddr));
}
static struct msgb *read_nsfrgre_msg(struct osmo_fd *bfd, int *error,
struct sockaddr_in *saddr)
{
struct msgb *msg = msgb_alloc(NS_ALLOC_SIZE, "Gb/NS/FR/GRE Rx");
int ret = 0;
socklen_t saddr_len = sizeof(*saddr);
struct iphdr *iph;
struct gre_hdr *greh;
uint8_t *frh;
uint16_t dlci;
if (!msg) {
*error = -ENOMEM;
return NULL;
}
ret = recvfrom(bfd->fd, msg->data, NS_ALLOC_SIZE, 0,
(struct sockaddr *)saddr, &saddr_len);
if (ret < 0) {
LOGP(DNS, LOGL_ERROR, "recv error %s during NS-FR-GRE recv\n",
strerror(errno));
*error = ret;
goto out_err;
} else if (ret == 0) {
*error = ret;
goto out_err;
}
msgb_put(msg, ret);
if (msg->len < sizeof(*iph) + sizeof(*greh) + 2) {
LOGP(DNS, LOGL_ERROR, "Short IP packet: %u bytes\n", msg->len);
*error = -EIO;
goto out_err;
}
iph = (struct iphdr *) msg->data;
if (msg->len < (iph->ihl*4 + sizeof(*greh) + 2)) {
LOGP(DNS, LOGL_ERROR, "Short IP packet: %u bytes\n", msg->len);
*error = -EIO;
goto out_err;
}
greh = (struct gre_hdr *) (msg->data + iph->ihl*4);
if (greh->flags) {
LOGP(DNS, LOGL_NOTICE, "Unknown GRE flags 0x%04x\n",
ntohs(greh->flags));
}
switch (ntohs(greh->ptype)) {
case GRE_PTYPE_IPv4:
/* IPv4 messages might be GRE keepalives */
*error = handle_rx_gre_ipv4(bfd, msg, iph, greh);
goto out_err;
break;
case GRE_PTYPE_FR:
/* continue as usual */
break;
default:
LOGP(DNS, LOGL_NOTICE, "Unknown GRE protocol 0x%04x != FR\n",
ntohs(greh->ptype));
*error = -EIO;
goto out_err;
break;
}
if (msg->len < sizeof(*greh) + 2) {
LOGP(DNS, LOGL_ERROR, "Short FR header: %u bytes\n", msg->len);
*error = -EIO;
goto out_err;
}
frh = (uint8_t *)greh + sizeof(*greh);
if (frh[0] & 0x01) {
LOGP(DNS, LOGL_NOTICE, "Unsupported single-byte FR address\n");
*error = -EIO;
goto out_err;
}
dlci = ((frh[0] & 0xfc) << 2);
if ((frh[1] & 0x0f) != 0x01) {
LOGP(DNS, LOGL_NOTICE, "Unknown second FR octet 0x%02x\n",
frh[1]);
*error = -EIO;
goto out_err;
}
dlci |= (frh[1] >> 4);
msg->l2h = frh+2;
/* Store DLCI in NETWORK BYTEORDER in sockaddr port member */
saddr->sin_port = htons(dlci);
return msg;
out_err:
msgb_free(msg);
return NULL;
}
int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
struct sockaddr_in *saddr, enum gprs_ns_ll ll);
static int handle_nsfrgre_read(struct osmo_fd *bfd)
{
int rc;
struct sockaddr_in saddr;
struct gprs_ns_inst *nsi = bfd->data;
struct msgb *msg;
uint16_t dlci;
msg = read_nsfrgre_msg(bfd, &rc, &saddr);
if (!msg)
return rc;
dlci = ntohs(saddr.sin_port);
if (dlci == 0 || dlci == 1023) {
LOGP(DNS, LOGL_INFO, "Received FR on LMI DLCI %u - ignoring\n",
dlci);
rc = 0;
goto out;
}
rc = gprs_ns_rcvmsg(nsi, msg, &saddr, GPRS_NS_LL_FR_GRE);
out:
msgb_free(msg);
return rc;
}
static int handle_nsfrgre_write(struct osmo_fd *bfd)
{
/* FIXME: actually send the data here instead of nsip_sendmsg() */
return -EIO;
}
int gprs_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg)
{
int rc;
struct gprs_ns_inst *nsi = nsvc->nsi;
struct sockaddr_in daddr;
uint16_t dlci = ntohs(nsvc->frgre.bts_addr.sin_port);
uint8_t *frh;
struct gre_hdr *greh;
/* Build socket address for the packet destionation */
daddr.sin_family = AF_INET;
daddr.sin_addr = nsvc->frgre.bts_addr.sin_addr;
daddr.sin_port = IPPROTO_GRE;
/* Prepend the FR header */
frh = msgb_push(msg, 2);
frh[0] = (dlci >> 2) & 0xfc;
frh[1] = ((dlci & 0xf)<<4) | 0x01;
/* Prepend the GRE header */
greh = (struct gre_hdr *) msgb_push(msg, sizeof(*greh));
greh->flags = 0;
greh->ptype = htons(GRE_PTYPE_FR);
rc = sendto(nsi->frgre.fd.fd, msg->data, msg->len, 0,
(struct sockaddr *)&daddr, sizeof(daddr));
msgb_free(msg);
return rc;
}
static int nsfrgre_fd_cb(struct osmo_fd *bfd, unsigned int what)
{
int rc = 0;
if (what & BSC_FD_READ)
rc = handle_nsfrgre_read(bfd);
if (what & BSC_FD_WRITE)
rc = handle_nsfrgre_write(bfd);
return rc;
}
int gprs_ns_frgre_listen(struct gprs_ns_inst *nsi)
{
struct in_addr in;
int rc;
in.s_addr = htonl(nsi->frgre.local_ip);
/* Make sure we close any existing socket before changing it */
if (nsi->frgre.fd.fd)
close(nsi->frgre.fd.fd);
if (!nsi->frgre.enabled)
return 0;
nsi->frgre.fd.cb = nsfrgre_fd_cb;
nsi->frgre.fd.data = nsi;
rc = osmo_sock_init_ofd(&nsi->frgre.fd, AF_INET, SOCK_RAW,
IPPROTO_GRE, inet_ntoa(in), 0,
OSMO_SOCK_F_BIND);
if (rc < 0) {
LOGP(DNS, LOGL_ERROR, "Error creating GRE socket (%s)\n",
strerror(errno));
return rc;
}
nsi->frgre.fd.data = nsi;
return rc;
}

View File

@ -0,0 +1,581 @@
/* VTY interface for our GPRS Networks Service (NS) implementation */
/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/misc.h>
#include "common_vty.h"
static struct gprs_ns_inst *vty_nsi = NULL;
/* FIXME: this should go to some common file as it is copied
* in vty_interface.c of the BSC */
static const struct value_string gprs_ns_timer_strs[] = {
{ 0, "tns-block" },
{ 1, "tns-block-retries" },
{ 2, "tns-reset" },
{ 3, "tns-reset-retries" },
{ 4, "tns-test" },
{ 5, "tns-alive" },
{ 6, "tns-alive-retries" },
{ 0, NULL }
};
static void log_set_nsvc_filter(struct log_target *target,
struct gprs_nsvc *nsvc)
{
if (nsvc) {
target->filter_map |= (1 << FLT_NSVC);
target->filter_data[FLT_NSVC] = nsvc;
} else if (target->filter_data[FLT_NSVC]) {
target->filter_map = ~(1 << FLT_NSVC);
target->filter_data[FLT_NSVC] = NULL;
}
}
static struct cmd_node ns_node = {
L_NS_NODE,
"%s(ns)#",
1,
};
static int config_write_ns(struct vty *vty)
{
struct gprs_nsvc *nsvc;
unsigned int i;
struct in_addr ia;
vty_out(vty, "ns%s", VTY_NEWLINE);
llist_for_each_entry(nsvc, &vty_nsi->gprs_nsvcs, list) {
if (!nsvc->persistent)
continue;
vty_out(vty, " nse %u nsvci %u%s",
nsvc->nsei, nsvc->nsvci, VTY_NEWLINE);
vty_out(vty, " nse %u remote-role %s%s",
nsvc->nsei, nsvc->remote_end_is_sgsn ? "sgsn" : "bss",
VTY_NEWLINE);
switch (nsvc->ll) {
case GPRS_NS_LL_UDP:
vty_out(vty, " nse %u encapsulation udp%s", nsvc->nsei,
VTY_NEWLINE);
vty_out(vty, " nse %u remote-ip %s%s",
nsvc->nsei,
inet_ntoa(nsvc->ip.bts_addr.sin_addr),
VTY_NEWLINE);
vty_out(vty, " nse %u remote-port %u%s",
nsvc->nsei, ntohs(nsvc->ip.bts_addr.sin_port),
VTY_NEWLINE);
break;
case GPRS_NS_LL_FR_GRE:
vty_out(vty, " nse %u encapsulation framerelay-gre%s",
nsvc->nsei, VTY_NEWLINE);
vty_out(vty, " nse %u remote-ip %s%s",
nsvc->nsei,
inet_ntoa(nsvc->frgre.bts_addr.sin_addr),
VTY_NEWLINE);
vty_out(vty, " nse %u fr-dlci %u%s",
nsvc->nsei, ntohs(nsvc->frgre.bts_addr.sin_port),
VTY_NEWLINE);
default:
break;
}
}
for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
vty_out(vty, " timer %s %u%s",
get_value_string(gprs_ns_timer_strs, i),
vty_nsi->timeout[i], VTY_NEWLINE);
if (vty_nsi->nsip.local_ip) {
ia.s_addr = htonl(vty_nsi->nsip.local_ip);
vty_out(vty, " encapsulation udp local-ip %s%s",
inet_ntoa(ia), VTY_NEWLINE);
}
if (vty_nsi->nsip.local_port)
vty_out(vty, " encapsulation udp local-port %u%s",
vty_nsi->nsip.local_port, VTY_NEWLINE);
vty_out(vty, " encapsulation framerelay-gre enabled %u%s",
vty_nsi->frgre.enabled ? 1 : 0, VTY_NEWLINE);
if (vty_nsi->frgre.local_ip) {
ia.s_addr = htonl(vty_nsi->frgre.local_ip);
vty_out(vty, " encapsulation framerelay-gre local-ip %s%s",
inet_ntoa(ia), VTY_NEWLINE);
}
return CMD_SUCCESS;
}
DEFUN(cfg_ns, cfg_ns_cmd,
"ns",
"Configure the GPRS Network Service")
{
vty->node = L_NS_NODE;
return CMD_SUCCESS;
}
static void dump_nse(struct vty *vty, struct gprs_nsvc *nsvc, int stats)
{
vty_out(vty, "NSEI %5u, NS-VC %5u, Remote: %-4s, %5s %9s",
nsvc->nsei, nsvc->nsvci,
nsvc->remote_end_is_sgsn ? "SGSN" : "BSS",
nsvc->state & NSE_S_ALIVE ? "ALIVE" : "DEAD",
nsvc->state & NSE_S_BLOCKED ? "BLOCKED" : "UNBLOCKED");
if (nsvc->ll == GPRS_NS_LL_UDP || nsvc->ll == GPRS_NS_LL_FR_GRE)
vty_out(vty, ", %s %15s:%u",
nsvc->ll == GPRS_NS_LL_UDP ? "UDP " : "FR-GRE",
inet_ntoa(nsvc->ip.bts_addr.sin_addr),
ntohs(nsvc->ip.bts_addr.sin_port));
vty_out(vty, "%s", VTY_NEWLINE);
if (stats)
vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
}
static void dump_ns(struct vty *vty, struct gprs_ns_inst *nsi, int stats)
{
struct gprs_nsvc *nsvc;
struct in_addr ia;
ia.s_addr = htonl(vty_nsi->nsip.local_ip);
vty_out(vty, "Encapsulation NS-UDP-IP Local IP: %s, UDP Port: %u%s",
inet_ntoa(ia), vty_nsi->nsip.local_port, VTY_NEWLINE);
ia.s_addr = htonl(vty_nsi->frgre.local_ip);
vty_out(vty, "Encapsulation NS-FR-GRE-IP Local IP: %s%s",
inet_ntoa(ia), VTY_NEWLINE);
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
if (nsvc == nsi->unknown_nsvc)
continue;
dump_nse(vty, nsvc, stats);
}
}
DEFUN(show_ns, show_ns_cmd, "show ns",
SHOW_STR "Display information about the NS protocol")
{
struct gprs_ns_inst *nsi = vty_nsi;
dump_ns(vty, nsi, 0);
return CMD_SUCCESS;
}
DEFUN(show_ns_stats, show_ns_stats_cmd, "show ns stats",
SHOW_STR
"Display information about the NS protocol\n"
"Include statistics\n")
{
struct gprs_ns_inst *nsi = vty_nsi;
dump_ns(vty, nsi, 1);
return CMD_SUCCESS;
}
DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
SHOW_STR "Display information about the NS protocol\n"
"Select one NSE by its NSE Identifier\n"
"Select one NSE by its NS-VC Identifier\n"
"The Identifier of selected type\n"
"Include Statistics\n")
{
struct gprs_ns_inst *nsi = vty_nsi;
struct gprs_nsvc *nsvc;
uint16_t id = atoi(argv[1]);
int show_stats = 0;
if (!strcmp(argv[0], "nsei"))
nsvc = gprs_nsvc_by_nsei(nsi, id);
else
nsvc = gprs_nsvc_by_nsvci(nsi, id);
if (!nsvc) {
vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (argc >= 3)
show_stats = 1;
dump_nse(vty, nsvc, show_stats);
return CMD_SUCCESS;
}
#define NSE_CMD_STR "Persistent NS Entity\n" "NS Entity ID (NSEI)\n"
DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
"nse <0-65535> nsvci <0-65534>",
NSE_CMD_STR
"NS Virtual Connection\n"
"NS Virtual Connection ID (NSVCI)\n"
)
{
uint16_t nsei = atoi(argv[0]);
uint16_t nsvci = atoi(argv[1]);
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsei);
if (!nsvc) {
nsvc = gprs_nsvc_create(vty_nsi, nsvci);
nsvc->nsei = nsei;
}
nsvc->nsvci = nsvci;
/* All NSVCs that are explicitly configured by VTY are
* marked as persistent so we can write them to the config
* file at some later point */
nsvc->persistent = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
"nse <0-65535> remote-ip A.B.C.D",
NSE_CMD_STR
"Remote IP Address\n"
"Remote IP Address\n")
{
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsei);
if (!nsvc) {
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
return CMD_WARNING;
}
inet_aton(argv[1], &nsvc->ip.bts_addr.sin_addr);
return CMD_SUCCESS;
}
DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
"nse <0-65535> remote-port <0-65535>",
NSE_CMD_STR
"Remote UDP Port\n"
"Remote UDP Port Number\n")
{
uint16_t nsei = atoi(argv[0]);
uint16_t port = atoi(argv[1]);
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsei);
if (!nsvc) {
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
return CMD_WARNING;
}
if (nsvc->ll != GPRS_NS_LL_UDP) {
vty_out(vty, "Cannot set UDP Port on non-UDP NSE%s",
VTY_NEWLINE);
return CMD_WARNING;
}
nsvc->ip.bts_addr.sin_port = htons(port);
return CMD_SUCCESS;
}
DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
"nse <0-65535> fr-dlci <16-1007>",
NSE_CMD_STR
"Frame Relay DLCI\n"
"Frame Relay DLCI Number\n")
{
uint16_t nsei = atoi(argv[0]);
uint16_t dlci = atoi(argv[1]);
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsei);
if (!nsvc) {
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
return CMD_WARNING;
}
if (nsvc->ll != GPRS_NS_LL_FR_GRE) {
vty_out(vty, "Cannot set FR DLCI on non-FR NSE%s",
VTY_NEWLINE);
return CMD_WARNING;
}
nsvc->frgre.bts_addr.sin_port = htons(dlci);
return CMD_SUCCESS;
}
DEFUN(cfg_nse_encaps, cfg_nse_encaps_cmd,
"nse <0-65535> encapsulation (udp|framerelay-gre)",
NSE_CMD_STR
"Encapsulation for NS\n"
"UDP/IP Encapsulation\n" "Frame-Relay/GRE/IP Encapsulation\n")
{
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsei);
if (!nsvc) {
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
return CMD_WARNING;
}
if (!strcmp(argv[1], "udp"))
nsvc->ll = GPRS_NS_LL_UDP;
else
nsvc->ll = GPRS_NS_LL_FR_GRE;
return CMD_SUCCESS;
}
DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
"nse <0-65535> remote-role (sgsn|bss)",
NSE_CMD_STR
"Remote NSE Role\n"
"Remote Peer is SGSN\n"
"Remote Peer is BSS\n")
{
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsei);
if (!nsvc) {
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
return CMD_WARNING;
}
if (!strcmp(argv[1], "sgsn"))
nsvc->remote_end_is_sgsn = 1;
else
nsvc->remote_end_is_sgsn = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_no_nse, cfg_no_nse_cmd,
"no nse <0-65535>",
"Delete Persistent NS Entity\n"
"Delete " NSE_CMD_STR)
{
uint16_t nsei = atoi(argv[0]);
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsei);
if (!nsvc) {
vty_out(vty, "No such NSE (%u)%s", nsei, VTY_NEWLINE);
return CMD_WARNING;
}
if (!nsvc->persistent) {
vty_out(vty, "NSEI %u is not a persistent NSE%s",
nsei, VTY_NEWLINE);
return CMD_WARNING;
}
nsvc->persistent = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
"timer " NS_TIMERS " <0-65535>",
"Network Service Timer\n"
NS_TIMERS_HELP "Timer Value\n")
{
int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
int val = atoi(argv[1]);
if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
return CMD_WARNING;
vty_nsi->timeout[idx] = val;
return CMD_SUCCESS;
}
#define ENCAPS_STR "NS encapsulation options\n"
DEFUN(cfg_nsip_local_ip, cfg_nsip_local_ip_cmd,
"encapsulation udp local-ip A.B.C.D",
ENCAPS_STR "NS over UDP Encapsulation\n"
"Set the IP address on which we listen for NS/UDP\n"
"IP Address\n")
{
struct in_addr ia;
inet_aton(argv[0], &ia);
vty_nsi->nsip.local_ip = ntohl(ia.s_addr);
return CMD_SUCCESS;
}
DEFUN(cfg_nsip_local_port, cfg_nsip_local_port_cmd,
"encapsulation udp local-port <0-65535>",
ENCAPS_STR "NS over UDP Encapsulation\n"
"Set the UDP port on which we listen for NS/UDP\n"
"UDP port number\n")
{
unsigned int port = atoi(argv[0]);
vty_nsi->nsip.local_port = port;
return CMD_SUCCESS;
}
DEFUN(cfg_frgre_local_ip, cfg_frgre_local_ip_cmd,
"encapsulation framerelay-gre local-ip A.B.C.D",
ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
"Set the IP address on which we listen for NS/FR/GRE\n"
"IP Address\n")
{
struct in_addr ia;
if (!vty_nsi->frgre.enabled) {
vty_out(vty, "FR/GRE is not enabled%s", VTY_NEWLINE);
return CMD_WARNING;
}
inet_aton(argv[0], &ia);
vty_nsi->frgre.local_ip = ntohl(ia.s_addr);
return CMD_SUCCESS;
}
DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd,
"encapsulation framerelay-gre enabled (1|0)",
ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
"Enable or disable Frame Relay over GRE\n"
"Enable\n" "Disable\n")
{
int enabled = atoi(argv[0]);
vty_nsi->frgre.enabled = enabled;
return CMD_SUCCESS;
}
DEFUN(nsvc_nsei, nsvc_nsei_cmd,
"nsvc nsei <0-65535> (block|unblock|reset)",
"Perform an operation on a NSVC\n"
"NSEI to identify NS-VC Identifier (NS-VCI)\n"
"The NSEI\n"
"Initiate BLOCK procedure\n"
"Initiate UNBLOCK procedure\n"
"Initiate RESET procedure\n")
{
uint16_t nsvci = atoi(argv[0]);
const char *operation = argv[1];
struct gprs_nsvc *nsvc;
nsvc = gprs_nsvc_by_nsei(vty_nsi, nsvci);
if (!nsvc) {
vty_out(vty, "No such NSVCI (%u)%s", nsvci, VTY_NEWLINE);
return CMD_WARNING;
}
if (!strcmp(operation, "block"))
gprs_ns_tx_block(nsvc, NS_CAUSE_OM_INTERVENTION);
else if (!strcmp(operation, "unblock"))
gprs_ns_tx_unblock(nsvc);
else if (!strcmp(operation, "reset"))
gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
else
return CMD_WARNING;
return CMD_SUCCESS;
}
DEFUN(logging_fltr_nsvc,
logging_fltr_nsvc_cmd,
"logging filter nsvc (nsei|nsvci) <0-65535>",
LOGGING_STR FILTER_STR
"Filter based on NS Virtual Connection\n"
"Identify NS-VC by NSEI\n"
"Identify NS-VC by NSVCI\n"
"Numeric identifier\n")
{
struct log_target *tgt = osmo_log_vty2tgt(vty);
struct gprs_nsvc *nsvc;
uint16_t id = atoi(argv[1]);
if (!tgt)
return CMD_WARNING;
if (!strcmp(argv[0], "nsei"))
nsvc = gprs_nsvc_by_nsei(vty_nsi, id);
else
nsvc = gprs_nsvc_by_nsvci(vty_nsi, id);
if (!nsvc) {
vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
return CMD_WARNING;
}
log_set_nsvc_filter(tgt, nsvc);
return CMD_SUCCESS;
}
int gprs_ns_vty_init(struct gprs_ns_inst *nsi)
{
vty_nsi = nsi;
install_element_ve(&show_ns_cmd);
install_element_ve(&show_ns_stats_cmd);
install_element_ve(&show_nse_cmd);
install_element_ve(&logging_fltr_nsvc_cmd);
install_element(CFG_LOG_NODE, &logging_fltr_nsvc_cmd);
install_element(CONFIG_NODE, &cfg_ns_cmd);
install_node(&ns_node, config_write_ns);
install_default(L_NS_NODE);
install_element(L_NS_NODE, &libgb_exit_cmd);
install_element(L_NS_NODE, &libgb_end_cmd);
install_element(L_NS_NODE, &cfg_nse_nsvci_cmd);
install_element(L_NS_NODE, &cfg_nse_remoteip_cmd);
install_element(L_NS_NODE, &cfg_nse_remoteport_cmd);
install_element(L_NS_NODE, &cfg_nse_fr_dlci_cmd);
install_element(L_NS_NODE, &cfg_nse_encaps_cmd);
install_element(L_NS_NODE, &cfg_nse_remoterole_cmd);
install_element(L_NS_NODE, &cfg_no_nse_cmd);
install_element(L_NS_NODE, &cfg_ns_timer_cmd);
install_element(L_NS_NODE, &cfg_nsip_local_ip_cmd);
install_element(L_NS_NODE, &cfg_nsip_local_port_cmd);
install_element(L_NS_NODE, &cfg_frgre_enable_cmd);
install_element(L_NS_NODE, &cfg_frgre_local_ip_cmd);
install_element(ENABLE_NODE, &nsvc_nsei_cmd);
return 0;
}

View File

@ -0,0 +1,68 @@
LIBOSMOGB_1.0 {
global:
bssgp_cause_str;
bssgp_create_cell_id;
bssgp_fc_in;
bssgp_fc_init;
bssgp_fc_ms_init;
bssgp_msgb_alloc;
bssgp_msgb_tlli_put;
bssgp_parse_cell_id;
bssgp_tx_bvc_block;
bssgp_tx_bvc_reset;
bssgp_tx_bvc_unblock;
bssgp_tx_flush_ll_ack;
bssgp_tx_llc_discarded;
bssgp_tx_ra_capa_upd;
bssgp_tx_radio_status_imsi;
bssgp_tx_radio_status_tlli;
bssgp_tx_radio_status_tmsi;
bssgp_tx_resume;
bssgp_tx_resume_ack;
bssgp_tx_resume_nack;
bssgp_tx_simple_bvci;
bssgp_tx_status;
bssgp_tx_suspend;
bssgp_tx_suspend_ack;
bssgp_tx_suspend_nack;
bssgp_tx_ul_ud;
bssgp_rcvmsg;
bssgp_rx_paging;
bssgp_set_log_ss;
bssgp_tx_dl_ud;
bssgp_tx_paging;
bssgp_vty_init;
bssgp_nsi;
gprs_ns_cause_str;
gprs_ns_destroy;
gprs_ns_frgre_listen;
gprs_ns_frgre_sendmsg;
gprs_ns_instantiate;
gprs_ns_nsip_listen;
gprs_ns_nsip_connect;
gprs_ns_rcvmsg;
gprs_ns_sendmsg;
gprs_ns_set_log_ss;
gprs_ns_tx_alive;
gprs_ns_tx_alive_ack;
gprs_ns_tx_block;
gprs_ns_tx_reset;
gprs_ns_tx_status;
gprs_ns_tx_unblock;
gprs_ns_vty_init;
gprs_nsvc_create;
gprs_nsvc_delete;
gprs_nsvc_reset;
gprs_nsvc_by_nsvci;
gprs_nsvc_by_nsei;
gprs_log_filter_fn;
btsctx_alloc;
btsctx_by_bvci_nsei;
btsctx_by_raid_cid;
local: *;
};

View File

@ -1,9 +1,9 @@
# 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=2:0:1
LIBVERSION=3:0:0
INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS = -fPIC -Wall
AM_CFLAGS = -Wall ${GCC_FVISIBILITY_HIDDEN}
# FIXME: this should eventually go into a milenage/Makefile.am
noinst_HEADERS = milenage/aes.h milenage/aes_i.h milenage/aes_wrap.h \
@ -19,7 +19,9 @@ libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c gsm_utils.c \
lapd_core.c lapdm.c \
auth_core.c auth_comp128v1.c auth_milenage.c \
milenage/aes-encblock.c milenage/aes-internal.c \
milenage/aes-internal-enc.c milenage/milenage.c
milenage/aes-internal-enc.c milenage/milenage.c gan.c
libosmogsm_la_LDFLAGS = -version-info $(LIBVERSION)
libosmogsm_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libosmogsm.map -version-info $(LIBVERSION)
libosmogsm_la_LIBADD = $(top_builddir)/src/libosmocore.la
EXTRA_DIST = libosmogsm.map

View File

@ -364,4 +364,4 @@ osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
}
}
/*! }@ */
/*! @} */

View File

@ -452,4 +452,4 @@ enum abis_nm_chan_comb abis_nm_pchan4chcomb(uint8_t chcomb)
return GSM_PCHAN_NONE;
}
/*! }@ */
/*! @} */

View File

@ -1,6 +1,6 @@
/* GSM/GPRS/3G authentication core infrastructure */
/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org>
/* (C) 2010-2012 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@ -30,11 +30,23 @@
#include <osmocom/crypt/auth.h>
/*! \addtogroup auth
* @{
*/
/* \file auth_core.c
*/
static LLIST_HEAD(osmo_auths);
static struct osmo_auth_impl *selected_auths[_OSMO_AUTH_ALG_NUM];
/* register a cipher with the core */
/*! \brief Register an authentication algorithm implementation with the core
* \param[in] impl Structure describing implementation and it's callbacks
*
* This function is called by an authentication implementation plugin to
* register itself with the authentication core.
*/
int osmo_auth_register(struct osmo_auth_impl *impl)
{
if (impl->algo >= ARRAY_SIZE(selected_auths))
@ -50,13 +62,23 @@ int osmo_auth_register(struct osmo_auth_impl *impl)
return 0;
}
/* load all available GPRS cipher plugins */
/*! \brief Load all available authentication plugins from the given path
* \param[in] path Path name of the directory containing the plugins
*
* This function will load all plugins contained in the specified path.
*/
int osmo_auth_load(const char *path)
{
/* load all plugins available from path */
return osmo_plugin_load_all(path);
}
/*! \brief Determine if a given authentication algorithm is supported
* \param[in] algo Algorithm which should be checked
*
* This function is used by an application to determine at runtime if a
* given authentication algorithm is supported or not.
*/
int osmo_auth_supported(enum osmo_auth_algo algo)
{
if (algo >= ARRAY_SIZE(selected_auths))
@ -68,6 +90,17 @@ int osmo_auth_supported(enum osmo_auth_algo algo)
return 0;
}
/*! \brief Generate authentication vector
* \param[out] vec Generated authentication vector
* \param[in] aud Subscriber-specific key material
* \param[in] rand Random challenge to be used
*
* This function performs the core cryptographic function of the AUC,
* computing authentication triples/quintuples based on the permanent
* subscriber data and a random value. The result is what is forwarded
* by the AUC via HLR and VLR to the MSC which will then be able to
* invoke authentication with the MS
*/
int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
struct osmo_sub_auth_data *aud,
const uint8_t *_rand)
@ -87,6 +120,20 @@ int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
return 0;
}
/*! \brief Generate authentication vector and re-sync sequence
* \param[out] vec Generated authentication vector
* \param[in] aud Subscriber-specific key material
* \param[in] rand_auts RAND value sent by the SIM/MS
* \param[in] auts AUTS value sent by the SIM/MS
* \param[in] rand Random challenge to be used to generate vector
*
* This function performs a special variant of the core cryptographic
* function of the AUC: computing authentication triples/quintuples
* based on the permanent subscriber data, a random value as well as the
* AUTS and RAND values returned by the SIM/MS. This special variant is
* needed if the sequence numbers between MS and AUC have for some
* reason become diffrent.
*/
int osmo_auth_gen_vec_auts(struct osmo_auth_vector *vec,
struct osmo_sub_auth_data *aud,
const uint8_t *rand_auts, const uint8_t *auts,
@ -100,7 +147,7 @@ int osmo_auth_gen_vec_auts(struct osmo_auth_vector *vec,
return impl->gen_vec_auts(vec, aud, rand_auts, auts, _rand);
}
const struct value_string auth_alg_vals[] = {
static const struct value_string auth_alg_vals[] = {
{ OSMO_AUTH_ALG_NONE, "None" },
{ OSMO_AUTH_ALG_COMP128v1, "COMP128v1" },
{ OSMO_AUTH_ALG_COMP128v2, "COMP128v2" },
@ -110,12 +157,16 @@ const struct value_string auth_alg_vals[] = {
{ 0, NULL }
};
/*! \brief Get human-readable name of authentication algorithm */
const char *osmo_auth_alg_name(enum osmo_auth_algo alg)
{
return get_value_string(auth_alg_vals, alg);
}
/*! \brief Parse human-readable name of authentication algorithm */
enum osmo_auth_algo osmo_auth_alg_parse(const char *name)
{
return get_string_value(auth_alg_vals, name);
}
/*! @} */

View File

@ -0,0 +1,77 @@
/* (C) 2012 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <unistd.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/protocol/gsm_44_318.h>
const struct value_string gan_msgt_vals[] = {
{ GA_MT_RC_DISCOVERY_REQUEST, "GA-RC DISCOVERY REQUEST" },
{ GA_MT_RC_DISCOVERY_ACCEPT, "GA-RC DISCOVERY ACCEPT" },
{ GA_MT_RC_DISCOVERY_REJECT, "GA-RC DISCOVERY REJECT" },
{ GA_MT_RC_REGISTER_REQUEST, "GA-RC REGISTER REQUEST" },
{ GA_MT_RC_REGISTER_ACCEPT, "GA-RC REGISTER ACCEPT" },
{ GA_MT_RC_REGISTER_REDIRECT, "GA-RC REGISTER REDIRECT" },
{ GA_MT_RC_REGISTER_REJECT, "GA-RC REGISTER REJECT" },
{ GA_MT_RC_DEREGISTER, "GA-RC DEREGISTER" },
{ GA_MT_RC_REGISTER_UPDATE_UL, "GA-RC REGISTER UPDATE UL" },
{ GA_MT_RC_REGISTER_UPDATE_DL, "GA-RC REGISTER UPDATE DL" },
{ GA_MT_RC_CELL_BCAST_INFO, "GA-RC CELL BROADCAST INFO" },
{ GA_MT_CSR_CIPH_MODE_CMD, "GA-CSR CIPHER MDOE COMMAND" },
{ GA_MT_CSR_CIPH_MODE_COMPL, "GA-CSR CIPHER MODE COMPLETE" },
{ GA_MT_CSR_ACT_CHAN, "GA-CSR ACTIVATE CHANNEL" },
{ GA_MT_CSR_ACT_CHAN_ACK, "GA-CSR ACTIVATE CHANNEL ACK" },
{ GA_MT_CSR_ACT_CHAN_COMPL, "GA-CSR ACTIVATE CHANNEL COMPLETE" },
{ GA_MT_CSR_ACT_CHAN_FAIL, "GA-CSR ACTIVATE CHANNEL FAIL" },
{ GA_MT_CSR_CHAN_MODE_MOD, "GA-CSR CHANNEL MODE MODIFY" },
{ GA_MT_CSR_CHAN_MODE_MOD_ACK, "GA-CSR CHANNEL MODE MODIFY ACK" },
{ GA_MT_CSR_RELEASE, "GA-CSR RELEASE" },
{ GA_MT_CSR_RELEASE_COMPL, "GA-CSR RELEASE COMPLETE" },
{ GA_MT_CSR_CLEAR_REQ, "GA-CSR CLEAR REQUEST" },
{ GA_MT_CSR_HO_ACCESS, "GA-CSR HANDOVER ACCESS" },
{ GA_MT_CSR_HO_COMPL, "GA-CSR HANDOVER COMPLETE" },
{ GA_MT_CSR_UL_QUAL_IND, "GA-CSR UL QUALITY INDICATION" },
{ GA_MT_CSR_HO_INFO, "GA-CSR HANDOVER INFO" },
{ GA_MT_CSR_HO_CMD, "GA-CSR HANDOVER COMMAND" },
{ GA_MT_CSR_HO_FAIL, "GA-CSR HANDOVER FAILURE" },
{ GA_MT_CSR_PAGING_REQ, "GA-CSR PAGING REQUEST" },
{ GA_MT_CSR_PAGING_RESP, "GA-CSR PAGING RESPONSE" },
{ GA_MT_CSR_UL_DIRECT_XFER, "GA-CSR UL DIRECT TRANSFER" },
{ GA_MT_CSR_DL_DIRECT_XFER, "GA-CSR DL DIRECT TRANSFER" },
{ GA_MT_CSR_STATUS, "GA-CSR STATUS" },
{ GA_MT_RC_KEEPALIVE, "GA-CSR KEEPALIVE" },
{ GA_MT_CSR_CM_ENQ, "GA-CSR CLASSMARK ENQUIRY" },
{ GA_MT_CSR_CM_CHANGE, "GA-CSR CLASSMARK CHANGE" },
{ GA_MT_PSR_GPRS_SUSPEND_REQ, "GA-PSR GPRS SUSPEND REQUEST" },
{ GA_RC_SYNC_INFO, "GA-RC SYNCH INFORMATION" },
{ GA_CSR_UTRAN_CM_CHG, "GA-CSR UTRAN CLASSMARK CHANGE" },
{ GA_MT_CSR_REQUEST, "GA-CSR REQUEST" },
{ GA_MT_CSR_REQUEST_ACCEPT, "GA-CSR REQUEST ACCEPT" },
{ GA_MT_CSR_REQUEST_REJECT, "GA-CSR REQUEST REJECT" },
{ 0, NULL }
};
static const struct value_string gan_pdisc_vals[] = {
{ GA_PDISC_RC, "RC" },
{ GA_PDISC_CSR, "CSR" },
{ GA_PDISC_PSR, "PSR" },
{ 0, NULL }
};

View File

@ -25,6 +25,7 @@
*
*/
#include "../../config.h"
#include <time.h>
#include <string.h>
@ -80,7 +81,12 @@ void gsm340_gen_scts(uint8_t *scts, time_t time)
*scts++ = gsm411_bcdify(tm->tm_hour);
*scts++ = gsm411_bcdify(tm->tm_min);
*scts++ = gsm411_bcdify(tm->tm_sec);
*scts++ = gsm411_bcdify(0); /* GMT */
#ifdef HAVE_TM_GMTOFF_IN_TM
*scts++ = gsm411_bcdify(tm->tm_gmtoff/(60*15));
#else
#warning find a portable way to obtain timezone offset
*scts++ = 0;
#endif
}
/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
@ -101,6 +107,9 @@ time_t gsm340_scts(uint8_t *scts)
tm.tm_hour = gsm411_unbcdify(*scts++);
tm.tm_min = gsm411_unbcdify(*scts++);
tm.tm_sec = gsm411_unbcdify(*scts++);
#ifdef HAVE_TM_GMTOFF_IN_TM
tm.tm_gmtoff = gsm411_unbcdify(*scts++) * 15*60;
#endif
/* according to gsm 03.40 time zone is
"expressed in quarters of an hour" */

View File

@ -285,6 +285,27 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
lai48->lac = htons(lac);
}
/* Attention: this function retunrs true integers, not hex! */
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
uint16_t *mnc, uint16_t *lac)
{
*mcc = (lai->digits[0] & 0x0f) * 100
+ (lai->digits[0] >> 4) * 10
+ (lai->digits[1] & 0x0f);
if ((lai->digits[1] & 0xf0) == 0xf0) {
*mnc = (lai->digits[2] & 0x0f) * 10
+ (lai->digits[2] >> 4);
} else {
*mnc = (lai->digits[2] & 0x0f) * 100
+ (lai->digits[2] >> 4) * 10
+ (lai->digits[1] >> 4);
}
*lac = ntohs(lai->lac);
return 0;
}
int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi)
{
uint32_t *tptr = (uint32_t *) &buf[3];

View File

@ -110,7 +110,7 @@ int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len,
return (bcd_cur - bcd_lv);
}
/* decode 'bearer capability' */
/* TS 04.08 10.5.4.5: decode 'bearer capability' */
int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
const uint8_t *lv)
{
@ -128,7 +128,8 @@ int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
bcap->coding = (lv[1] & 0x10) >> 4;
bcap->radio = (lv[1] & 0x60) >> 5;
if (bcap->transfer == GSM_MNCC_BCAP_SPEECH) {
switch (bcap->transfer) {
case GSM_MNCC_BCAP_SPEECH:
i = 1;
s = 0;
while(!(lv[i] & 0x80)) {
@ -142,7 +143,68 @@ int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
if (s == 7) /* maximum speech versions + end of list */
return 0;
}
} else {
break;
case GSM_MNCC_BCAP_UNR_DIG:
case GSM_MNCC_BCAP_FAX_G3:
i = 1;
while(!(lv[i] & 0x80)) {
i++; /* octet 3a etc */
if (in_len < i)
return 0;
/* ignore them */
}
/* octet 4: skip */
i++;
/* octet 5 */
i++;
if (in_len < i)
return 0;
bcap->data.rate_adaption = (lv[i] >> 3) & 3;
bcap->data.sig_access = lv[i] & 7;
while(!(lv[i] & 0x80)) {
i++; /* octet 5a etc */
if (in_len < i)
return 0;
/* ignore them */
}
/* octet 6 */
i++;
if (in_len < i)
return 0;
bcap->data.async = lv[i] & 1;
if (!(lv[i] & 0x80)) {
i++;
if (in_len < i)
return 0;
/* octet 6a */
bcap->data.nr_stop_bits = ((lv[i] >> 7) & 1) + 1;
if (lv[i] & 0x10)
bcap->data.nr_data_bits = 8;
else
bcap->data.nr_data_bits = 7;
bcap->data.user_rate = lv[i] & 0xf;
if (!(lv[i] & 0x80)) {
i++;
if (in_len < i)
return 0;
/* octet 6b */
bcap->data.parity = lv[i] & 7;
bcap->data.interm_rate = (lv[i] >> 5) & 3;
/* octet 6c */
if (!(lv[i] & 0x80)) {
i++;
if (in_len < i)
return 0;
bcap->data.transp = (lv[i] >> 5) & 3;
bcap->data.modem_type = lv[i] & 0x1F;
}
}
}
break;
default:
i = 1;
while (!(lv[i] & 0x80)) {
i++; /* octet 3a etc */
@ -151,12 +213,13 @@ int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
/* ignore them */
}
/* FIXME: implement OCTET 4+ parsing */
break;
}
return 0;
}
/* encode 'bearer capability' */
/* TS 04.08 10.5.4.5: encode 'bearer capability' */
int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only,
const struct gsm_mncc_bearer_cap *bcap)
{
@ -168,7 +231,8 @@ int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only,
lv[1] |= bcap->coding << 4;
lv[1] |= bcap->radio << 5;
if (bcap->transfer == GSM_MNCC_BCAP_SPEECH) {
switch (bcap->transfer) {
case GSM_MNCC_BCAP_SPEECH:
for (s = 0; bcap->speech_ver[s] >= 0; s++) {
i++; /* octet 3a etc */
lv[i] = bcap->speech_ver[s];
@ -176,8 +240,29 @@ int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only,
lv[i] |= bcap->speech_ctm << 5;
}
lv[i] |= 0x80; /* last IE of octet 3 etc */
} else {
/* FIXME: implement OCTET 4+ encoding */
break;
case GSM48_BCAP_ITCAP_UNR_DIG_INF:
case GSM48_BCAP_ITCAP_FAX_G3:
lv[i++] |= 0x80; /* last IE of octet 3 etc */
/* octet 4 */
lv[i++] = 0xb8;
/* octet 5 */
lv[i++] = 0x80 | ((bcap->data.rate_adaption & 3) << 3)
| (bcap->data.sig_access & 7);
/* octet 6 */
lv[i++] = 0x20 | (bcap->data.async & 1);
/* octet 6a */
lv[i++] = (bcap->data.user_rate & 0xf) |
(bcap->data.nr_data_bits == 8 ? 0x10 : 0x00) |
(bcap->data.nr_stop_bits == 2 ? 0x40 : 0x00);
/* octet 6b */
lv[i++] = (bcap->data.parity & 7) |
((bcap->data.interm_rate & 3) << 5);
/* octet 6c */
lv[i] = 0x80 | (bcap->data.modem_type & 0x1f);
break;
default:
return -EINVAL;
}
lv[0] = i;
@ -189,7 +274,7 @@ int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only,
return 0;
}
/* decode 'call control cap' */
/* TS 04.08 10.5.4.5a: decode 'call control cap' */
int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv)
{
uint8_t in_len = lv[0];
@ -204,7 +289,7 @@ int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv)
return 0;
}
/* encode 'call control cap' */
/* TS 04.08 10.5.4.5a: encode 'call control cap' */
int gsm48_encode_cccap(struct msgb *msg,
const struct gsm_mncc_cccap *ccap)
{
@ -222,7 +307,7 @@ int gsm48_encode_cccap(struct msgb *msg,
return 0;
}
/* decode 'called party BCD number' */
/* TS 04.08 10.5.4.7: decode 'called party BCD number' */
int gsm48_decode_called(struct gsm_mncc_number *called,
const uint8_t *lv)
{
@ -241,7 +326,7 @@ int gsm48_decode_called(struct gsm_mncc_number *called,
return 0;
}
/* encode 'called party BCD number' */
/* TS 04.08 10.5.4.7: encode 'called party BCD number' */
int gsm48_encode_called(struct msgb *msg,
const struct gsm_mncc_number *called)
{
@ -321,7 +406,7 @@ int gsm48_encode_callerid(struct msgb *msg, int ie, int max_len,
return 0;
}
/* decode 'cause' */
/* TS 04.08 10.5.4.11: decode 'cause' */
int gsm48_decode_cause(struct gsm_mncc_cause *cause,
const uint8_t *lv)
{
@ -364,7 +449,7 @@ int gsm48_decode_cause(struct gsm_mncc_cause *cause,
return 0;
}
/* encode 'cause' */
/* TS 04.08 10.5.4.11: encode 'cause' */
int gsm48_encode_cause(struct msgb *msg, int lv_only,
const struct gsm_mncc_cause *cause)
{
@ -404,49 +489,49 @@ int gsm48_encode_cause(struct msgb *msg, int lv_only,
return 0;
}
/* decode 'calling number' */
/* TS 04.08 10.5.4.9: 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' */
/* TS 04.08 10.5.4.9: 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' */
/* TS 04.08 10.5.4.13: 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' */
/* TS 04.08 10.5.4.13: 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' */
/* TS 04.08 10.5.4.21b: 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' */
/* TS 04.08 10.5.4.21b: 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' */
/* TS 04.08 10.5.4.15: decode 'facility' */
int gsm48_decode_facility(struct gsm_mncc_facility *facility,
const uint8_t *lv)
{
@ -464,7 +549,7 @@ int gsm48_decode_facility(struct gsm_mncc_facility *facility,
return 0;
}
/* encode 'facility' */
/* TS 04.08 10.5.4.15: encode 'facility' */
int gsm48_encode_facility(struct msgb *msg, int lv_only,
const struct gsm_mncc_facility *facility)
{
@ -483,7 +568,7 @@ int gsm48_encode_facility(struct msgb *msg, int lv_only,
return 0;
}
/* decode 'notify' */
/* TS 04.08 10.5.4.20: decode 'notify' */
int gsm48_decode_notify(int *notify, const uint8_t *v)
{
*notify = v[0] & 0x7f;
@ -491,7 +576,7 @@ int gsm48_decode_notify(int *notify, const uint8_t *v)
return 0;
}
/* encode 'notify' */
/* TS 04.08 10.5.4.20: encode 'notify' */
int gsm48_encode_notify(struct msgb *msg, int notify)
{
msgb_v_put(msg, notify | 0x80);
@ -499,7 +584,7 @@ int gsm48_encode_notify(struct msgb *msg, int notify)
return 0;
}
/* decode 'signal' */
/* TS 04.08 10.5.4.23: decode 'signal' */
int gsm48_decode_signal(int *signal, const uint8_t *v)
{
*signal = v[0];
@ -507,7 +592,7 @@ int gsm48_decode_signal(int *signal, const uint8_t *v)
return 0;
}
/* encode 'signal' */
/* TS 04.08 10.5.4.23: encode 'signal' */
int gsm48_encode_signal(struct msgb *msg, int signal)
{
msgb_tv_put(msg, GSM48_IE_SIGNAL, signal);
@ -515,7 +600,7 @@ int gsm48_encode_signal(struct msgb *msg, int signal)
return 0;
}
/* decode 'keypad' */
/* TS 04.08 10.5.4.17: decode 'keypad' */
int gsm48_decode_keypad(int *keypad, const uint8_t *lv)
{
uint8_t in_len = lv[0];
@ -528,7 +613,7 @@ int gsm48_decode_keypad(int *keypad, const uint8_t *lv)
return 0;
}
/* encode 'keypad' */
/* TS 04.08 10.5.4.17: encode 'keypad' */
int gsm48_encode_keypad(struct msgb *msg, int keypad)
{
msgb_tv_put(msg, GSM48_IE_KPD_FACILITY, keypad);
@ -536,7 +621,7 @@ int gsm48_encode_keypad(struct msgb *msg, int keypad)
return 0;
}
/* decode 'progress' */
/* TS 04.08 10.5.4.21: decode 'progress' */
int gsm48_decode_progress(struct gsm_mncc_progress *progress,
const uint8_t *lv)
{
@ -552,7 +637,7 @@ int gsm48_decode_progress(struct gsm_mncc_progress *progress,
return 0;
}
/* encode 'progress' */
/* TS 04.08 10.5.4.21: encode 'progress' */
int gsm48_encode_progress(struct msgb *msg, int lv_only,
const struct gsm_mncc_progress *p)
{
@ -569,7 +654,7 @@ int gsm48_encode_progress(struct msgb *msg, int lv_only,
return 0;
}
/* decode 'user-user' */
/* TS 04.08 10.5.4.25: decode 'user-user' */
int gsm48_decode_useruser(struct gsm_mncc_useruser *uu,
const uint8_t *lv)
{
@ -595,7 +680,7 @@ int gsm48_decode_useruser(struct gsm_mncc_useruser *uu,
return 0;
}
/* encode 'useruser' */
/* TS 04.08 10.5.4.25: encode 'useruser' */
int gsm48_encode_useruser(struct msgb *msg, int lv_only,
const struct gsm_mncc_useruser *uu)
{
@ -615,7 +700,7 @@ int gsm48_encode_useruser(struct msgb *msg, int lv_only,
return 0;
}
/* decode 'ss version' */
/* TS 04.08 10.5.4.24: decode 'ss version' */
int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv,
const uint8_t *lv)
{
@ -630,7 +715,7 @@ int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv,
return 0;
}
/* encode 'ss version' */
/* TS 04.08 10.5.4.24: encode 'ss version' */
int gsm48_encode_ssversion(struct msgb *msg,
const struct gsm_mncc_ssversion *ssv)
{
@ -648,7 +733,7 @@ int gsm48_encode_ssversion(struct msgb *msg,
/* decode 'more data' does not require a function, because it has no value */
/* encode 'more data' */
/* TS 04.08 10.5.4.19: encode 'more data' */
int gsm48_encode_more(struct msgb *msg)
{
uint8_t *ie;

View File

@ -391,7 +391,6 @@ static int rsl_rll_error(uint8_t cause, struct lapdm_msg_ctx *mctx)
LOGP(DLLAPD, LOGL_NOTICE, "sending MDL-ERROR-IND %d\n", cause);
msg = rsl_rll_simple(RSL_MT_ERROR_IND, mctx->chan_nr, mctx->link_id, 1);
msg->l2h = msgb_put(msg, sizeof(struct abis_rsl_rll_hdr));
msgb_tlv_put(msg, RSL_IE_RLM_CAUSE, 1, &cause);
return rslms_sendmsg(msg, mctx->dl->entity);
}
@ -960,7 +959,12 @@ static int rslms_rx_rll_rel_req(struct msgb *msg, struct lapdm_datalink *dl)
mode = rllh->data[1] & 1;
/* Pull rllh */
msgb_pull(msg, msg->tail - msg->l2h);
msgb_pull_l2h(msg);
/* 04.06 3.8.3: No information field is permitted with the DISC
* command. */
msg->len = 0;
msg->tail = msg->l3h = msg->data;
/* prepare prim */
osmo_prim_init(&dp.oph, 0, PRIM_DL_REL, PRIM_OP_REQUEST, msg);
@ -1242,4 +1246,4 @@ void lapdm_channel_set_flags(struct lapdm_channel *lc, unsigned int flags)
lapdm_entity_set_flags(&lc->lapdm_acch, flags);
}
/*! }@ */
/*! @} */

View File

@ -0,0 +1,236 @@
LIBOSMOGSM_1.0 {
global:
abis_nm_adm_state_names;
abis_nm_att_settable;
abis_nm_avail_name;
abis_nm_chcomb4pchan;
abis_nm_debugp_foh;
abis_nm_event_type_name;
abis_nm_nack_cause_name;
abis_nm_nack_name;
abis_nm_att_tlvdef;
abis_nm_obj_class_names;
abis_nm_opstate_name;
abis_nm_nacks;
abis_nm_no_ack_nack;
abis_nm_pchan4chcomb;
abis_nm_reports;
abis_nm_severity_name;
abis_nm_sw_load_msgs;
abis_nm_test_name;
osmo_sitype_strs;
comp128;
dbm2rxlev;
gprs_cipher_gen_input_i;
gprs_cipher_gen_input_ui;
gprs_cipher_load;
gprs_cipher_register;
gprs_cipher_run;
gprs_cipher_supported;
gprs_tlli_type;
gprs_tmsi2tlli;
gsm0480_create_notifySS;
gsm0480_create_unstructuredSS_Notify;
gsm0480_create_ussd_resp;
gsm0480_decode_ussd_request;
gsm0480_wrap_facility;
gsm0480_wrap_invoke;
gsm0502_calc_paging_group;
gsm0808_att_tlvdef;
gsm0808_bssap_name;
gsm0808_bssmap_name;
gsm0808_create_assignment_completed;
gsm0808_create_assignment_failure;
gsm0808_create_cipher_complete;
gsm0808_create_cipher_reject;
gsm0808_create_classmark_update;
gsm0808_create_clear_command;
gsm0808_create_clear_complete;
gsm0808_create_clear_rqst;
gsm0808_create_dtap;
gsm0808_create_layer3;
gsm0808_create_reset;
gsm0808_create_sapi_reject;
gsm0808_prepend_dtap_header;
gsm338_get_sms_alphabet;
gsm340_gen_oa;
gsm340_gen_scts;
gsm340_scts;
gsm340_validity_period;
gsm411_bcdify;
gsm411_msgb_alloc;
gsm411_push_cp_header;
gsm411_push_rp_header;
gsm411_smc_clear;
gsm411_smc_init;
gsm411_smc_recv;
gsm411_smc_send;
gsm411_smr_clear;
gsm411_smr_init;
gsm411_smr_recv;
gsm411_smr_send;
gsm411_unbcdify;
gsm411_cp_cause_strs;
gsm411_rp_cause_strs;
gsm48_att_tlvdef;
gsm48_cc_msg_name;
gsm48_cc_state_name;
gsm48_construct_ra;
gsm48_decode_bcd_number;
gsm48_decode_bearer_cap;
gsm48_decode_called;
gsm48_decode_callerid;
gsm48_decode_calling;
gsm48_decode_cause;
gsm48_decode_cccap;
gsm48_decode_connected;
gsm48_decode_facility;
gsm48_decode_freq_list;
gsm48_decode_keypad;
gsm48_decode_lai;
gsm48_decode_notify;
gsm48_decode_progress;
gsm48_decode_redirecting;
gsm48_decode_signal;
gsm48_decode_ssversion;
gsm48_decode_useruser;
gsm48_encode_bcd_number;
gsm48_encode_bearer_cap;
gsm48_encode_called;
gsm48_encode_callerid;
gsm48_encode_calling;
gsm48_encode_cause;
gsm48_encode_cccap;
gsm48_encode_connected;
gsm48_encode_facility;
gsm48_encode_keypad;
gsm48_encode_more;
gsm48_encode_notify;
gsm48_encode_progress;
gsm48_encode_redirecting;
gsm48_encode_signal;
gsm48_encode_ssversion;
gsm48_encode_useruser;
gsm48_generate_lai;
gsm48_generate_mid_from_imsi;
gsm48_generate_mid_from_tmsi;
gsm48_mi_to_string;
gsm48_mm_att_tlvdef;
gsm48_number_of_paging_subchannels;
gsm48_parse_ra;
gsm48_rr_att_tlvdef;
gsm_7bit_decode;
gsm_7bit_decode_hdr;
gsm_7bit_encode;
gsm_arfcn2band;
gsm_arfcn2freq10;
gsm_band_name;
gsm_band_parse;
gsm_fn2gsmtime;
gsm_get_octet_len;
gsm_gsmtime2fn;
gsm_milenage;
gsm_septet_encode;
gsm_septets2octets;
lapd_dl_exit;
lapd_dl_init;
lapd_dl_reset;
lapd_msgb_alloc;
lapd_ph_data_ind;
lapd_recv_dlsap;
lapd_set_mode;
lapd_state_names;
lapdm_channel_exit;
lapdm_channel_init;
lapdm_channel_reset;
lapdm_channel_set_flags;
lapdm_channel_set_l1;
lapdm_channel_set_l3;
lapdm_channel_set_mode;
lapdm_entity_exit;
lapdm_entity_init;
lapdm_entity_reset;
lapdm_entity_set_flags;
lapdm_entity_set_mode;
lapdm_phsap_dequeue_prim;
lapdm_phsap_up;
lapdm_rslms_recvmsg;
milenage_auts;
milenage_check;
milenage_f1;
milenage_f2345;
milenage_generate;
milenage_opc_gen;
ms_class_gmsk_dbm;
ms_pwr_ctl_lvl;
ms_pwr_dbm;
osmo_a5;
osmo_a5_1;
osmo_a5_2;
osmo_auth_alg_name;
osmo_auth_alg_parse;
osmo_auth_gen_vec;
osmo_auth_gen_vec_auts;
osmo_auth_load;
osmo_auth_register;
osmo_auth_supported;
osmo_rsl2sitype;
osmo_sitype2rsl;
rr_cause_name;
rsl_att_tlvdef;
rsl_ccch_conf_to_bs_cc_chans;
rsl_ccch_conf_to_bs_ccch_sdcch_comb;
rsl_chan_nr_str;
rsl_dec_chan_nr;
rsl_enc_chan_nr;
rsl_err_name;
rsl_init_cchan_hdr;
rsl_init_rll_hdr;
rsl_ipac_msg_name;
rsl_msg_name;
rsl_rll_push_hdr;
rsl_rll_push_l3;
rsl_rll_simple;
rsl_rlm_cause_name;
rxlev2dbm;
rxlev_stat_dump;
rxlev_stat_get_next;
rxlev_stat_input;
rxlev_stat_reset;
tlv_def_patch;
tlv_dump;
tlv_parse;
tlv_parse_one;
tvlv_att_def;
vtvlv_gan_att_def;
gan_msgt_vals;
gan_pdisc_vals;
local: *;
};

View File

@ -504,4 +504,4 @@ struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
return msg;
}
/*! }@ */
/*! @} */

View File

@ -9,6 +9,7 @@
/*! \file tlv.c */
struct tlv_definition tvlv_att_def;
struct tlv_definition vtvlv_gan_att_def;
/*! \brief Dump pasred TLV structure to stdout */
int tlv_dump(struct tlv_parsed *dec)
@ -69,7 +70,7 @@ int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
len = def->def[tag].fixed_len + 1;
break;
case TLV_TYPE_TLV:
/* GSM TS 04.07 11.2.4: Type 4 TLV */
tlv: /* GSM TS 04.07 11.2.4: Type 4 TLV */
if (buf + 1 > buf + buf_len)
return -1;
*o_val = buf+2;
@ -78,6 +79,22 @@ int tlv_parse_one(uint8_t *o_tag, uint16_t *o_len, const uint8_t **o_val,
if (len > buf_len)
return -2;
break;
case TLV_TYPE_vTvLV_GAN: /* 44.318 / 11.1.4 */
/* FIXME: variable-length TAG! */
if (*(buf+1) & 0x80) {
/* like TL16Vbut without highest bit of len */
if (2 > buf_len)
return -1;
*o_val = buf+3;
*o_len = (*(buf+1) & 0x7F) << 8 | *(buf+2);
len = *o_len + 3;
if (len > buf_len)
return -2;
} else {
/* like TLV */
goto tlv;
}
break;
case TLV_TYPE_TvLV:
if (*(buf+1) & 0x80) {
/* like TLV, but without highest bit of len */
@ -184,6 +201,9 @@ 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;
for (i = 0; i < ARRAY_SIZE(vtvlv_gan_att_def.def); i++)
vtvlv_gan_att_def.def[i].type = TLV_TYPE_vTvLV_GAN;
}
/*! }@ */
/*! @} */

Some files were not shown because too many files have changed in this diff Show More