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:
commit
d08b949c2b
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
dh_auto_configure
|
||||
dh_auto_build
|
||||
dh_auto_test
|
||||
dh_prep
|
||||
dh_installdirs
|
||||
dh_auto_install
|
|
@ -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...
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
3.0 (git)
|
||||
3.0 (native)
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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' $< > $@
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
if ENABLE_VTY
|
||||
SUBDIRS = vty codec crypt gsm core
|
||||
else
|
||||
SUBDIRS = codec crypt gsm core
|
||||
endif
|
|
@ -1,3 +0,0 @@
|
|||
osmocodec_HEADERS = codec.h
|
||||
|
||||
osmocodecdir = $(includedir)/osmocom/codec
|
|
@ -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 */
|
||||
|
|
|
@ -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' $< > $@
|
|
@ -2,5 +2,6 @@
|
|||
#define _OSMO_BACKTRACE_H_
|
||||
|
||||
void osmo_generate_backtrace(void);
|
||||
void osmo_log_backtrace(int subsys, int level);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -36,6 +36,6 @@
|
|||
#include <osmocom/core/crc32gen.h>
|
||||
#include <osmocom/core/crc64gen.h>
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
||||
#endif /* __OSMO_CRCGEN_H__ */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -74,6 +74,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
||||
#endif /* TIMER_COMPAT_H */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
osmocrypt_HEADERS = gprs_cipher.h auth.h
|
||||
|
||||
osmocryptdir = $(includedir)/osmocom/crypt
|
|
@ -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 */
|
||||
|
||||
/* @} */
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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__ */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -143,6 +143,7 @@ enum gsm_chan_t {
|
|||
GSM_LCHAN_TCH_H,
|
||||
GSM_LCHAN_UNKNOWN,
|
||||
GSM_LCHAN_CCCH,
|
||||
GSM_LCHAN_PDTCH,
|
||||
_GSM_LCHAN_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -743,6 +743,6 @@ enum ipac_bcch_info_type {
|
|||
IPAC_BINF_CELL_ALLOC = (1 << 2),
|
||||
};
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
||||
#endif /* PROTO_GSM_12_21_H */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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' $< > $@
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -185,4 +185,4 @@ void osmo_revbytebits_buf(uint8_t *buf, int len)
|
|||
}
|
||||
}
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
|
|
@ -261,4 +261,4 @@ int bitvec_find_bit_pos(const struct bitvec *bv, unsigned int n,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -628,4 +628,4 @@ osmo_conv_decode(const struct osmo_conv_code *code,
|
|||
return rv;
|
||||
}
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
|
|
@ -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: */
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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: *;
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -364,4 +364,4 @@ osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
|
|||
}
|
||||
}
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
|
|
@ -452,4 +452,4 @@ enum abis_nm_chan_comb abis_nm_pchan4chcomb(uint8_t chcomb)
|
|||
return GSM_PCHAN_NONE;
|
||||
}
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
|
@ -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" */
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
|
|
@ -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: *;
|
||||
};
|
|
@ -504,4 +504,4 @@ struct msgb *rsl_rll_simple(uint8_t msg_type, uint8_t chan_nr,
|
|||
return msg;
|
||||
}
|
||||
|
||||
/*! }@ */
|
||||
/*! @} */
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue