Compare commits
97 Commits
Author | SHA1 | Date |
---|---|---|
Oliver Smith | 7ba62d3061 | |
Vadim Yanitskiy | 62b28ffe1b | |
Vadim Yanitskiy | cdf716cf9a | |
Oliver Smith | a9c39c04de | |
Vadim Yanitskiy | 282de031f1 | |
Vadim Yanitskiy | c3156193da | |
Alexander Couzens | cd3a8cfad6 | |
Alexander Couzens | e51b3be379 | |
Alexander Couzens | b34e0a5720 | |
Oliver Smith | 05363e0a32 | |
Max | a07e6d9c58 | |
Harald Welte | 1ede89a35a | |
Harald Welte | 647304fbe5 | |
Harald Welte | 370d6e8b59 | |
Pau Espin | dc4c294f94 | |
Vadim Yanitskiy | f2545b1b8f | |
Andreas Eversberg | 1f1d90f175 | |
Oliver Smith | 2a89bbf66f | |
Daniel Willmann | 676777c5f9 | |
Daniel Willmann | ff9c46cc61 | |
Daniel Willmann | 75a0aa78a3 | |
Daniel Willmann | 20aef4de28 | |
Philipp Maier | e746b0bef6 | |
Pau Espin | 57567968ea | |
Philipp Maier | 7e4dbb4b34 | |
Philipp Maier | 7840375d51 | |
Philipp Maier | 429d332ece | |
Philipp Maier | f24970a7ca | |
Pau Espin | 2365fec0fb | |
Pau Espin | 5df65b6c30 | |
Pau Espin | 5f1020b963 | |
Oliver Smith | eda1b83f75 | |
Vadim Yanitskiy | b83aabaa95 | |
Pau Espin | 1bebd08a4b | |
Oliver Smith | a86056fdf3 | |
Vadim Yanitskiy | 99ec755643 | |
Pau Espin | d5dca3a67f | |
Vadim Yanitskiy | 3c26a1dc3c | |
arehbein | 642019f288 | |
Oliver Smith | f8a5066ad0 | |
Pau Espin | 8c42673eba | |
Pau Espin | 07feb06d54 | |
Pau Espin | 86b630cfe1 | |
Pau Espin | 93bc518b53 | |
Pau Espin | 58101ea587 | |
Pau Espin | 6aad14c3fa | |
Pau Espin | f44dfa8a0e | |
Pau Espin | e931b39b3c | |
Pau Espin | fd9e82da31 | |
Pau Espin | f2307c483f | |
Pau Espin | 15a52d92c4 | |
Pau Espin | 05190c36bb | |
Pau Espin | 3d3c8c55f0 | |
Pau Espin | 164a1eeb8a | |
Pau Espin | 69569879ae | |
Pau Espin | fd4d435442 | |
Pau Espin | 8ec269a0e0 | |
Pau Espin | 4bd6f663a7 | |
Pau Espin | 52c9b8e593 | |
Pau Espin | 51028e2c16 | |
Pau Espin | e69f460ae7 | |
Pau Espin | 0e707fc83a | |
Pau Espin | ffd6e37eb5 | |
Pau Espin | 44bde6b85a | |
Pau Espin | e659f75cf1 | |
Pau Espin | 67e71eac1c | |
Pau Espin | c1cf4af11b | |
Pau Espin | f37aedbf76 | |
Pau Espin | 920c6c8c81 | |
Pau Espin | df203361e8 | |
Pau Espin | b61ab9b9ac | |
Pau Espin | 5f4736aa85 | |
Pau Espin | fc1a5538d0 | |
Pau Espin | eb967fccb2 | |
Pau Espin | 13c00008b4 | |
Pau Espin | e5614e434f | |
Pau Espin | b0b582bff8 | |
Pau Espin | bc46812bd7 | |
Pau Espin | 4398ac073b | |
Pau Espin | 05d5f28e93 | |
Pau Espin | 7a74ae492e | |
Pau Espin | 749ca7c850 | |
Max | e7ccfdb4aa | |
Oliver Smith | e39ff86dd9 | |
Pau Espin | 57b63875c7 | |
Oliver Smith | 55e3dc8ec8 | |
Oliver Smith | acd967a177 | |
Pau Espin | 8501126031 | |
Max | b43496a60d | |
Max | caff83e702 | |
Max | 61f2186592 | |
Max | 559636a4a2 | |
Vadim Yanitskiy | 13ccbc1e61 | |
Vadim Yanitskiy | d32852664d | |
Max | 77cdc424cb | |
Vadim Yanitskiy | fb6cf3221e | |
Vadim Yanitskiy | c63a8381e5 |
|
@ -0,0 +1 @@
|
|||
open_collective: osmocom
|
|
@ -6,8 +6,8 @@ debian/*.log
|
|||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
bscconfig.h
|
||||
bscconfig.h.in
|
||||
config.h
|
||||
config.h.in
|
||||
*.*~
|
||||
*.sw?
|
||||
.libs
|
||||
|
|
|
@ -19,7 +19,7 @@ SUBDIRS = \
|
|||
BUILT_SOURCES = $(top_srcdir)/.version
|
||||
EXTRA_DIST = \
|
||||
.version \
|
||||
contrib/osmo-sgsn.spec.in \
|
||||
README.md \
|
||||
debian \
|
||||
git-version-gen \
|
||||
osmoappdesc.py \
|
||||
|
|
43
README.md
43
README.md
|
@ -1,28 +1,30 @@
|
|||
osmo-sgssn - Osmocom SGSN Implementation
|
||||
========================================
|
||||
osmo-sgsn - Osmocom SGSN Implementation
|
||||
=======================================
|
||||
|
||||
This repository contains a C-language implementation of a GSM Serving GPRS
|
||||
Support Node (SGSN) for 2G (GSM) and 3G (UMTS). It is part of the
|
||||
This repository contains a C-language implementation of a *Serving GPRS
|
||||
Support Node (SGSN)* for 2.5/2.75G (GPRS/EDGE) and 3G (UMTS). It is part of the
|
||||
[Osmocom](https://osmocom.org/) Open Source Mobile Communications
|
||||
project.
|
||||
|
||||
OsmoSGSN exposes
|
||||
* Gb towards PCUs (e.g. OsmoPCU): Various GbIP flavors + Gb/FR/E1
|
||||
* GTP towards a GGSN (e.g. OsmoGGSN);
|
||||
* IuPS over IP towards RNCs / HNBGW (e.g. osmo-hnbgw)
|
||||
* The Osmocom typical telnet VTY and CTRL interfaces.
|
||||
* The Osmocom typical statsd exporter.
|
||||
* GSUP (custom MAP-like protocol) towards osmo-hlr
|
||||
|
||||
* *Gb* towards PCUs (e.g. [OsmoPCU](https://osmocom.org/projects/osmopcu/wiki/OsmoPCU)): Various GbIP flavors + Gb/FR/E1
|
||||
* *GTP* towards a GGSN (e.g. [OsmoGGSN](https://osmocom.org/projects/openggsn/wiki))
|
||||
* IuPS over IP towards RNCs / HNBGW (e.g. [osmo-hnbgw](https://osmocom.org/projects/osmohnbgw/wiki))
|
||||
* The Osmocom typical telnet *VTY* and *CTRL* interfaces.
|
||||
* The Osmocom typical *statsd* exporter.
|
||||
* GSUP (custom MAP-like protocol) towards [osmo-hlr](https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR)
|
||||
|
||||
OsmoSGSN implements
|
||||
|
||||
* GPRS mobility management
|
||||
* GPRS session management
|
||||
|
||||
|
||||
Homepage
|
||||
--------
|
||||
|
||||
You can find the OsmoSGSN issue tracker and wiki online at
|
||||
<https://osmocom.org/projects/osmosgsn> and <https://osmocom.org/projects/osmosgsn/wiki>.
|
||||
You can find the OsmoSGSN homepage online at <https://osmocom.org/projects/osmosgsn/wiki>.
|
||||
|
||||
|
||||
GIT Repository
|
||||
|
@ -46,6 +48,14 @@ Pre-rendered PDF version of the current "master" can be found at
|
|||
as well as the [VTY Reference Manual](https://ftp.osmocom.org/docs/latest/osmosgsn-vty-reference.pdf)
|
||||
|
||||
|
||||
Forum
|
||||
-----
|
||||
|
||||
We welcome any osmo-sgsn related discussions in the
|
||||
[Cellular Network Infratructure -> 2G/3G Core Network](https://discourse.osmocom.org/c/cni/2g-3g-cn).
|
||||
section of the osmocom discourse (web based Forum).
|
||||
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
|
||||
|
@ -58,6 +68,15 @@ Please observe the [Osmocom Mailing List
|
|||
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
|
||||
when posting.
|
||||
|
||||
|
||||
Issue Tracker
|
||||
-------------
|
||||
|
||||
We use the [issue tracker of the osmo-sgsn project on osmocom.org](https://osmocom.org/projects/osmosgsn/issues) for
|
||||
tracking the state of bug reports and feature requests. Feel free to submit any issues you may find, or help
|
||||
us out by resolving existing issues.
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
#component what description / commit summary line
|
||||
libosmocore > 1.9.0 gsup.h: Using new fields in struct osmo_gsup_pdp_info (ABI break)
|
33
configure.ac
33
configure.ac
|
@ -38,30 +38,23 @@ dnl use a defined standard across all builds and don't depend on compiler defaul
|
|||
CFLAGS="$CFLAGS -std=gnu11"
|
||||
|
||||
dnl checks for libraries
|
||||
AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
|
||||
AC_SUBST(LIBRARY_DL)
|
||||
|
||||
AC_SEARCH_LIBS([dlsym], [dl dld], [LIBRARY_DLSYM="$LIBS";LIBS=""])
|
||||
AC_SUBST(LIBRARY_DLSYM)
|
||||
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.7.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.7.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.7.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.7.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.7.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.2.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.5.0)
|
||||
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.5.0)
|
||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.7.0)
|
||||
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.11.0)
|
||||
|
||||
# Enable/disable 3G aka IuPS + IuCS support?
|
||||
AC_ARG_ENABLE([iu], [AS_HELP_STRING([--enable-iu], [Build 3G support, aka IuPS and IuCS interfaces])],
|
||||
[osmo_ac_iu="$enableval"],[osmo_ac_iu="no"])
|
||||
if test "x$osmo_ac_iu" = "xyes" ; then
|
||||
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.6.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBASN1C, libasn1c >= 0.9.30)
|
||||
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 1.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 1.5.0)
|
||||
AC_DEFINE(BUILD_IU, 1, [Define if we want to build IuPS and IuCS interfaces support])
|
||||
fi
|
||||
AM_CONDITIONAL(BUILD_IU, test "x$osmo_ac_iu" = "xyes")
|
||||
|
@ -237,11 +230,12 @@ AC_MSG_RESULT([CFLAGS="$CFLAGS"])
|
|||
AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
|
||||
|
||||
dnl Generate the output
|
||||
AM_CONFIG_HEADER(bscconfig.h)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_OUTPUT(
|
||||
include/Makefile
|
||||
include/osmocom/Makefile
|
||||
include/osmocom/gtphub/Makefile
|
||||
include/osmocom/sgsn/Makefile
|
||||
src/Makefile
|
||||
src/gprs/Makefile
|
||||
|
@ -261,5 +255,4 @@ AC_OUTPUT(
|
|||
doc/manuals/Makefile
|
||||
contrib/Makefile
|
||||
contrib/systemd/Makefile
|
||||
contrib/osmo-sgsn.spec
|
||||
Makefile)
|
||||
|
|
|
@ -37,14 +37,11 @@ osmo-build-dep.sh libosmo-netif
|
|||
osmo-build-dep.sh osmo-ggsn
|
||||
osmo-build-dep.sh osmo-hlr
|
||||
|
||||
enable_werror=""
|
||||
if [ "x$IU" = "x--enable-iu" ]; then
|
||||
osmo-build-dep.sh libosmo-sccp
|
||||
osmo-build-dep.sh libasn1c
|
||||
#osmo-build-dep.sh asn1c aper-prefix # only needed for make regen in osmo-iuh
|
||||
osmo-build-dep.sh osmo-iuh
|
||||
else
|
||||
enable_werror="--enable-werror"
|
||||
fi
|
||||
|
||||
# Additional configure options and depends
|
||||
|
@ -63,12 +60,12 @@ set -x
|
|||
|
||||
cd "$base"
|
||||
autoreconf --install --force
|
||||
./configure --enable-sanitize $enable_werror $IU --enable-external-tests $CONFIG
|
||||
./configure --enable-sanitize --enable-werror $IU --enable-external-tests $CONFIG
|
||||
$MAKE $PARALLEL_MAKE
|
||||
LD_LIBRARY_PATH="$inst/lib" $MAKE check \
|
||||
|| cat-testlogs.sh
|
||||
LD_LIBRARY_PATH="$inst/lib" \
|
||||
DISTCHECK_CONFIGURE_FLAGS="$enable_werror $IU --enable-external-tests $CONFIG" \
|
||||
DISTCHECK_CONFIGURE_FLAGS="--enable-werror $IU --enable-external-tests $CONFIG" \
|
||||
$MAKE $PARALLEL_MAKE distcheck \
|
||||
|| cat-testlogs.sh
|
||||
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
#
|
||||
# spec file for package osmo-sgsn
|
||||
#
|
||||
# Copyright (c) 2017, Martin Hauke <mardnh@gmx.de>
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
# upon. The license for this file, and modifications and additions to the
|
||||
# file, is the same license as for the pristine package itself (unless the
|
||||
# license for the pristine package is not an Open Source License, in which
|
||||
# case the license is the MIT License). An "Open Source License" is a
|
||||
# license that conforms to the Open Source Definition (Version 1.9)
|
||||
# published by the Open Source Initiative.
|
||||
|
||||
## Disable LTO for now since it breaks compilation of the tests
|
||||
## https://osmocom.org/issues/4116
|
||||
%define _lto_cflags %{nil}
|
||||
|
||||
%define with_iu 1
|
||||
Name: osmo-sgsn
|
||||
Version: @VERSION@
|
||||
Release: 0
|
||||
Summary: Osmocom's SGSN for 2G and 3G packet-switched mobile networks
|
||||
License: AGPL-3.0-or-later AND GPL-2.0-or-later
|
||||
Group: Productivity/Telephony/Servers
|
||||
URL: https://osmocom.org/projects/osmosgsn
|
||||
Source: %{name}-%{version}.tar.xz
|
||||
BuildRequires: autoconf
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: pkgconfig
|
||||
%if 0%{?suse_version}
|
||||
BuildRequires: systemd-rpm-macros
|
||||
%endif
|
||||
BuildRequires: pkgconfig(libcares)
|
||||
BuildRequires: pkgconfig(libcrypto) >= 0.9.5
|
||||
BuildRequires: pkgconfig(libgtp) >= 1.9.0
|
||||
BuildRequires: pkgconfig(libosmo-gsup-client) >= 1.5.0
|
||||
BuildRequires: pkgconfig(libosmo-netif) >= 1.2.0
|
||||
BuildRequires: pkgconfig(libosmoabis) >= 1.3.0
|
||||
BuildRequires: pkgconfig(libosmocore) >= 1.7.0
|
||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.7.0
|
||||
BuildRequires: pkgconfig(libosmogb) >= 1.7.0
|
||||
BuildRequires: pkgconfig(libosmogsm) >= 1.7.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.7.0
|
||||
%{?systemd_requires}
|
||||
%if %{with_iu}
|
||||
BuildRequires: pkgconfig(libasn1c)
|
||||
BuildRequires: pkgconfig(libosmo-ranap) >= 1.3.0
|
||||
BuildRequires: pkgconfig(libosmo-sigtran) >= 1.6.0
|
||||
%endif
|
||||
|
||||
%description
|
||||
OsmoSGSN is Osmocom's Serving GPRS Support Node for 2G and 3G
|
||||
packet-switched mobile networks.
|
||||
|
||||
%package -n osmo-gtphub
|
||||
Summary: Osmocom GTP Hub: Proxy for GTP traffic between multiple SGSNs and GGSNs
|
||||
Group: Productivity/Telephony/Servers
|
||||
|
||||
%description -n osmo-gtphub
|
||||
Osmocom GTP Hub: Proxy for GTP traffic between multiple SGSNs and GGSNs.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
echo "%{version}" >.tarball-version
|
||||
autoreconf -fi
|
||||
%configure \
|
||||
%if %{with_iu}
|
||||
--enable-iu \
|
||||
%endif
|
||||
--docdir=%{_docdir}/%{name} \
|
||||
--with-systemdsystemunitdir=%{_unitdir}
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
%make_install
|
||||
|
||||
%if 0%{?suse_version}
|
||||
%preun %service_del_preun %{name}.service
|
||||
%postun %service_del_postun %{name}.service
|
||||
%pre %service_add_pre %{name}.service
|
||||
%post %service_add_post %{name}.service
|
||||
%preun -n osmo-gtphub %service_del_preun osmo-gtphub.service
|
||||
%postun -n osmo-gtphub %service_del_postun osmo-gtphub.service
|
||||
%pre -n osmo-gtphub %service_add_pre osmo-gtphub.service
|
||||
%post -n osmo-gtphub %service_add_post osmo-gtphub.service
|
||||
%endif
|
||||
|
||||
%check
|
||||
make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
|
||||
|
||||
%files
|
||||
%doc AUTHORS README.md
|
||||
%dir %{_docdir}/%{name}/examples
|
||||
%dir %{_docdir}/%{name}/examples/osmo-sgsn
|
||||
%exclude %{_docdir}/%{name}/examples/osmo-gtphub
|
||||
%{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn-accept-all.cfg
|
||||
%{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn.cfg
|
||||
%{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn_custom-sccp.cfg
|
||||
%{_bindir}/osmo-sgsn
|
||||
%dir %{_sysconfdir}/osmocom
|
||||
%config(noreplace) %{_sysconfdir}/osmocom/osmo-sgsn.cfg
|
||||
%{_unitdir}/%{name}.service
|
||||
|
||||
%files -n osmo-gtphub
|
||||
%dir %{_docdir}/%{name}/examples
|
||||
%dir %{_docdir}/%{name}/examples/osmo-gtphub
|
||||
%{_docdir}/%{name}/examples/osmo-gtphub/osmo-gtphub-1iface.cfg
|
||||
%{_docdir}/%{name}/examples/osmo-gtphub/osmo-gtphub.cfg
|
||||
%{_bindir}/osmo-gtphub
|
||||
%dir %{_sysconfdir}/osmocom
|
||||
%config(noreplace) %{_sysconfdir}/osmocom/osmo-gtphub.cfg
|
||||
%{_unitdir}/osmo-gtphub.service
|
||||
|
||||
%changelog
|
|
@ -1,9 +1,15 @@
|
|||
[Unit]
|
||||
Description=Osmocom GTP Hub
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=osmocom
|
||||
Group=osmocom
|
||||
ExecStart=/usr/bin/osmo-gtphub -c /etc/osmocom/osmo-gtphub.cfg
|
||||
StateDirectory=osmocom
|
||||
WorkingDirectory=%S/osmocom
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
RestartPreventExitStatus=1
|
||||
|
|
|
@ -3,10 +3,16 @@ Description=Osmocom SGSN (Serving GPRS Support Node)
|
|||
Wants=osmo-hlr.service
|
||||
After=osmo-hlr.service
|
||||
After=osmo-hnbgw.service
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
StateDirectory=osmocom
|
||||
WorkingDirectory=%S/osmocom
|
||||
Restart=always
|
||||
User=osmocom
|
||||
Group=osmocom
|
||||
ExecStart=/usr/bin/osmo-sgsn -c /etc/osmocom/osmo-sgsn.cfg
|
||||
RestartSec=2
|
||||
|
||||
|
|
|
@ -1,3 +1,114 @@
|
|||
osmo-sgsn (1.11.1) unstable; urgency=medium
|
||||
|
||||
[ Philipp Maier ]
|
||||
* sgsn_rim: forward message based on RIM ROUTING ADDRESS
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* sgsn_vty: Fix output in config_write_sgsn
|
||||
* sgsn_vty: Correctly indent encryption cipher-plugin-path
|
||||
* vty-tests: Test encryption options
|
||||
* libgtp: Check for all successful create_pdp_conf causes
|
||||
|
||||
-- Oliver Smith <osmith@sysmocom.de> Tue, 28 Nov 2023 13:32:46 +0100
|
||||
|
||||
osmo-sgsn (1.11.0) unstable; urgency=medium
|
||||
|
||||
[ Oliver Smith ]
|
||||
* Run struct_endianness.py
|
||||
* debian: set compat level to 10
|
||||
* systemd: depend on networking-online.target
|
||||
|
||||
[ arehbein ]
|
||||
* Transition to use of 'telnet_init_default'
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* tests: use -no-install libtool flag to avoid ./lt-* scripts
|
||||
* tests: $(BUILT_SOURCES) is not defined, depend on osmo-sgsn
|
||||
* copyright: fix typo: sysmocom s/s.m.f.c./s.f.m.c./ GmbH
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* gmm: Ciphering Key Sequence Number IE has half octet tag
|
||||
* gprs_sm.c: Fix load of misaligned ptr address
|
||||
* Write explicit role & sctp-role fields in ASP configurations
|
||||
* gmm: Update DRX params during rx RAU REQ
|
||||
* gmm: Add missing GSM48_IE_GMM_RX_NPDU_NUM_LIST IE in gsm48_gmm_att_tlvdef
|
||||
|
||||
[ Philipp Maier ]
|
||||
* sgsn_rim: fix typo
|
||||
* sgsn_rim: cosmetic: improve comment
|
||||
* sgsn_rim: get rid of MME check in sgsn_rim_rx_from_gtp:
|
||||
* sgsn_rim: do not check the origin of a RIM message
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 12 Sep 2023 16:57:02 +0200
|
||||
|
||||
osmo-sgsn (1.10.0) unstable; urgency=medium
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* configure.ac: do not require unused dlsym/dlopen
|
||||
* gprs_llc: fix misleading spacing in gprs_llc_rcvmsg()
|
||||
* gprs_llc.h: use '#pragma once'
|
||||
* llc: gprs_llc_fcs(): make the input data pointer const
|
||||
|
||||
[ Max ]
|
||||
* Set working directory in systemd service file
|
||||
* SNDCP: log more details on failure
|
||||
* GTP: migrate from deprecated function
|
||||
* Constify LLC/SNDCP parameters
|
||||
* GMM: permit E_GMM_COMMON_PROC_SUCCESS in normal state
|
||||
* ctrl: take both address and port from vty config
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* vty: Make new libgtp tdefs configurable through VTY
|
||||
* sndcp: Put decompress handling code into helper function
|
||||
* Move gprs_gb_parse.[c,h] to tests/sgsn/
|
||||
* Create new specific file for BSSGP code
|
||||
* Move some functions gprs_gb.[c,h] -> gprs_gmm.[c,h]
|
||||
* Rename gprs_gb.[c,h] -> gprs_ns.[c,h]
|
||||
* Move gprs_tmr_to_secs() to tests/gprs/gprs_test.c
|
||||
* cosmetic: gprs_llc_vty.c: Fix trailing whitespace
|
||||
* vty: Fix wrong value_string used to print llme state
|
||||
* Standarize lle and llme state enum & value_string
|
||||
* Remove unused function gprs_parse_mi_tmsi()
|
||||
* Replace gprs_str_to_apn() with libosmocore API osmo_apn_from_str()
|
||||
* Move struct sgsn_ggsn_ctx to its own file gtp_ggsn.{c,h}
|
||||
* gprs_subscriber: Move API declarations to correct header
|
||||
* Move gprs_sndcp_vty_init() declaration to gprs_sndcp.h
|
||||
* Introduce new header file sgsn/gtp.h
|
||||
* Fix -Werror=old-style-definition
|
||||
* Move related structs to gprs_subscriber.h
|
||||
* Remove unneeded extern declaration from libosmocotrl
|
||||
* Keep sgsn subsystems under struct sgsn_instance lifecycle
|
||||
* Move global ggsn_list into struct sgsn_instance
|
||||
* Move struct apn_ctx and APN related definitions to its own file
|
||||
* Move struct sgsn_subscriber_pdp_data to gprs_subscriber.h
|
||||
* sgsn.h: Drop declaration of non existing function
|
||||
* Properly split llc->sndcp->gtp unitdata pathi through extra func call
|
||||
* Move func defintions of funcs implemented in gprs_sndcp.c to gprs_sndcp.h
|
||||
* sndcp: Standarize unitdata function naming
|
||||
* Move gtp related functions to gtp.h
|
||||
* Move global apn_list inside struct sgsn_instance
|
||||
* gtp_{ggsn,mme}: Allocate contexts under struct sgsn_instance
|
||||
* Move extern declarations of tall_sgsn_ctx to sgsn.h
|
||||
* Drop extern declarations of global sgsn_instance in source files
|
||||
* Move sgsn_pdp_ctx to its own file pdpctx.{c,h}
|
||||
* Move global pdp_list inside struct sgsn_instance
|
||||
* Move gtphub header to include/osmocom/gtphub/
|
||||
* Move sgsn_ctrl_cmds_install() declaration to sgsn.h
|
||||
* Move LOGGSUBSCRP to gprs_subscriber.h
|
||||
* Rename bscconfig.h -> config.h
|
||||
* gtphub.h: Remove dependency on sgsn/gprs_sgsn.h
|
||||
* Split gprs_sgsn.{c,h} -> {auth,mmctx,sgsn}.{c,h}
|
||||
* Move global mmctx list into struct sgsn_instance
|
||||
* vty: Introduce encryption cipher-plugin-path command
|
||||
* Fix extra whitespace in pdpctx_ctr_description
|
||||
|
||||
[ Oliver Smith ]
|
||||
* contrib/jenkins.sh: use enable-werror with IU too
|
||||
* sgsn_libgtp: cb_data_ind: remove mm_idle assert
|
||||
* osmo-gtphub.cfg: fix conflict with osmo-ggsn.cfg
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 07 Feb 2023 17:34:26 +0100
|
||||
|
||||
osmo-sgsn (1.9.0) unstable; urgency=medium
|
||||
|
||||
[ Oliver Smith ]
|
||||
|
|
|
@ -1 +1 @@
|
|||
9
|
||||
10
|
||||
|
|
|
@ -2,7 +2,7 @@ Source: osmo-sgsn
|
|||
Section: net
|
||||
Priority: extra
|
||||
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
|
||||
Build-Depends: debhelper (>=9),
|
||||
Build-Depends: debhelper (>= 10),
|
||||
dh-autoreconf,
|
||||
autotools-dev,
|
||||
autoconf,
|
||||
|
@ -11,16 +11,16 @@ Build-Depends: debhelper (>=9),
|
|||
pkg-config,
|
||||
libtalloc-dev,
|
||||
libc-ares-dev,
|
||||
libgtp-dev (>= 1.9.0),
|
||||
libosmocore-dev (>= 1.7.0),
|
||||
libosmo-abis-dev (>= 1.3.0),
|
||||
libosmo-netif-dev (>= 1.2.0),
|
||||
libosmo-gsup-client-dev (>= 1.5.0),
|
||||
libgtp-dev (>= 1.11.0),
|
||||
libosmocore-dev (>= 1.9.0),
|
||||
libosmo-abis-dev (>= 1.5.0),
|
||||
libosmo-netif-dev (>= 1.4.0),
|
||||
libosmo-gsup-client-dev (>= 1.7.0),
|
||||
libasn1c-dev (>= 0.9.30),
|
||||
libosmo-ranap-dev (>= 1.3.0),
|
||||
libosmo-sigtran-dev (>= 1.6.0),
|
||||
libosmo-sccp-dev (>= 1.6.0),
|
||||
osmo-gsm-manuals-dev (>= 1.3.0)
|
||||
libosmo-ranap-dev (>= 1.5.0),
|
||||
libosmo-sigtran-dev (>= 1.8.0),
|
||||
libosmo-sccp-dev (>= 1.8.0),
|
||||
osmo-gsm-manuals-dev (>= 1.5.0)
|
||||
Standards-Version: 3.9.8
|
||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
|
||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
|
||||
|
|
|
@ -33,7 +33,6 @@ Files: .gitignore
|
|||
include/osmocom/sgsn/crc24.h
|
||||
include/osmocom/sgsn/debug.h
|
||||
include/osmocom/sgsn/gb_proxy.h
|
||||
include/osmocom/sgsn/gprs_gb_parse.h
|
||||
include/osmocom/sgsn/gprs_gmm.h
|
||||
include/osmocom/sgsn/gprs_llc.h
|
||||
include/osmocom/sgsn/gprs_sgsn.h
|
||||
|
@ -53,6 +52,7 @@ Files: .gitignore
|
|||
tests/gprs/gprs_test.ok
|
||||
tests/gtphub/Makefile.am
|
||||
tests/gtphub/gtphub_test.ok
|
||||
tests/sgsn/gprs_gb_parse.h
|
||||
tests/sgsn/Makefile.am
|
||||
tests/sgsn/sgsn_test.ok
|
||||
tests/slhc/Makefile.am
|
||||
|
@ -74,11 +74,10 @@ Files: include/osmocom/sgsn/a_reset.h
|
|||
include/osmocom/sgsn/gprs_sndcp_pcomp.h
|
||||
include/osmocom/sgsn/gprs_sndcp_xid.h
|
||||
include/osmocom/sgsn/gprs_utils.h
|
||||
include/osmocom/sgsn/gtphub.h
|
||||
include/osmocom/gtphub/gtphub.h
|
||||
include/osmocom/sgsn/signal.h
|
||||
src/gprs/gprs_llc_parse.c
|
||||
src/gprs/crc24.c
|
||||
src/gprs/gprs_gb_parse.c
|
||||
src/gprs/gprs_utils.c
|
||||
src/gprs/sgsn_ares.c
|
||||
src/gtphub/gtphub.c
|
||||
|
@ -103,6 +102,7 @@ Files: include/osmocom/sgsn/a_reset.h
|
|||
src/sgsn/sgsn_main.c
|
||||
src/sgsn/sgsn_vty.c
|
||||
tests/gtphub/gtphub_test.c
|
||||
tests/sgsn/gprs_gb_parse.c
|
||||
tests/sgsn/sgsn_test.c
|
||||
tests/slhc/slhc_test.c
|
||||
tests/sndcp_xid/sndcp_xid_test.c
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/sh -e
|
||||
case "$1" in
|
||||
configure)
|
||||
# Create the osmocom group and user (if it doesn't exist yet)
|
||||
if ! getent group osmocom >/dev/null; then
|
||||
groupadd --system osmocom
|
||||
fi
|
||||
if ! getent passwd osmocom >/dev/null; then
|
||||
useradd \
|
||||
--system \
|
||||
--gid osmocom \
|
||||
--home-dir /var/lib/osmocom \
|
||||
--shell /sbin/nologin \
|
||||
--comment "Open Source Mobile Communications" \
|
||||
osmocom
|
||||
fi
|
||||
|
||||
# Fix permissions of previous (root-owned) install (OS#4107)
|
||||
chown osmocom:osmocom /etc/osmocom/osmo-sgsn.cfg
|
||||
chmod 0660 /etc/osmocom/osmo-sgsn.cfg
|
||||
chown root:osmocom /etc/osmocom
|
||||
chmod 2775 /etc/osmocom
|
||||
mkdir -p /var/lib/osmocom
|
||||
chown -R osmocom:osmocom /var/lib/osmocom
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb(1) will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
#DEBHELPER#
|
|
@ -5,6 +5,14 @@
|
|||
! For the test, try to use most config commands.
|
||||
!
|
||||
|
||||
log stderr
|
||||
logging color 1
|
||||
logging print category-hex 0
|
||||
logging print category 1
|
||||
logging timestamp 0
|
||||
logging print file basename last
|
||||
logging print level 1
|
||||
|
||||
line vty
|
||||
no login
|
||||
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
! Osmocom gtphub configuration
|
||||
!
|
||||
|
||||
log stderr
|
||||
logging color 1
|
||||
logging print category-hex 0
|
||||
logging print category 1
|
||||
logging timestamp 0
|
||||
logging print file basename last
|
||||
logging print level 1
|
||||
|
||||
line vty
|
||||
no login
|
||||
|
||||
|
@ -9,7 +17,7 @@ gtphub
|
|||
! Local addresses to listen on and send from, each on standard ports
|
||||
! 2123 and 2152. Setting these addresses is mandatory.
|
||||
bind-to-sgsns 127.0.0.10
|
||||
bind-to-ggsns 127.0.0.2
|
||||
bind-to-ggsns 127.0.0.20
|
||||
|
||||
! Local nonstandard ports or separate IPs:
|
||||
!bind-to-sgsns ctrl 127.0.0.1 2342 user 127.0.0.1 4223
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
! Osmocom SGSN configuration
|
||||
!
|
||||
!
|
||||
log stderr
|
||||
logging color 1
|
||||
logging print category-hex 0
|
||||
logging print category 1
|
||||
logging timestamp 0
|
||||
logging print file basename last
|
||||
logging print level 1
|
||||
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
! Osmocom SGSN configuration
|
||||
!
|
||||
!
|
||||
log stderr
|
||||
logging color 1
|
||||
logging print category-hex 0
|
||||
logging print category 1
|
||||
logging timestamp 0
|
||||
logging print file basename last
|
||||
logging print level 1
|
||||
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
! Osmocom SGSN configuration
|
||||
!
|
||||
!
|
||||
log stderr
|
||||
logging color 1
|
||||
logging print category-hex 0
|
||||
logging print category 1
|
||||
logging timestamp 0
|
||||
logging print file basename last
|
||||
logging print level 1
|
||||
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
|
@ -9,6 +17,8 @@ cs7 instance 0
|
|||
point-code 0.23.4
|
||||
asp asp-clnt-OsmoSGSN-A 2905 0 m3ua
|
||||
remote-ip 172.18.8.200 ! where to reach the STP
|
||||
role asp
|
||||
sctp-role client
|
||||
as as-clnt-OsmoSGSN-A m3ua
|
||||
asp asp-clnt-OsmoSGSN-A
|
||||
routing-key 3 0.23.4
|
||||
|
|
|
@ -422,6 +422,7 @@ cs7 instance 0
|
|||
point-code 0.23.4
|
||||
asp asp-clnt-OsmoSGSN 2905 0 m3ua
|
||||
remote-ip 127.0.0.1
|
||||
role asp
|
||||
sctp-role client
|
||||
as as-clnt-OsmoSGSN m3ua
|
||||
asp asp-clnt-OsmoSGSN
|
||||
|
|
|
@ -15,6 +15,14 @@
|
|||
Conversion to asciidoc, removal of sysmoBTS specific parts.
|
||||
</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>3</revnumber>
|
||||
<date>April 2024</date>
|
||||
<authorinitials>AC</authorinitials>
|
||||
<revremark>
|
||||
Replace NS chapter with new NS2 chapter to match the code.
|
||||
</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
<authorgroup>
|
||||
|
@ -29,10 +37,21 @@
|
|||
<jobtitle>Managing Director</jobtitle>
|
||||
</affiliation>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Alexander</firstname>
|
||||
<surname>Couzens</surname>
|
||||
<email>acouzens@sysmocom.de</email>
|
||||
<authorinitials>AC</authorinitials>
|
||||
<affiliation>
|
||||
<shortaffil>sysmocom</shortaffil>
|
||||
<orgname>sysmocom - s.f.m.c. GmbH</orgname>
|
||||
<jobtitle>Developer</jobtitle>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2013-2016</year>
|
||||
<year>2013-2024</year>
|
||||
<holder>sysmocom - s.f.m.c. GmbH</holder>
|
||||
</copyright>
|
||||
|
||||
|
@ -47,8 +66,8 @@
|
|||
</para>
|
||||
<para>
|
||||
The Asciidoc source code of this manual can be found at
|
||||
<ulink url="http://git.osmocom.org/osmo-gsm-manuals/">
|
||||
http://git.osmocom.org/osmo-gsm-manuals/
|
||||
<ulink url="https://git.osmocom.org/osmo-gsm-manuals/">
|
||||
https://git.osmocom.org/osmo-gsm-manuals/
|
||||
</ulink>
|
||||
</para>
|
||||
</legalnotice>
|
||||
|
|
|
@ -21,7 +21,7 @@ include::{srcdir}/chapters/configuration.adoc[]
|
|||
|
||||
include::./common/chapters/cs7-config.adoc[]
|
||||
|
||||
include::./common/chapters/gb.adoc[]
|
||||
include::./common/chapters/gb-ns2.adoc[]
|
||||
|
||||
include::./common/chapters/control_if.adoc[]
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
SUBDIRS = \
|
||||
gtphub \
|
||||
sgsn \
|
||||
$(NULL)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
noinst_HEADERS = \
|
||||
gtphub.h \
|
||||
$(NULL)
|
|
@ -27,9 +27,7 @@
|
|||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
|
||||
#include <osmocom/gsm/apn.h>
|
||||
|
||||
/* support */
|
||||
|
||||
|
@ -428,7 +426,7 @@ struct gtphub_resolved_ggsn {
|
|||
|
||||
/* The APN OI, the Operator Identifier, is the combined address,
|
||||
* including parts of the IMSI and APN NI, and ending with ".gprs". */
|
||||
char apn_oi_str[GSM_APN_LENGTH];
|
||||
char apn_oi_str[APN_MAXLEN+1];
|
||||
|
||||
/* Which address and port we resolved that to. */
|
||||
struct gtphub_peer_port *peer;
|
|
@ -1,18 +1,19 @@
|
|||
noinst_HEADERS = \
|
||||
apn.h \
|
||||
auth.h \
|
||||
common.h \
|
||||
crc24.h \
|
||||
debug.h \
|
||||
gprs_gb.h \
|
||||
gprs_gb_parse.h \
|
||||
gprs_bssgp.h \
|
||||
gprs_gmm.h \
|
||||
gprs_gmm_fsm.h \
|
||||
gprs_gmm_attach.h \
|
||||
gprs_mm_state_gb_fsm.h \
|
||||
gprs_mm_state_iu_fsm.h \
|
||||
gprs_ns.h \
|
||||
gprs_llc.h \
|
||||
gprs_llc_xid.h \
|
||||
gprs_ranap.h \
|
||||
gprs_sgsn.h \
|
||||
gprs_sm.h \
|
||||
gprs_sndcp_comp.h \
|
||||
gprs_sndcp_dcomp.h \
|
||||
|
@ -21,8 +22,11 @@ noinst_HEADERS = \
|
|||
gprs_sndcp_xid.h \
|
||||
gprs_subscriber.h \
|
||||
gprs_utils.h \
|
||||
gtphub.h \
|
||||
gtp.h \
|
||||
gtp_ggsn.h \
|
||||
gtp_mme.h \
|
||||
mmctx.h \
|
||||
pdpctx.h \
|
||||
sgsn.h \
|
||||
sgsn_rim.h \
|
||||
signal.h \
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
struct sgsn_ggsn_ctx;
|
||||
|
||||
#define GSM_APN_LENGTH 102
|
||||
|
||||
struct apn_ctx {
|
||||
struct llist_head list;
|
||||
struct sgsn_ggsn_ctx *ggsn;
|
||||
char *name;
|
||||
char *imsi_prefix;
|
||||
char *description;
|
||||
};
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix);
|
||||
void sgsn_apn_ctx_free(struct apn_ctx *actx);
|
||||
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix);
|
||||
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi_prefix);
|
|
@ -0,0 +1,39 @@
|
|||
/* MS authorization and subscriber data handling */
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
struct sgsn_config;
|
||||
struct sgsn_instance;
|
||||
struct sgsn_mm_ctx;
|
||||
struct gsm_auth_tuple;
|
||||
|
||||
/* Authorization/ACL handling */
|
||||
enum sgsn_auth_state {
|
||||
SGSN_AUTH_UNKNOWN,
|
||||
SGSN_AUTH_AUTHENTICATE,
|
||||
SGSN_AUTH_UMTS_RESYNC,
|
||||
SGSN_AUTH_ACCEPTED,
|
||||
SGSN_AUTH_REJECTED
|
||||
};
|
||||
|
||||
extern const struct value_string *sgsn_auth_state_names;
|
||||
|
||||
void sgsn_auth_init(struct sgsn_instance *sgsn);
|
||||
/* Request authorization */
|
||||
enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm);
|
||||
int sgsn_auth_request(struct sgsn_mm_ctx *mm);
|
||||
void sgsn_auth_update(struct sgsn_mm_ctx *mm);
|
||||
struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
|
||||
unsigned key_seq);
|
||||
|
||||
/*
|
||||
* Authorization/ACL handling
|
||||
*/
|
||||
struct imsi_acl_entry {
|
||||
struct llist_head list;
|
||||
char imsi[OSMO_IMSI_BUF_SIZE];
|
||||
};
|
||||
struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, const struct sgsn_config *cfg);
|
||||
int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg);
|
||||
int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg);
|
|
@ -5,6 +5,6 @@
|
|||
|
||||
#define INIT_CRC24 0xffffff
|
||||
|
||||
uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len);
|
||||
uint32_t crc24_calc(uint32_t fcs, const uint8_t *cp, unsigned int len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
/* Called by bssgp layer when a prim is received from lower layers. */
|
||||
int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph);
|
||||
|
||||
/* called by the bssgp layer to send NS PDUs */
|
||||
int sgsn_bssgp_dispatch_ns_unitdata_req_cb(void *ctx, struct msgb *msg);
|
||||
|
||||
/* page a MS in its routing area */
|
||||
int sgsn_bssgp_page_ps_ra(struct sgsn_mm_ctx *mmctx);
|
|
@ -1,20 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
|
||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
|
||||
bool drop_cipherable);
|
||||
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
|
||||
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg);
|
||||
|
||||
/* page a MS in its routing area */
|
||||
int gprs_gb_page_ps_ra(struct sgsn_mm_ctx *mmctx);
|
||||
|
||||
/* called by the bssgp layer to send NS PDUs */
|
||||
int gprs_gb_send_cb(void *ctx, struct msgb *msg);
|
||||
|
||||
/* called by the ns layer */
|
||||
int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
|
|
@ -1,11 +1,15 @@
|
|||
#ifndef _GPRS_GMM_H
|
||||
#define _GPRS_GMM_H
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/crypt/auth.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
struct gprs_llc_llme;
|
||||
|
||||
int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm,
|
||||
const struct osmo_auth_vector *vec,
|
||||
uint8_t key_seq, bool force_standby);
|
||||
|
@ -28,6 +32,11 @@ int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli);
|
|||
int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
|
||||
uint8_t suspend_ref);
|
||||
|
||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
|
||||
bool drop_cipherable);
|
||||
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
|
||||
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg);
|
||||
|
||||
time_t gprs_max_time_to_idle(void);
|
||||
|
||||
int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
|
||||
struct gprs_llc_llme;
|
||||
|
||||
/* 3GPP TS 24.008 § 4.1.3.3 GMM mobility management states on the network side */
|
||||
enum gmm_fsm_states {
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
#ifndef _GPRS_LLC_H
|
||||
#define _GPRS_LLC_H
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
#include <osmocom/crypt/gprs_cipher.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_llc_xid.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
|
||||
/* Section 4.7 LLC Layer Structure */
|
||||
enum gprs_llc_sapi {
|
||||
GPRS_SAPI_GMM = 1,
|
||||
|
@ -91,6 +96,7 @@ enum gprs_llc_lle_state {
|
|||
GPRS_LLES_LOCAL_REL = 6, /* Local Release */
|
||||
GPRS_LLES_TIMER_REC = 7, /* Timer Recovery */
|
||||
};
|
||||
extern const struct value_string gprs_llc_lle_state_names[];
|
||||
|
||||
enum gprs_llc_llme_state {
|
||||
GPRS_LLMS_UNASSIGNED = 1, /* No TLLI yet */
|
||||
|
@ -272,18 +278,15 @@ static inline int gprs_llc_is_retransmit(uint16_t nu, uint16_t vur)
|
|||
}
|
||||
|
||||
/* LLC low level functions */
|
||||
void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
|
||||
void gprs_llme_copy_key(const struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
|
||||
|
||||
/* parse a GPRS LLC header, also check for invalid frames */
|
||||
int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp,
|
||||
uint8_t *llc_hdr, int len);
|
||||
void gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph, struct gprs_llc_lle *lle);
|
||||
int gprs_llc_fcs(uint8_t *data, unsigned int len);
|
||||
int gprs_llc_fcs(const uint8_t *data, unsigned int len);
|
||||
|
||||
|
||||
/* LLME handling routines */
|
||||
struct llist_head *gprs_llme_list(void);
|
||||
struct gprs_llc_lle *gprs_lle_get_or_create(const uint32_t tlli, uint8_t sapi);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
|
||||
/* called by the ns layer */
|
||||
int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
|
|
@ -1,13 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
|
||||
#ifdef BUILD_IU
|
||||
#include <osmocom/ranap/ranap_ies_defs.h>
|
||||
#include <osmocom/ranap/ranap_msg_factory.h>
|
||||
#include <osmocom/ranap/iu_client.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
struct sgsn_pdp_ctx;
|
||||
|
||||
void activate_pdp_rabs(struct sgsn_mm_ctx *ctx);
|
||||
int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data);
|
||||
int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp);
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
struct sgsn_pdp_ctx;
|
||||
struct gprs_llc_llme;
|
||||
|
||||
int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause, bool teardown);
|
||||
int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
|
||||
struct gprs_llc_lle;
|
||||
|
||||
/* A fragment queue header, maintaining list of fragments for one N-PDU */
|
||||
struct defrag_state {
|
||||
|
@ -60,6 +63,8 @@ struct gprs_sndcp_entity {
|
|||
|
||||
extern struct llist_head gprs_sndcp_entities;
|
||||
|
||||
int gprs_sndcp_vty_init(void);
|
||||
|
||||
/* Set of SNDCP-XID negotiation (See also: TS 144 065,
|
||||
* Section 6.8 XID parameter negotiation) */
|
||||
int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi);
|
||||
|
@ -68,7 +73,7 @@ int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi);
|
|||
* Section 6.8 XID parameter negotiation) */
|
||||
int sndcp_sn_xid_ind(struct gprs_llc_xid_field *xid_field_indication,
|
||||
struct gprs_llc_xid_field *xid_field_response,
|
||||
struct gprs_llc_lle *lle);
|
||||
const struct gprs_llc_lle *lle);
|
||||
|
||||
/* Process SNDCP-XID indication
|
||||
* (See also: TS 144 065, Section 6.8 XID parameter negotiation) */
|
||||
|
@ -77,6 +82,20 @@ int sndcp_sn_xid_conf(struct gprs_llc_xid_field *xid_field_conf,
|
|||
struct gprs_llc_lle *lle);
|
||||
|
||||
/* Clean up all gprs_sndcp_entities related to llme (OS#4824) */
|
||||
void gprs_sndcp_sm_deactivate_ind_by_llme(struct gprs_llc_llme *llme);
|
||||
void gprs_sndcp_sm_deactivate_ind_by_llme(const struct gprs_llc_llme *llme);
|
||||
|
||||
/* Called by SNDCP when it has received/re-assembled a N-PDU */
|
||||
int sndcp_sn_unitdata_ind(struct gprs_sndcp_entity *sne, struct msgb *msg,
|
||||
uint32_t npdu_len, uint8_t *npdu);
|
||||
int sndcp_sn_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
|
||||
void *mmcontext);
|
||||
|
||||
/* Entry point for the SNSM-ACTIVATE.indication */
|
||||
int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
|
||||
/* Entry point for the SNSM-DEACTIVATE.indication */
|
||||
int sndcp_sm_deactivate_ind(const struct gprs_llc_lle *lle, uint8_t nsapi);
|
||||
|
||||
int sndcp_ll_unitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
|
||||
uint8_t *hdr, uint16_t len);
|
||||
|
||||
#endif /* INT_SNDCP_H */
|
||||
|
|
|
@ -4,10 +4,70 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
|
||||
#include <osmocom/sgsn/apn.h>
|
||||
|
||||
struct sgsn_instance;
|
||||
struct sgsn_mm_ctx;
|
||||
|
||||
extern struct llist_head * const gprs_subscribers;
|
||||
|
||||
#define GPRS_SUBSCRIBER_FIRST_CONTACT 0x00000001
|
||||
#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
|
||||
#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
|
||||
#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
|
||||
#define GPRS_SUBSCRIBER_ENABLE_PURGE (1 << 19)
|
||||
|
||||
#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
|
||||
GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
|
||||
GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
|
||||
)
|
||||
|
||||
struct gsm_auth_tuple {
|
||||
int use_count;
|
||||
int key_seq;
|
||||
struct osmo_auth_vector vec;
|
||||
};
|
||||
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
|
||||
|
||||
struct sgsn_subscriber_data {
|
||||
struct sgsn_mm_ctx *mm;
|
||||
struct gsm_auth_tuple auth_triplets[5];
|
||||
int auth_triplets_updated;
|
||||
struct llist_head pdp_list;
|
||||
int error_cause;
|
||||
|
||||
uint8_t msisdn[9];
|
||||
size_t msisdn_len;
|
||||
|
||||
uint8_t hlr[9];
|
||||
size_t hlr_len;
|
||||
|
||||
uint8_t pdp_charg[2];
|
||||
bool has_pdp_charg;
|
||||
};
|
||||
|
||||
/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
|
||||
/* see GSM 09.02, B.1, gprsSubscriptionData */
|
||||
struct sgsn_subscriber_pdp_data {
|
||||
struct llist_head list;
|
||||
|
||||
unsigned int context_id;
|
||||
enum gsm48_pdp_type_org pdp_type_org;
|
||||
enum gsm48_pdp_type_nr pdp_type_nr;
|
||||
struct osmo_sockaddr pdp_address[2];
|
||||
char apn_str[GSM_APN_LENGTH];
|
||||
uint8_t qos_subscribed[20];
|
||||
size_t qos_subscribed_len;
|
||||
uint8_t pdp_charg[2];
|
||||
bool has_pdp_charg;
|
||||
};
|
||||
|
||||
struct sgsn_subscriber_pdp_data *sgsn_subscriber_pdp_data_alloc(struct sgsn_subscriber_data *sdata);
|
||||
|
||||
struct gprs_subscr {
|
||||
struct llist_head entry;
|
||||
int use_count;
|
||||
|
@ -29,3 +89,22 @@ struct gprs_subscr *_gprs_subscr_put(struct gprs_subscr *gsub,
|
|||
const char *file, int line);
|
||||
#define gprs_subscr_get(gsub) _gprs_subscr_get(gsub, __FILE__, __LINE__)
|
||||
#define gprs_subscr_put(gsub) _gprs_subscr_put(gsub, __FILE__, __LINE__)
|
||||
|
||||
int gprs_subscr_init(struct sgsn_instance *sgi);
|
||||
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
|
||||
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
|
||||
const uint8_t *auts,
|
||||
const uint8_t *auts_rand);
|
||||
void gprs_subscr_cleanup(struct gprs_subscr *subscr);
|
||||
struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi);
|
||||
struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx);
|
||||
struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi);
|
||||
void gprs_subscr_cancel(struct gprs_subscr *subscr);
|
||||
void gprs_subscr_update(struct gprs_subscr *subscr);
|
||||
void gprs_subscr_update_auth_info(struct gprs_subscr *subscr);
|
||||
int gprs_subscr_rx_gsup_message(struct msgb *msg);
|
||||
|
||||
#define LOGGSUBSCRP(level, subscr, fmt, args...) \
|
||||
LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
|
||||
(subscr) ? (subscr)->imsi : "---", \
|
||||
## args)
|
||||
|
|
|
@ -29,15 +29,11 @@
|
|||
struct msgb;
|
||||
struct gprs_ra_id;
|
||||
|
||||
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str);
|
||||
|
||||
/* GSM 04.08, 10.5.7.3 GPRS Timer */
|
||||
int gprs_tmr_to_secs(uint8_t tmr);
|
||||
uint8_t gprs_secs_to_tmr_floor(int secs);
|
||||
|
||||
int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len);
|
||||
int gprs_is_mi_imsi(const uint8_t *value, size_t value_len);
|
||||
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi);
|
||||
void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi);
|
||||
|
||||
int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
#include <osmocom/gprs/gprs_bssgp_rim.h>
|
||||
|
||||
struct gprs_ra_id;
|
||||
struct sgsn_instance;
|
||||
struct sgsn_ggsn_ctx;
|
||||
struct sgsn_pdp_ctx;
|
||||
struct sgsn_mm_ctx;
|
||||
struct sgsn_mme_ctx;
|
||||
|
||||
int sgsn_gtp_init(struct sgsn_instance *sgi);
|
||||
|
||||
int sgsn_mme_ran_info_req(struct sgsn_mme_ctx *mme, const struct bssgp_ran_information_pdu *pdu);
|
||||
|
||||
void sgsn_ggsn_echo_req(struct sgsn_ggsn_ctx *ggc);
|
||||
struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
|
||||
struct sgsn_mm_ctx *mmctx,
|
||||
uint16_t nsapi,
|
||||
struct tlv_parsed *tp);
|
||||
|
||||
int sgsn_gtp_data_req(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
|
||||
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
|
||||
int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
|
||||
void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen);
|
||||
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx);
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/gprs/protocol/gsm_24_301.h>
|
||||
|
||||
struct gsn_t;
|
||||
struct sgsn_pdp_ctx;
|
||||
struct sgsn_instance;
|
||||
|
||||
struct sgsn_ggsn_ctx {
|
||||
struct llist_head list;
|
||||
uint32_t id;
|
||||
unsigned int gtp_version;
|
||||
struct in_addr remote_addr;
|
||||
int remote_restart_ctr;
|
||||
struct gsn_t *gsn;
|
||||
struct llist_head pdp_list; /* list of associated pdp ctx (struct sgsn_pdp_ctx*) */
|
||||
struct osmo_timer_list echo_timer;
|
||||
unsigned int echo_interval;
|
||||
};
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(struct sgsn_instance *sgsn, uint32_t id);
|
||||
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(struct sgsn_instance *sgsn, uint32_t id);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct sgsn_instance *sgsn, struct in_addr *addr);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(struct sgsn_instance *sgsn, uint32_t id);
|
||||
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx);
|
||||
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except);
|
||||
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn);
|
||||
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
|
||||
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
|
||||
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc);
|
||||
|
||||
#define LOGGGSN(ggc, level, fmt, args...) { \
|
||||
char _buf[INET_ADDRSTRLEN]; \
|
||||
LOGP(DGTP, level, "GGSN(%" PRIu32 ":%s): " fmt, (ggc)->id, inet_ntop(AF_INET, &(ggc)->remote_addr, _buf, sizeof(_buf)), ## args); \
|
||||
} while (0)
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _GPRS_SGSN_H
|
||||
#define _GPRS_SGSN_H
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
|
@ -14,12 +13,17 @@
|
|||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
#include <osmocom/crypt/auth.h>
|
||||
|
||||
#include <osmocom/sgsn/apn.h>
|
||||
#include <osmocom/sgsn/auth.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
|
||||
#define GSM_EXTENSION_LENGTH 15
|
||||
#define GSM_APN_LENGTH 102
|
||||
|
||||
struct gprs_llc_lle;
|
||||
struct ctrl_handle;
|
||||
struct gprs_subscr;
|
||||
struct sgsn_ggsn_ctx;
|
||||
struct sgsn_pdp_ctx;
|
||||
|
||||
enum gsm48_gsm_cause;
|
||||
|
||||
|
@ -37,13 +41,6 @@ enum gprs_mm_ctr {
|
|||
GMM_CTR_RA_UPDATE,
|
||||
};
|
||||
|
||||
enum gprs_pdp_ctx {
|
||||
PDP_CTR_PKTS_UDATA_IN,
|
||||
PDP_CTR_PKTS_UDATA_OUT,
|
||||
PDP_CTR_BYTES_UDATA_IN,
|
||||
PDP_CTR_BYTES_UDATA_OUT,
|
||||
};
|
||||
|
||||
enum gprs_t3350_mode {
|
||||
GMM_T3350_MODE_NONE,
|
||||
GMM_T3350_MODE_ATT,
|
||||
|
@ -51,17 +48,6 @@ enum gprs_t3350_mode {
|
|||
GMM_T3350_MODE_PTMSI_REALL,
|
||||
};
|
||||
|
||||
/* Authorization/ACL handling */
|
||||
enum sgsn_auth_state {
|
||||
SGSN_AUTH_UNKNOWN,
|
||||
SGSN_AUTH_AUTHENTICATE,
|
||||
SGSN_AUTH_UMTS_RESYNC,
|
||||
SGSN_AUTH_ACCEPTED,
|
||||
SGSN_AUTH_REJECTED
|
||||
};
|
||||
|
||||
#define MS_RADIO_ACCESS_CAPA
|
||||
|
||||
enum sgsn_ggsn_lookup_state {
|
||||
SGSN_GGSN_2DIGIT,
|
||||
SGSN_GGSN_3DIGIT,
|
||||
|
@ -104,13 +90,6 @@ struct service_info {
|
|||
|
||||
struct ranap_ue_conn_ctx;
|
||||
|
||||
struct gsm_auth_tuple {
|
||||
int use_count;
|
||||
int key_seq;
|
||||
struct osmo_auth_vector vec;
|
||||
};
|
||||
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
|
||||
|
||||
/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
|
||||
/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
|
||||
struct sgsn_mm_ctx {
|
||||
|
@ -295,64 +274,6 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
|
|||
enum gsm48_gsm_cause *gsm_cause,
|
||||
char *apn_str);
|
||||
|
||||
enum pdp_ctx_state {
|
||||
PDP_STATE_NONE,
|
||||
PDP_STATE_CR_REQ,
|
||||
PDP_STATE_CR_CONF,
|
||||
|
||||
/* 04.08 / Figure 6.2 / 6.1.2.2 */
|
||||
PDP_STATE_INACT_PEND,
|
||||
PDP_STATE_INACTIVE = PDP_STATE_NONE,
|
||||
};
|
||||
|
||||
enum pdp_type {
|
||||
PDP_TYPE_NONE,
|
||||
PDP_TYPE_ETSI_PPP,
|
||||
PDP_TYPE_IANA_IPv4,
|
||||
PDP_TYPE_IANA_IPv6,
|
||||
};
|
||||
|
||||
struct sgsn_pdp_ctx {
|
||||
struct llist_head list; /* list_head for mmctx->pdp_list */
|
||||
struct llist_head g_list; /* list_head for global list */
|
||||
struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
|
||||
int destroy_ggsn; /* destroy it on destruction */
|
||||
struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
|
||||
struct llist_head ggsn_list; /* list_head for ggsn->pdp_list */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
//unsigned int id;
|
||||
struct pdp_t *lib; /* pointer to libgtp PDP ctx */
|
||||
enum pdp_ctx_state state;
|
||||
enum pdp_type type;
|
||||
uint32_t address;
|
||||
char *apn_subscribed;
|
||||
//char *apn_used;
|
||||
uint16_t nsapi; /* SNDCP */
|
||||
uint16_t sapi; /* LLC */
|
||||
uint8_t ti; /* transaction identifier */
|
||||
int vplmn_allowed;
|
||||
uint32_t qos_profile_subscr;
|
||||
//uint32_t qos_profile_req;
|
||||
//uint32_t qos_profile_neg;
|
||||
uint8_t radio_prio;
|
||||
//uint32_t charging_id;
|
||||
|
||||
struct osmo_timer_list timer;
|
||||
unsigned int T; /* Txxxx number */
|
||||
unsigned int num_T_exp; /* number of consecutive T expirations */
|
||||
|
||||
struct osmo_timer_list cdr_timer; /* CDR record wird timer */
|
||||
struct timespec cdr_start; /* The start of the CDR */
|
||||
uint64_t cdr_bytes_in;
|
||||
uint64_t cdr_bytes_out;
|
||||
uint32_t cdr_charging_id;
|
||||
};
|
||||
|
||||
#define LOGPDPCTXP(level, pdp, fmt, args...) \
|
||||
LOGP(DGPRS, level, "PDP(%s/%u) " \
|
||||
fmt, (pdp)->mm ? (pdp)->mm->imsi : "---", (pdp)->ti, ## args)
|
||||
|
||||
/* look up PDP context by MM context and NSAPI */
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
|
||||
uint8_t nsapi);
|
||||
|
@ -360,168 +281,7 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
|
|||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
|
||||
uint8_t tid);
|
||||
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
|
||||
struct sgsn_ggsn_ctx *ggsn,
|
||||
uint8_t nsapi);
|
||||
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp);
|
||||
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
|
||||
|
||||
|
||||
struct sgsn_ggsn_ctx {
|
||||
struct llist_head list;
|
||||
uint32_t id;
|
||||
unsigned int gtp_version;
|
||||
struct in_addr remote_addr;
|
||||
int remote_restart_ctr;
|
||||
struct gsn_t *gsn;
|
||||
struct llist_head pdp_list; /* list of associated pdp ctx (struct sgsn_pdp_ctx*) */
|
||||
struct osmo_timer_list echo_timer;
|
||||
unsigned int echo_interval;
|
||||
};
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
|
||||
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
|
||||
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx);
|
||||
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except);
|
||||
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn);
|
||||
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
|
||||
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
|
||||
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc);
|
||||
|
||||
#define LOGGGSN(ggc, level, fmt, args...) { \
|
||||
char _buf[INET_ADDRSTRLEN]; \
|
||||
LOGP(DGTP, level, "GGSN(%" PRIu32 ":%s): " fmt, (ggc)->id, inet_ntop(AF_INET, &(ggc)->remote_addr, _buf, sizeof(_buf)), ## args); \
|
||||
} while (0)
|
||||
|
||||
struct apn_ctx {
|
||||
struct llist_head list;
|
||||
struct sgsn_ggsn_ctx *ggsn;
|
||||
char *name;
|
||||
char *imsi_prefix;
|
||||
char *description;
|
||||
};
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix);
|
||||
void sgsn_apn_ctx_free(struct apn_ctx *actx);
|
||||
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix);
|
||||
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi_prefix);
|
||||
|
||||
extern struct llist_head sgsn_mm_ctxts;
|
||||
extern struct llist_head sgsn_ggsn_ctxts;
|
||||
extern struct llist_head sgsn_apn_ctxts;
|
||||
extern struct llist_head sgsn_pdp_ctxts;
|
||||
|
||||
uint32_t sgsn_alloc_ptmsi(void);
|
||||
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx);
|
||||
void sgsn_inst_init(struct sgsn_instance *sgsn);
|
||||
|
||||
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6);
|
||||
|
||||
/*
|
||||
* ctrl interface related work
|
||||
*/
|
||||
int sgsn_ctrl_cmds_install(void);
|
||||
|
||||
/*
|
||||
* Authorization/ACL handling
|
||||
*/
|
||||
struct imsi_acl_entry {
|
||||
struct llist_head list;
|
||||
char imsi[OSMO_IMSI_BUF_SIZE];
|
||||
};
|
||||
|
||||
/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
|
||||
/* see GSM 09.02, B.1, gprsSubscriptionData */
|
||||
struct sgsn_subscriber_pdp_data {
|
||||
struct llist_head list;
|
||||
|
||||
unsigned int context_id;
|
||||
uint16_t pdp_type;
|
||||
char apn_str[GSM_APN_LENGTH];
|
||||
uint8_t qos_subscribed[20];
|
||||
size_t qos_subscribed_len;
|
||||
uint8_t pdp_charg[2];
|
||||
bool has_pdp_charg;
|
||||
};
|
||||
|
||||
struct sgsn_subscriber_data {
|
||||
struct sgsn_mm_ctx *mm;
|
||||
struct gsm_auth_tuple auth_triplets[5];
|
||||
int auth_triplets_updated;
|
||||
struct llist_head pdp_list;
|
||||
int error_cause;
|
||||
|
||||
uint8_t msisdn[9];
|
||||
size_t msisdn_len;
|
||||
|
||||
uint8_t hlr[9];
|
||||
size_t hlr_len;
|
||||
|
||||
uint8_t pdp_charg[2];
|
||||
bool has_pdp_charg;
|
||||
};
|
||||
|
||||
#define SGSN_ERROR_CAUSE_NONE (-1)
|
||||
|
||||
#define LOGGSUBSCRP(level, subscr, fmt, args...) \
|
||||
LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
|
||||
(subscr) ? (subscr)->imsi : "---", \
|
||||
## args)
|
||||
|
||||
struct sgsn_config;
|
||||
struct sgsn_instance;
|
||||
extern const struct value_string *sgsn_auth_state_names;
|
||||
|
||||
void sgsn_auth_init(struct sgsn_instance *sgsn);
|
||||
struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, const struct sgsn_config *cfg);
|
||||
int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg);
|
||||
int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg);
|
||||
/* Request authorization */
|
||||
int sgsn_auth_request(struct sgsn_mm_ctx *mm);
|
||||
enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm);
|
||||
void sgsn_auth_update(struct sgsn_mm_ctx *mm);
|
||||
struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
|
||||
unsigned key_seq);
|
||||
|
||||
/*
|
||||
* GPRS subscriber data
|
||||
*/
|
||||
#define GPRS_SUBSCRIBER_FIRST_CONTACT 0x00000001
|
||||
#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
|
||||
#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
|
||||
#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
|
||||
#define GPRS_SUBSCRIBER_ENABLE_PURGE (1 << 19)
|
||||
|
||||
#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
|
||||
GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
|
||||
GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
|
||||
)
|
||||
|
||||
int gprs_subscr_init(struct sgsn_instance *sgi);
|
||||
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
|
||||
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
|
||||
const uint8_t *auts,
|
||||
const uint8_t *auts_rand);
|
||||
int gprs_subscr_auth_sync(struct gprs_subscr *subscr,
|
||||
const uint8_t *auts, const uint8_t *auts_rand);
|
||||
void gprs_subscr_cleanup(struct gprs_subscr *subscr);
|
||||
struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi);
|
||||
struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx( struct sgsn_mm_ctx *mmctx);
|
||||
struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi);
|
||||
void gprs_subscr_cancel(struct gprs_subscr *subscr);
|
||||
void gprs_subscr_update(struct gprs_subscr *subscr);
|
||||
void gprs_subscr_update_auth_info(struct gprs_subscr *subscr);
|
||||
int gprs_subscr_rx_gsup_message(struct msgb *msg);
|
||||
|
||||
/* Called on subscriber data updates */
|
||||
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);
|
||||
|
||||
int gprs_sndcp_vty_init(void);
|
||||
struct sgsn_instance;
|
||||
int sgsn_gtp_init(struct sgsn_instance *sgi);
|
||||
|
||||
void sgsn_rate_ctr_init();
|
||||
|
||||
#endif /* _GPRS_SGSN_H */
|
|
@ -0,0 +1,94 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
|
||||
#include <osmocom/crypt/gprs_cipher.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
#include <osmocom/crypt/auth.h>
|
||||
|
||||
#include <osmocom/sgsn/apn.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
struct sgsn_ggsn_ctx;
|
||||
|
||||
enum gprs_pdp_ctx {
|
||||
PDP_CTR_PKTS_UDATA_IN,
|
||||
PDP_CTR_PKTS_UDATA_OUT,
|
||||
PDP_CTR_BYTES_UDATA_IN,
|
||||
PDP_CTR_BYTES_UDATA_OUT,
|
||||
};
|
||||
|
||||
enum pdp_ctx_state {
|
||||
PDP_STATE_NONE,
|
||||
PDP_STATE_CR_REQ,
|
||||
PDP_STATE_CR_CONF,
|
||||
|
||||
/* 04.08 / Figure 6.2 / 6.1.2.2 */
|
||||
PDP_STATE_INACT_PEND,
|
||||
PDP_STATE_INACTIVE = PDP_STATE_NONE,
|
||||
};
|
||||
|
||||
enum pdp_type {
|
||||
PDP_TYPE_NONE,
|
||||
PDP_TYPE_ETSI_PPP,
|
||||
PDP_TYPE_IANA_IPv4,
|
||||
PDP_TYPE_IANA_IPv6,
|
||||
};
|
||||
|
||||
struct sgsn_pdp_ctx {
|
||||
struct llist_head list; /* list_head for mmctx->pdp_list */
|
||||
struct llist_head g_list; /* list_head for global list */
|
||||
struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
|
||||
int destroy_ggsn; /* destroy it on destruction */
|
||||
struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
|
||||
struct llist_head ggsn_list; /* list_head for ggsn->pdp_list */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
//unsigned int id;
|
||||
struct pdp_t *lib; /* pointer to libgtp PDP ctx */
|
||||
enum pdp_ctx_state state;
|
||||
enum pdp_type type;
|
||||
uint32_t address;
|
||||
char *apn_subscribed;
|
||||
//char *apn_used;
|
||||
uint16_t nsapi; /* SNDCP */
|
||||
uint16_t sapi; /* LLC */
|
||||
uint8_t ti; /* transaction identifier */
|
||||
int vplmn_allowed;
|
||||
uint32_t qos_profile_subscr;
|
||||
//uint32_t qos_profile_req;
|
||||
//uint32_t qos_profile_neg;
|
||||
uint8_t radio_prio;
|
||||
//uint32_t charging_id;
|
||||
|
||||
struct osmo_timer_list timer;
|
||||
unsigned int T; /* Txxxx number */
|
||||
unsigned int num_T_exp; /* number of consecutive T expirations */
|
||||
|
||||
struct osmo_timer_list cdr_timer; /* CDR record wird timer */
|
||||
struct timespec cdr_start; /* The start of the CDR */
|
||||
uint64_t cdr_bytes_in;
|
||||
uint64_t cdr_bytes_out;
|
||||
uint32_t cdr_charging_id;
|
||||
};
|
||||
|
||||
#define LOGPDPCTXP(level, pdp, fmt, args...) \
|
||||
LOGP(DGPRS, level, "PDP(%s/%u) " \
|
||||
fmt, (pdp)->mm ? (pdp)->mm->imsi : "---", (pdp)->ti, ## args)
|
||||
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
|
||||
struct sgsn_ggsn_ctx *ggsn,
|
||||
uint8_t nsapi);
|
||||
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp);
|
||||
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
|
||||
|
||||
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6);
|
||||
|
|
@ -8,13 +8,13 @@
|
|||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/auth.h>
|
||||
#include <osmocom/sgsn/gtp_mme.h>
|
||||
#include <osmocom/gsm/oap_client.h>
|
||||
#include <osmocom/gsupclient/gsup_client.h>
|
||||
#include <osmocom/sgsn/common.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
#include "../../config.h"
|
||||
|
||||
#if BUILD_IU
|
||||
#include <osmocom/ranap/iu_client.h>
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
struct hostent;
|
||||
|
||||
#define SGSN_ERROR_CAUSE_NONE (-1)
|
||||
|
||||
enum sgsn_auth_policy {
|
||||
SGSN_AUTH_POLICY_OPEN,
|
||||
SGSN_AUTH_POLICY_CLOSED,
|
||||
|
@ -75,6 +77,7 @@ struct sgsn_config {
|
|||
/* misc */
|
||||
struct gprs_ns2_inst *nsi;
|
||||
|
||||
char *crypt_cipher_plugin_path;
|
||||
enum sgsn_auth_policy auth_policy;
|
||||
uint8_t gea_encryption_mask;
|
||||
uint8_t uea_encryption_mask;
|
||||
|
@ -93,6 +96,7 @@ struct sgsn_config {
|
|||
|
||||
/* Timer defintions */
|
||||
struct osmo_tdef *T_defs;
|
||||
struct osmo_tdef *T_defs_gtp;
|
||||
|
||||
int dynamic_lookup;
|
||||
|
||||
|
@ -150,10 +154,22 @@ struct sgsn_instance {
|
|||
|
||||
struct rate_ctr_group *rate_ctrs;
|
||||
|
||||
struct llist_head apn_list; /* list of struct sgsn_apn_ctx */
|
||||
struct llist_head ggsn_list; /* list of struct sgsn_ggsn_ctx */
|
||||
struct llist_head mme_list; /* list of struct sgsn_mme_ctx */
|
||||
struct llist_head mm_list; /* list of struct sgsn_mm_ctx */
|
||||
struct llist_head pdp_list; /* list of struct sgsn_pdp_ctx */
|
||||
|
||||
struct ctrl_handle *ctrlh;
|
||||
};
|
||||
|
||||
extern struct sgsn_instance *sgsn;
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
/*
|
||||
* ctrl interface related work (sgsn_ctrl.c)
|
||||
*/
|
||||
int sgsn_ctrl_cmds_install(void);
|
||||
|
||||
/* sgsn_vty.c */
|
||||
|
||||
|
@ -162,40 +178,13 @@ int sgsn_parse_config(const char *config_file);
|
|||
char *sgsn_gtp_ntoa(struct ul16_t *ul);
|
||||
|
||||
/* sgsn.c */
|
||||
|
||||
/* Main input function for Gb proxy */
|
||||
int sgsn_rcvmsg(struct msgb *msg, struct gprs_ns2_vc *nsvc, uint16_t ns_bvci);
|
||||
|
||||
/* sgsn_libgtp.c */
|
||||
struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
|
||||
struct sgsn_mm_ctx *mmctx,
|
||||
uint16_t nsapi,
|
||||
struct tlv_parsed *tp);
|
||||
int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
|
||||
void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen);
|
||||
void sgsn_ggsn_echo_req(struct sgsn_ggsn_ctx *ggc);
|
||||
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx);
|
||||
int sgsn_mme_ran_info_req(struct sgsn_mme_ctx *mme, const struct bssgp_ran_information_pdu *pdu);
|
||||
|
||||
/* gprs_sndcp.c */
|
||||
|
||||
/* Entry point for the SNSM-ACTIVATE.indication */
|
||||
int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
|
||||
/* Entry point for the SNSM-DEACTIVATE.indication */
|
||||
int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
|
||||
/* Called by SNDCP when it has received/re-assembled a N-PDU */
|
||||
int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
|
||||
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
|
||||
int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
|
||||
void *mmcontext);
|
||||
int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
|
||||
uint8_t *hdr, uint16_t len);
|
||||
|
||||
|
||||
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx);
|
||||
int sgsn_inst_init(struct sgsn_instance *sgsn);
|
||||
/*
|
||||
* CDR related functionality
|
||||
*/
|
||||
int sgsn_cdr_init(struct sgsn_instance *sgsn);
|
||||
void sgsn_cdr_release(struct sgsn_instance *sgsn);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
struct sgsn_mme_ctx;
|
||||
|
||||
int sgsn_rim_rx_from_gb(struct osmo_bssgp_prim *bp, struct msgb *msg);
|
||||
int sgsn_rim_rx_from_gtp(struct bssgp_ran_information_pdu *pdu, struct sgsn_mme_ctx *mme);
|
||||
int sgsn_rim_rx_from_gtp(struct msgb *msg, struct bssgp_rim_routing_info *rim_routing_address);
|
||||
|
|
|
@ -29,7 +29,6 @@ endif
|
|||
noinst_LTLIBRARIES = libcommon.la
|
||||
|
||||
libcommon_la_SOURCES = \
|
||||
gprs_gb_parse.c \
|
||||
gprs_llc_parse.c \
|
||||
crc24.c \
|
||||
gprs_utils.c \
|
||||
|
|
|
@ -59,7 +59,7 @@ static const uint32_t tbl_crc24[256] = {
|
|||
|
||||
#define INIT_CRC24 0xffffff
|
||||
|
||||
uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len)
|
||||
uint32_t crc24_calc(uint32_t fcs, const uint8_t *cp, unsigned int len)
|
||||
{
|
||||
while (len--)
|
||||
fcs = (fcs >> 8) ^ tbl_crc24[(fcs ^ *cp++) & 0xff];
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/crc24.h>
|
||||
|
@ -55,7 +55,7 @@ static const struct value_string llc_cmd_strs[] = {
|
|||
#define N202 4
|
||||
#define CRC24_LENGTH 3
|
||||
|
||||
int gprs_llc_fcs(uint8_t *data, unsigned int len)
|
||||
int gprs_llc_fcs(const uint8_t *data, unsigned int len)
|
||||
{
|
||||
uint32_t fcs_calc;
|
||||
|
||||
|
|
|
@ -30,56 +30,6 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str)
|
||||
{
|
||||
uint8_t *last_len_field;
|
||||
int len;
|
||||
|
||||
/* Can we even write the length field to the output? */
|
||||
if (max_len == 0)
|
||||
return -1;
|
||||
|
||||
/* Remember where we need to put the length once we know it */
|
||||
last_len_field = apn_enc;
|
||||
len = 1;
|
||||
apn_enc += 1;
|
||||
|
||||
while (str[0]) {
|
||||
if (len >= max_len)
|
||||
return -1;
|
||||
|
||||
if (str[0] == '.') {
|
||||
*last_len_field = (apn_enc - last_len_field) - 1;
|
||||
last_len_field = apn_enc;
|
||||
} else {
|
||||
*apn_enc = str[0];
|
||||
}
|
||||
apn_enc += 1;
|
||||
str += 1;
|
||||
len += 1;
|
||||
}
|
||||
|
||||
*last_len_field = (apn_enc - last_len_field) - 1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* GSM 04.08, 10.5.7.3 GPRS Timer */
|
||||
int gprs_tmr_to_secs(uint8_t tmr)
|
||||
{
|
||||
switch (tmr & GPRS_TMR_UNIT_MASK) {
|
||||
case GPRS_TMR_2SECONDS:
|
||||
return 2 * (tmr & GPRS_TMR_FACT_MASK);
|
||||
default:
|
||||
case GPRS_TMR_MINUTE:
|
||||
return 60 * (tmr & GPRS_TMR_FACT_MASK);
|
||||
case GPRS_TMR_6MINUTE:
|
||||
return 360 * (tmr & GPRS_TMR_FACT_MASK);
|
||||
case GPRS_TMR_DEACTIVATED:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* This functions returns a tmr value such that
|
||||
* - f is monotonic
|
||||
* - f(s) <= s
|
||||
|
@ -132,19 +82,6 @@ int gprs_is_mi_imsi(const uint8_t *value, size_t value_len)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi)
|
||||
{
|
||||
uint32_t tmsi_be;
|
||||
|
||||
if (!gprs_is_mi_tmsi(value, value_len))
|
||||
return 0;
|
||||
|
||||
memcpy(&tmsi_be, value + 1, sizeof(tmsi_be));
|
||||
|
||||
*tmsi = ntohl(tmsi_be);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi)
|
||||
{
|
||||
uint32_t tmsi_be;
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
|
||||
#include <netdb.h>
|
||||
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
struct cares_event_fd {
|
||||
struct llist_head head;
|
||||
struct osmo_fd fd;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <gtp.h>
|
||||
#include <gtpie.h>
|
||||
|
||||
#include <osmocom/sgsn/gtphub.h>
|
||||
#include <osmocom/gtphub/gtphub.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
|
||||
|
@ -475,7 +475,7 @@ static int get_ie_imsi_str(union gtpie_member *ie[], int i,
|
|||
* present but cannot be decoded. */
|
||||
static int get_ie_apn_str(union gtpie_member *ie[], const char **apn_str)
|
||||
{
|
||||
static char apn_buf[GSM_APN_LENGTH];
|
||||
static char apn_buf[APN_MAXLEN+1];
|
||||
unsigned int len;
|
||||
if (gtpie_gettlv(ie, GTPIE_APN, 0,
|
||||
&len, apn_buf, sizeof(apn_buf)) != 0)
|
||||
|
@ -971,7 +971,7 @@ static inline void set_tei(struct gtp_packet_desc *p, uint32_t tei)
|
|||
|
||||
static void gtphub_mapping_del_cb(struct expiring_item *expi);
|
||||
|
||||
static struct nr_mapping *gtphub_mapping_new()
|
||||
static struct nr_mapping *gtphub_mapping_new(void)
|
||||
{
|
||||
struct nr_mapping *nrm;
|
||||
nrm = talloc_zero(osmo_gtphub_ctx, struct nr_mapping);
|
||||
|
@ -995,7 +995,7 @@ static const char *gtphub_tunnel_side_str(struct gtphub_tunnel *tun,
|
|||
char *pos = buf;
|
||||
int left = sizeof(buf);
|
||||
int l;
|
||||
|
||||
|
||||
struct gtphub_tunnel_endpoint *c, *u;
|
||||
c = &tun->endpoint[side_idx][GTPH_PLANE_CTRL];
|
||||
u = &tun->endpoint[side_idx][GTPH_PLANE_USER];
|
||||
|
@ -1104,7 +1104,7 @@ static void gtphub_tunnel_del_cb(struct expiring_item *expi)
|
|||
/* rate counter index for hubs: [7; 10] */
|
||||
#define CTR_IDX_HUB(s, p) CTR_IDX(s, p, 3, 2)
|
||||
|
||||
static struct gtphub_tunnel *gtphub_tunnel_new()
|
||||
static struct gtphub_tunnel *gtphub_tunnel_new(void)
|
||||
{
|
||||
struct gtphub_tunnel *tun;
|
||||
tun = talloc_zero(osmo_gtphub_ctx, struct gtphub_tunnel);
|
||||
|
@ -2283,7 +2283,7 @@ int gtphub_handle_buf(struct gtphub *hub,
|
|||
!= 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Either to_peer was resolved from an existing tunnel,
|
||||
* or a PDP Ctx and thus a tunnel has just been created,
|
||||
* or the tunnel has been deleted due to this message. */
|
||||
|
@ -2690,7 +2690,7 @@ static struct gtphub_peer_addr *gtphub_addr_have(struct gtphub *hub,
|
|||
struct gtphub_peer *peer = gtphub_peer_new(hub, bind);
|
||||
|
||||
a = gtphub_peer_add_addr(peer, addr);
|
||||
|
||||
|
||||
LOG(LOGL_DEBUG, "New peer address: %s %s\n",
|
||||
bind->label,
|
||||
gsn_addr_to_str(&a->addr));
|
||||
|
|
|
@ -28,11 +28,12 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <osmocom/sgsn/gtphub.h>
|
||||
#include <osmocom/gtphub/gtphub.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
/* TODO split GRX ares from sgsn into a separate struct and allow use without
|
||||
* globals. */
|
||||
|
@ -56,8 +57,8 @@ struct ggsn_lookup {
|
|||
struct gtphub *hub;
|
||||
|
||||
char imsi_str[GSM23003_IMSI_MAX_DIGITS+1];
|
||||
char apn_ni_str[GSM_APN_LENGTH];
|
||||
char apn_oi_str[GSM_APN_LENGTH];
|
||||
char apn_ni_str[APN_MAXLEN+1];
|
||||
char apn_oi_str[APN_MAXLEN+1];
|
||||
int have_3dig_mnc;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
|
@ -41,10 +42,10 @@
|
|||
#include <osmocom/vty/misc.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gtphub.h>
|
||||
#include <osmocom/gtphub/gtphub.h>
|
||||
#include <osmocom/sgsn/vty.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
#include "../../config.h"
|
||||
|
||||
#if BUILD_IU
|
||||
#include <osmocom/sigtran/osmo_ss7.h>
|
||||
|
@ -353,8 +354,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/* start telnet after reading config for vty_get_bind_addr() */
|
||||
rc = telnet_init_dynif(osmo_gtphub_ctx, 0, vty_get_bind_addr(),
|
||||
OSMO_VTY_PORT_GTPHUB);
|
||||
rc = telnet_init_default(osmo_gtphub_ctx, NULL, OSMO_VTY_PORT_GTPHUB);
|
||||
if (rc < 0)
|
||||
exit(1);
|
||||
|
||||
|
|
|
@ -25,7 +25,12 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <osmocom/sgsn/gtphub.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
#include <osmocom/gtphub/gtphub.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
/* Convenience makro, note: only within this C file. */
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <osmocom/vty/misc.h>
|
||||
|
||||
#include <osmocom/sgsn/vty.h>
|
||||
#include <osmocom/sgsn/gtphub.h>
|
||||
#include <osmocom/gtphub/gtphub.h>
|
||||
|
||||
/* TODO split GRX ares from sgsn into a separate struct and allow use without
|
||||
* globals. */
|
||||
|
|
|
@ -40,12 +40,13 @@ bin_PROGRAMS = \
|
|||
$(NULL)
|
||||
|
||||
osmo_sgsn_SOURCES = \
|
||||
gprs_gb.c \
|
||||
apn.c \
|
||||
gprs_bssgp.c \
|
||||
gprs_gmm_attach.c \
|
||||
gprs_gmm.c \
|
||||
gprs_gmm_fsm.c \
|
||||
gprs_mm_state_gb_fsm.c \
|
||||
gprs_sgsn.c \
|
||||
gprs_ns.c \
|
||||
gprs_sm.c \
|
||||
gprs_sndcp.c \
|
||||
gprs_sndcp_comp.c \
|
||||
|
@ -53,12 +54,16 @@ osmo_sgsn_SOURCES = \
|
|||
gprs_sndcp_pcomp.c \
|
||||
gprs_sndcp_vty.c \
|
||||
gprs_sndcp_xid.c \
|
||||
gtp_ggsn.c \
|
||||
gtp_mme.c \
|
||||
sgsn.c \
|
||||
sgsn_main.c \
|
||||
sgsn_vty.c \
|
||||
sgsn_libgtp.c \
|
||||
gprs_llc.c \
|
||||
gprs_llc_vty.c \
|
||||
mmctx.c \
|
||||
pdpctx.c \
|
||||
sgsn_ctrl.c \
|
||||
sgsn_auth.c \
|
||||
gprs_subscriber.c \
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/* APN contexts */
|
||||
|
||||
/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 by On-Waves
|
||||
* (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <talloc.h>
|
||||
|
||||
#include <osmocom/sgsn/apn.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
|
||||
static struct apn_ctx *sgsn_apn_ctx_alloc(const char *ap_name, const char *imsi_prefix)
|
||||
{
|
||||
struct apn_ctx *actx;
|
||||
|
||||
actx = talloc_zero(sgsn, struct apn_ctx);
|
||||
if (!actx)
|
||||
return NULL;
|
||||
actx->name = talloc_strdup(actx, ap_name);
|
||||
actx->imsi_prefix = talloc_strdup(actx, imsi_prefix);
|
||||
|
||||
llist_add_tail(&actx->list, &sgsn->apn_list);
|
||||
|
||||
return actx;
|
||||
}
|
||||
|
||||
void sgsn_apn_ctx_free(struct apn_ctx *actx)
|
||||
{
|
||||
llist_del(&actx->list);
|
||||
talloc_free(actx);
|
||||
}
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi)
|
||||
{
|
||||
struct apn_ctx *actx;
|
||||
struct apn_ctx *found_actx = NULL;
|
||||
size_t imsi_prio = 0;
|
||||
size_t name_prio = 0;
|
||||
size_t name_req_len = strlen(name);
|
||||
|
||||
llist_for_each_entry(actx, &sgsn->apn_list, list) {
|
||||
size_t name_ref_len, imsi_ref_len;
|
||||
const char *name_ref_start, *name_match_start;
|
||||
|
||||
imsi_ref_len = strlen(actx->imsi_prefix);
|
||||
if (strncmp(actx->imsi_prefix, imsi, imsi_ref_len) != 0)
|
||||
continue;
|
||||
|
||||
if (imsi_ref_len < imsi_prio)
|
||||
continue;
|
||||
|
||||
/* IMSI matches */
|
||||
|
||||
name_ref_start = &actx->name[0];
|
||||
if (name_ref_start[0] == '*') {
|
||||
/* Suffix match */
|
||||
name_ref_start += 1;
|
||||
name_ref_len = strlen(name_ref_start);
|
||||
if (name_ref_len > name_req_len)
|
||||
continue;
|
||||
} else {
|
||||
name_ref_len = strlen(name_ref_start);
|
||||
if (name_ref_len != name_req_len)
|
||||
continue;
|
||||
}
|
||||
|
||||
name_match_start = name + (name_req_len - name_ref_len);
|
||||
if (strcasecmp(name_match_start, name_ref_start) != 0)
|
||||
continue;
|
||||
|
||||
/* IMSI and name match */
|
||||
|
||||
if (imsi_ref_len == imsi_prio && name_ref_len < name_prio)
|
||||
/* Lower priority, skip */
|
||||
continue;
|
||||
|
||||
imsi_prio = imsi_ref_len;
|
||||
name_prio = name_ref_len;
|
||||
found_actx = actx;
|
||||
}
|
||||
return found_actx;
|
||||
}
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix)
|
||||
{
|
||||
struct apn_ctx *actx;
|
||||
|
||||
llist_for_each_entry(actx, &sgsn->apn_list, list) {
|
||||
if (strcasecmp(name, actx->name) == 0 &&
|
||||
strcasecmp(imsi_prefix, actx->imsi_prefix) == 0)
|
||||
return actx;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix)
|
||||
{
|
||||
struct apn_ctx *actx;
|
||||
|
||||
actx = sgsn_apn_ctx_by_name(name, imsi_prefix);
|
||||
if (!actx)
|
||||
actx = sgsn_apn_ctx_alloc(name, imsi_prefix);
|
||||
|
||||
return actx;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/* GPRS BSSGP protocol implementation as per 3GPP TS 08.18 */
|
||||
|
||||
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 by On-Waves
|
||||
* (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
*
|
||||
* 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 <osmocom/core/prim.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/sgsn_rim.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
|
||||
/* call-back function for the BSSGP protocol */
|
||||
int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph)
|
||||
{
|
||||
struct osmo_bssgp_prim *bp;
|
||||
bp = container_of(oph, struct osmo_bssgp_prim, oph);
|
||||
|
||||
switch (oph->sap) {
|
||||
case SAP_BSSGP_LL:
|
||||
switch (oph->primitive) {
|
||||
case PRIM_BSSGP_UL_UD:
|
||||
return gprs_llc_rcvmsg(oph->msg, bp->tp);
|
||||
}
|
||||
break;
|
||||
case SAP_BSSGP_GMM:
|
||||
switch (oph->primitive) {
|
||||
case PRIM_BSSGP_GMM_SUSPEND:
|
||||
return gprs_gmm_rx_suspend(bp->ra_id, bp->tlli);
|
||||
case PRIM_BSSGP_GMM_RESUME:
|
||||
return gprs_gmm_rx_resume(bp->ra_id, bp->tlli,
|
||||
bp->u.resume.suspend_ref);
|
||||
}
|
||||
break;
|
||||
case SAP_BSSGP_NM:
|
||||
break;
|
||||
case SAP_BSSGP_RIM:
|
||||
return sgsn_rim_rx_from_gb(bp, oph->msg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sgsn_bssgp_page_ps_ra(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
struct bssgp_paging_info pinfo;
|
||||
int rc;
|
||||
|
||||
/* FIXME: page whole routing area, not only the last known cell */
|
||||
|
||||
/* initiate PS PAGING procedure */
|
||||
memset(&pinfo, 0, sizeof(pinfo));
|
||||
pinfo.mode = BSSGP_PAGING_PS;
|
||||
pinfo.scope = BSSGP_PAGING_BVCI;
|
||||
pinfo.bvci = mmctx->gb.bvci;
|
||||
pinfo.imsi = mmctx->imsi;
|
||||
pinfo.ptmsi = &mmctx->p_tmsi;
|
||||
pinfo.drx_params = mmctx->drx_parms;
|
||||
pinfo.qos[0] = 0; // FIXME
|
||||
rc = bssgp_tx_paging(mmctx->gb.nsei, 0, &pinfo);
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PAGING_PS));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* called by the bssgp layer to send NS PDUs */
|
||||
int sgsn_bssgp_dispatch_ns_unitdata_req_cb(void *ctx, struct msgb *msg)
|
||||
{
|
||||
struct gprs_ns2_inst *nsi = (struct gprs_ns2_inst *) ctx;
|
||||
struct osmo_gprs_ns2_prim nsp = {};
|
||||
nsp.nsei = msgb_nsei(msg);
|
||||
nsp.bvci = msgb_bvci(msg);
|
||||
osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA, PRIM_OP_REQUEST, msg);
|
||||
return gprs_ns2_recv_prim(nsi, &nsp.oph);
|
||||
}
|
|
@ -30,7 +30,7 @@
|
|||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "bscconfig.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
|
@ -48,7 +48,7 @@
|
|||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
|
@ -60,17 +60,17 @@
|
|||
#include <osmocom/sgsn/signal.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp.h>
|
||||
#include <osmocom/sgsn/gprs_ranap.h>
|
||||
#include <osmocom/sgsn/gprs_sm.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
|
||||
#include <pdp.h>
|
||||
|
||||
#define PTMSI_ALLOC
|
||||
|
||||
extern struct sgsn_instance *sgsn;
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
static const struct tlv_definition gsm48_gmm_att_tlvdef = {
|
||||
.def = {
|
||||
[GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_FIXED, 1 },
|
||||
[GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_SINGLE_TV, 1 },
|
||||
[GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 },
|
||||
[GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 },
|
||||
[GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 },
|
||||
|
@ -79,6 +79,7 @@ static const struct tlv_definition gsm48_gmm_att_tlvdef = {
|
|||
[GSM48_IE_GMM_AUTH_RES_EXT] = { TLV_TYPE_TLV, 0 },
|
||||
[GSM48_IE_GMM_AUTH_FAIL_PAR] = { TLV_TYPE_TLV, 0 },
|
||||
[GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 },
|
||||
[GSM48_IE_GMM_RX_NPDU_NUM_LIST] = { TLV_TYPE_TLV, 0 },
|
||||
[GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_FIXED, 2 },
|
||||
[GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 },
|
||||
[GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 },
|
||||
|
@ -110,9 +111,14 @@ static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T)
|
|||
|
||||
static void mmctx_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
|
||||
{
|
||||
if (mm->T != T)
|
||||
if (!osmo_timer_pending(&mm->timer)) {
|
||||
LOGMMCTXP(LOGL_NOTICE, mm, "Stopping *inactive* MM timer %u\n", T);
|
||||
return;
|
||||
}
|
||||
if (mm->T != T) {
|
||||
LOGMMCTXP(LOGL_ERROR, mm, "Stopping MM timer %u but "
|
||||
"%u is running\n", T, mm->T);
|
||||
}
|
||||
osmo_timer_del(&mm->timer);
|
||||
}
|
||||
|
||||
|
@ -1390,11 +1396,11 @@ static int gsm48_rx_gmm_att_compl(struct sgsn_mm_ctx *mmctx)
|
|||
/* only in case SGSN offered new P-TMSI */
|
||||
LOGMMCTXP(LOGL_INFO, mmctx, "-> GMM ATTACH COMPLETE\n");
|
||||
|
||||
#ifdef BUILD_IU
|
||||
#ifdef BUILD_IU
|
||||
if (mmctx->iu.ue_ctx) {
|
||||
ranap_iu_tx_release(mmctx->iu.ue_ctx, NULL);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
mmctx_timer_stop(mmctx, 3350);
|
||||
mmctx->t3350_mode = GMM_T3350_MODE_NONE;
|
||||
|
@ -1766,6 +1772,10 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
|
|||
/* Update the MM context with the new (i.e. foreign) TLLI */
|
||||
mmctx->gb.tlli = msgb_tlli(msg);
|
||||
}
|
||||
/* Update the MM context with the new DRX params */
|
||||
if (TLVP_PRESENT(&tp, GSM48_IE_GMM_DRX_PARAM))
|
||||
memcpy(&mmctx->drx_parms, TLVP_VAL(&tp, GSM48_IE_GMM_DRX_PARAM), sizeof(mmctx->drx_parms));
|
||||
|
||||
/* FIXME: Update the MM context with the MS radio acc capabilities */
|
||||
/* FIXME: Update the MM context with the MS network capabilities */
|
||||
|
||||
|
@ -2313,3 +2323,51 @@ int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
|
|||
osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_RESUME, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
|
||||
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg)
|
||||
{
|
||||
msgid2mmctx(mmctx, msg);
|
||||
if (mmctx->gb.llme)
|
||||
osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_PDU_RECEPTION, NULL);
|
||||
}
|
||||
|
||||
/* Main entry point for incoming 04.08 GPRS messages from Gb */
|
||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
|
||||
bool drop_cipherable)
|
||||
{
|
||||
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
|
||||
uint8_t pdisc = gsm48_hdr_pdisc(gh);
|
||||
struct sgsn_mm_ctx *mmctx;
|
||||
struct gprs_ra_id ra_id;
|
||||
int rc = -EINVAL;
|
||||
|
||||
bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
|
||||
mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
|
||||
if (mmctx) {
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PKTS_SIG_IN));
|
||||
mmctx->gb.llme = llme;
|
||||
gprs_gb_recv_pdu(mmctx, msg);
|
||||
}
|
||||
|
||||
/* MMCTX can be NULL */
|
||||
|
||||
switch (pdisc) {
|
||||
case GSM48_PDISC_MM_GPRS:
|
||||
rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
|
||||
break;
|
||||
case GSM48_PDISC_SM_GPRS:
|
||||
rc = gsm0408_rcv_gsm(mmctx, msg, llme);
|
||||
break;
|
||||
default:
|
||||
LOGMMCTXP(LOGL_NOTICE, mmctx,
|
||||
"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
|
||||
pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
|
||||
/* FIXME: return status message */
|
||||
break;
|
||||
}
|
||||
|
||||
/* MMCTX can be invalid */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
|
||||
#define X(s) (1 << (s))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* GMM mobility management states on the network side, 3GPP TS 24.008 § 4.1.3.3 */
|
||||
/*
|
||||
* (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
|
||||
* (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0+
|
||||
|
@ -80,6 +80,11 @@ static void st_gmm_registered_normal(struct osmo_fsm_inst *fi, uint32_t event, v
|
|||
case E_GMM_COMMON_PROC_INIT_REQ:
|
||||
gmm_fsm_state_chg(fi, ST_GMM_COMMON_PROC_INIT);
|
||||
break;
|
||||
case E_GMM_COMMON_PROC_SUCCESS:
|
||||
/* If we were moved from ST_GMM_COMMON_PROC_INIT here by
|
||||
* E_GMM_ATTACH_SUCCESS instead of E_GMM_COMMON_PROC_SUCCESS then we'll receive the latter here:
|
||||
* we should simply ignore it */
|
||||
break;
|
||||
/* case E_GMM_NET_INIT_DETACH_REQ:
|
||||
gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED_INIT);
|
||||
break; */
|
||||
|
@ -141,6 +146,7 @@ static struct osmo_fsm_state gmm_fsm_states[] = {
|
|||
[ST_GMM_REGISTERED_NORMAL] = {
|
||||
.in_event_mask =
|
||||
X(E_GMM_COMMON_PROC_INIT_REQ) |
|
||||
X(E_GMM_COMMON_PROC_SUCCESS) |
|
||||
/* X(E_GMM_NET_INIT_DETACH_REQ) | */
|
||||
/* X(E_GMM_MS_INIT_DETACH_REQ) | */
|
||||
X(E_GMM_SUSPEND),
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <osmocom/gsm/gsm_utils.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/crc24.h>
|
||||
|
@ -50,10 +50,21 @@ const struct value_string gprs_llc_llme_state_names[] = {
|
|||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const struct value_string gprs_llc_lle_state_names[] = {
|
||||
{ GPRS_LLES_UNASSIGNED, "TLLI Unassigned" },
|
||||
{ GPRS_LLES_ASSIGNED_ADM, "TLLI Assigned" },
|
||||
{ GPRS_LLES_LOCAL_EST, "Local Establishment" },
|
||||
{ GPRS_LLES_REMOTE_EST, "Remote Establishment" },
|
||||
{ GPRS_LLES_ABM, "Asynchronous Balanced Mode" },
|
||||
{ GPRS_LLES_LOCAL_REL, "Local Release" },
|
||||
{ GPRS_LLES_TIMER_REC, "Timer Recovery" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static struct gprs_llc_llme *llme_alloc(uint32_t tlli);
|
||||
static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
|
||||
static int gprs_llc_tx_xid(const struct gprs_llc_lle *lle, struct msgb *msg,
|
||||
int command);
|
||||
static int gprs_llc_tx_dm(struct gprs_llc_lle *lle);
|
||||
static int gprs_llc_tx_dm(const struct gprs_llc_lle *lle);
|
||||
static int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi,
|
||||
int command, enum gprs_llc_u_cmd u_cmd, int pf_bit);
|
||||
|
||||
|
@ -212,7 +223,7 @@ static int gprs_llc_process_xid_ind(uint8_t *bytes_request,
|
|||
int bytes_request_len,
|
||||
uint8_t *bytes_response,
|
||||
int bytes_response_maxlen,
|
||||
struct gprs_llc_lle *lle)
|
||||
const struct gprs_llc_lle *lle)
|
||||
{
|
||||
/* Note: This function computes the response that is sent back to the
|
||||
* MS when a mobile originated XID is received. The function is
|
||||
|
@ -288,7 +299,7 @@ static int gprs_llc_process_xid_ind(uint8_t *bytes_request,
|
|||
|
||||
/* Dispatch XID indications and responses comming from the MS */
|
||||
static void rx_llc_xid(struct gprs_llc_lle *lle,
|
||||
struct gprs_llc_hdr_parsed *gph)
|
||||
const struct gprs_llc_hdr_parsed *gph)
|
||||
{
|
||||
uint8_t response[1024];
|
||||
int response_len;
|
||||
|
@ -681,7 +692,7 @@ int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi, int command,
|
|||
}
|
||||
|
||||
/* Send XID response to LLE */
|
||||
static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
|
||||
static int gprs_llc_tx_xid(const struct gprs_llc_lle *lle, struct msgb *msg,
|
||||
int command)
|
||||
{
|
||||
/* copy identifiers from LLE to ensure lower layers can route */
|
||||
|
@ -692,7 +703,7 @@ static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
|
|||
return gprs_llc_tx_u(msg, lle->sapi, command, GPRS_LLC_U_XID, 1);
|
||||
}
|
||||
|
||||
static int gprs_llc_tx_dm(struct gprs_llc_lle *lle)
|
||||
static int gprs_llc_tx_dm(const struct gprs_llc_lle *lle)
|
||||
{
|
||||
struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_DM");
|
||||
|
||||
|
@ -705,7 +716,7 @@ static int gprs_llc_tx_dm(struct gprs_llc_lle *lle)
|
|||
}
|
||||
|
||||
/* encrypt information field + FCS, if needed! */
|
||||
static int apply_gea(struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu,
|
||||
static int apply_gea(const struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu,
|
||||
uint32_t oc, uint8_t sapi, uint8_t *fcs, uint8_t *data)
|
||||
{
|
||||
uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK];
|
||||
|
@ -965,9 +976,9 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
|
|||
llhp.data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
llhp.fcs = *(llhp.data + llhp.data_len);
|
||||
llhp.fcs |= *(llhp.data + llhp.data_len + 1) << 8;
|
||||
llhp.fcs |= *(llhp.data + llhp.data_len + 2) << 16;
|
||||
llhp.fcs = *(llhp.data + llhp.data_len);
|
||||
llhp.fcs |= *(llhp.data + llhp.data_len + 1) << 8;
|
||||
llhp.fcs |= *(llhp.data + llhp.data_len + 2) << 16;
|
||||
} else {
|
||||
LOGP(DLLC, LOGL_NOTICE, "encrypted frame for LLC that "
|
||||
"has no KC/Algo! Dropping.\n");
|
||||
|
@ -1019,7 +1030,7 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
|
|||
case GPRS_SAPI_SNDCP9:
|
||||
case GPRS_SAPI_SNDCP11:
|
||||
/* send LL_DATA_IND/LL_UNITDATA_IND to SNDCP */
|
||||
rc = sndcp_llunitdata_ind(msg, lle, llhp.data, llhp.data_len);
|
||||
rc = sndcp_ll_unitdata_ind(msg, lle, llhp.data, llhp.data_len);
|
||||
break;
|
||||
case GPRS_SAPI_SMS:
|
||||
/* FIXME */
|
||||
|
@ -1037,7 +1048,7 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
|
|||
}
|
||||
|
||||
/* Propagate crypto parameters MM -> LLME */
|
||||
void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme)
|
||||
void gprs_llme_copy_key(const struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme)
|
||||
{
|
||||
if (!mm)
|
||||
return;
|
||||
|
|
|
@ -39,22 +39,11 @@
|
|||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
|
||||
struct value_string gprs_llc_state_strs[] = {
|
||||
{ GPRS_LLES_UNASSIGNED, "TLLI Unassigned" },
|
||||
{ GPRS_LLES_ASSIGNED_ADM, "TLLI Assigned" },
|
||||
{ GPRS_LLES_LOCAL_EST, "Local Establishment" },
|
||||
{ GPRS_LLES_REMOTE_EST, "Remote Establishment" },
|
||||
{ GPRS_LLES_ABM, "Asynchronous Balanced Mode" },
|
||||
{ GPRS_LLES_LOCAL_REL, "Local Release" },
|
||||
{ GPRS_LLES_TIMER_REC, "Timer Recovery" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static void vty_dump_lle(struct vty *vty, struct gprs_llc_lle *lle)
|
||||
{
|
||||
struct gprs_llc_params *par = &lle->params;
|
||||
vty_out(vty, " SAPI %2u State %s VUsend=%u, VUrecv=%u", lle->sapi,
|
||||
get_value_string(gprs_llc_state_strs, lle->state),
|
||||
vty_out(vty, " SAPI %2u State %s VUsend=%u, VUrecv=%u", lle->sapi,
|
||||
get_value_string(gprs_llc_lle_state_names, lle->state),
|
||||
lle->vu_send, lle->vu_recv);
|
||||
vty_out(vty, " Vsent=%u Vack=%u Vrecv=%u, RetransCtr=%u%s",
|
||||
lle->v_sent, lle->v_ack, lle->v_recv,
|
||||
|
@ -79,7 +68,7 @@ static void vty_dump_llme(struct vty *vty, struct gprs_llc_llme *llme)
|
|||
get_value_string(gprs_cipher_names, llme->algo), llme->iov_ui,
|
||||
llme->cksn, llme->age_timestamp == GPRS_LLME_RESET_AGE ? 0 :
|
||||
(int)(now_tp.tv_sec - (time_t)llme->age_timestamp),
|
||||
get_value_string(gprs_llc_state_strs, llme->state), VTY_NEWLINE);
|
||||
get_value_string(gprs_llc_llme_state_names, llme->state), VTY_NEWLINE);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(valid_sapis); i++) {
|
||||
struct gprs_llc_lle *lle;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* TS 23.060 § 6.1.1 Mobility Management States (A/Gb mode) */
|
||||
/*
|
||||
* (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
|
||||
* (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0+
|
||||
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
|
||||
#define X(s) (1 << (s))
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* TS 23.060 § 6.1.2 Mobility Management States (Iu mode) */
|
||||
/*
|
||||
* (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
|
||||
* (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0+
|
||||
|
@ -29,6 +29,9 @@
|
|||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_ranap.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
|
||||
#define X(s) (1 << (s))
|
||||
|
||||
|
|
|
@ -29,95 +29,10 @@
|
|||
#include <osmocom/gprs/gprs_bssgp_bss.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
|
||||
#include "bscconfig.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_sm.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
|
||||
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg) {
|
||||
msgid2mmctx(mmctx, msg);
|
||||
if (mmctx->gb.llme)
|
||||
osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_PDU_RECEPTION, NULL);
|
||||
}
|
||||
|
||||
/* Main entry point for incoming 04.08 GPRS messages from Gb */
|
||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
|
||||
bool drop_cipherable)
|
||||
{
|
||||
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
|
||||
uint8_t pdisc = gsm48_hdr_pdisc(gh);
|
||||
struct sgsn_mm_ctx *mmctx;
|
||||
struct gprs_ra_id ra_id;
|
||||
int rc = -EINVAL;
|
||||
|
||||
bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
|
||||
mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
|
||||
if (mmctx) {
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PKTS_SIG_IN));
|
||||
mmctx->gb.llme = llme;
|
||||
gprs_gb_recv_pdu(mmctx, msg);
|
||||
}
|
||||
|
||||
/* MMCTX can be NULL */
|
||||
|
||||
switch (pdisc) {
|
||||
case GSM48_PDISC_MM_GPRS:
|
||||
rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
|
||||
break;
|
||||
case GSM48_PDISC_SM_GPRS:
|
||||
rc = gsm0408_rcv_gsm(mmctx, msg, llme);
|
||||
break;
|
||||
default:
|
||||
LOGMMCTXP(LOGL_NOTICE, mmctx,
|
||||
"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
|
||||
pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
|
||||
/* FIXME: return status message */
|
||||
break;
|
||||
}
|
||||
|
||||
/* MMCTX can be invalid */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int gprs_gb_page_ps_ra(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
struct bssgp_paging_info pinfo;
|
||||
int rc;
|
||||
|
||||
/* FIXME: page whole routing area, not only the last known cell */
|
||||
|
||||
/* initiate PS PAGING procedure */
|
||||
memset(&pinfo, 0, sizeof(pinfo));
|
||||
pinfo.mode = BSSGP_PAGING_PS;
|
||||
pinfo.scope = BSSGP_PAGING_BVCI;
|
||||
pinfo.bvci = mmctx->gb.bvci;
|
||||
pinfo.imsi = mmctx->imsi;
|
||||
pinfo.ptmsi = &mmctx->p_tmsi;
|
||||
pinfo.drx_params = mmctx->drx_parms;
|
||||
pinfo.qos[0] = 0; // FIXME
|
||||
rc = bssgp_tx_paging(mmctx->gb.nsei, 0, &pinfo);
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PAGING_PS));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* called by the bssgp layer to send NS PDUs */
|
||||
int gprs_gb_send_cb(void *ctx, struct msgb *msg)
|
||||
{
|
||||
struct gprs_ns2_inst *nsi = (struct gprs_ns2_inst *) ctx;
|
||||
struct osmo_gprs_ns2_prim nsp = {};
|
||||
nsp.nsei = msgb_nsei(msg);
|
||||
nsp.bvci = msgb_bvci(msg);
|
||||
osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA, PRIM_OP_REQUEST, msg);
|
||||
return gprs_ns2_recv_prim(nsi, &nsp.oph);
|
||||
}
|
||||
|
||||
void gprs_ns_prim_status_cb(struct osmo_gprs_ns2_prim *nsp)
|
||||
{
|
||||
switch (nsp->u.status.cause) {
|
|
@ -21,7 +21,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "bscconfig.h"
|
||||
#include "config.h"
|
||||
#include <gtp.h>
|
||||
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
@ -37,6 +37,10 @@
|
|||
#include <osmocom/sgsn/gprs_ranap.h>
|
||||
#include <osmocom/sgsn/gprs_gmm_attach.h>
|
||||
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
|
||||
/* Send RAB activation requests for all PDP contexts */
|
||||
void activate_pdp_rabs(struct sgsn_mm_ctx *ctx)
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "bscconfig.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/tdef.h>
|
||||
|
@ -36,13 +36,15 @@
|
|||
#include <osmocom/sgsn/gprs_sm.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp.h>
|
||||
#include <osmocom/sgsn/gprs_ranap.h>
|
||||
|
||||
extern void *tall_sgsn_ctx;
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
|
||||
/* 3GPP TS 04.08 sec 6.1.3.4.3(.a) "Abnormal cases" */
|
||||
#define T339X_MAX_RETRANS 4
|
||||
|
@ -376,7 +378,7 @@ static void ggsn_lookup_cb(void *arg, int status, int timeouts, struct hostent *
|
|||
goto reject_due_failure;
|
||||
}
|
||||
|
||||
ggsn = sgsn_ggsn_ctx_alloc(UINT32_MAX);
|
||||
ggsn = sgsn_ggsn_ctx_alloc(sgsn, UINT32_MAX);
|
||||
if (!ggsn) {
|
||||
LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "Failed to create ggsn.\n");
|
||||
goto reject_due_failure;
|
||||
|
@ -448,7 +450,7 @@ static int do_act_pdp_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg, bool *del
|
|||
DEBUGPC(DMM, "IPv4 ");
|
||||
if (req_pdpa_len >= 6) {
|
||||
struct in_addr ia;
|
||||
ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2)));
|
||||
ia.s_addr = osmo_load32be(req_pdpa+2);
|
||||
DEBUGPC(DMM, "%s ", inet_ntop(AF_INET, &ia, buf, sizeof(buf)));
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_gb.h>
|
||||
#include <osmocom/sgsn/gprs_ns.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp.h>
|
||||
|
@ -41,6 +41,9 @@
|
|||
#include <osmocom/sgsn/gprs_sndcp_pcomp.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp_dcomp.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp_comp.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
|
||||
#define DEBUG_IP_PACKETS 0 /* 0=Disabled, 1=Enabled */
|
||||
|
||||
|
@ -66,7 +69,7 @@ static uint16_t calc_ip_csum(uint8_t *data, int len)
|
|||
}
|
||||
|
||||
/* Calculate TCP/IP checksum */
|
||||
static uint16_t calc_tcpip_csum(const void *ctx, uint8_t *packet, int len)
|
||||
static uint16_t calc_tcpip_csum(const void *ctx, const uint8_t *packet, int len)
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint16_t csum;
|
||||
|
@ -84,7 +87,7 @@ static uint16_t calc_tcpip_csum(const void *ctx, uint8_t *packet, int len)
|
|||
}
|
||||
|
||||
/* Show some ip packet details */
|
||||
static void debug_ip_packet(uint8_t *data, int len, int dir, char *info)
|
||||
static void debug_ip_packet(const uint8_t *data, int len, int dir, const char *info)
|
||||
{
|
||||
uint8_t tcp_flags;
|
||||
char flags_debugmsg[256];
|
||||
|
@ -173,7 +176,7 @@ struct sndcp_common_hdr {
|
|||
uint8_t first:1;
|
||||
uint8_t spare:1;
|
||||
#elif OSMO_IS_BIG_ENDIAN
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
|
||||
uint8_t spare:1, first:1, type:1, more:1, nsapi:4;
|
||||
#endif
|
||||
} __attribute__((packed));
|
||||
|
@ -185,7 +188,7 @@ struct sndcp_comp_hdr {
|
|||
uint8_t pcomp:4;
|
||||
uint8_t dcomp:4;
|
||||
#elif OSMO_IS_BIG_ENDIAN
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
|
||||
uint8_t dcomp:4, pcomp:4;
|
||||
#endif
|
||||
} __attribute__((packed));
|
||||
|
@ -198,7 +201,7 @@ struct sndcp_udata_hdr {
|
|||
/* octet 4 */
|
||||
uint8_t npdu_low;
|
||||
#elif OSMO_IS_BIG_ENDIAN
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
|
||||
uint8_t seg_nr:4, npdu_high:4;
|
||||
uint8_t npdu_low;
|
||||
#endif
|
||||
|
@ -221,7 +224,8 @@ struct defrag_queue_entry {
|
|||
LLIST_HEAD(gprs_sndcp_entities);
|
||||
|
||||
/* Check if any compression parameters are set in the sgsn configuration */
|
||||
static inline int any_pcomp_or_dcomp_active(struct sgsn_instance *sgsn) {
|
||||
static inline int any_pcomp_or_dcomp_active(const struct sgsn_instance *sgsn)
|
||||
{
|
||||
if (sgsn->cfg.pcomp_rfc1144.active || sgsn->cfg.pcomp_rfc1144.passive ||
|
||||
sgsn->cfg.dcomp_v42bis.active || sgsn->cfg.dcomp_v42bis.passive)
|
||||
return true;
|
||||
|
@ -260,7 +264,7 @@ static int defrag_enqueue(struct gprs_sndcp_entity *sne, uint8_t seg_nr,
|
|||
}
|
||||
|
||||
/* return if we have all segments of this N-PDU */
|
||||
static int defrag_have_all_segments(struct gprs_sndcp_entity *sne)
|
||||
static int defrag_have_all_segments(const struct gprs_sndcp_entity *sne)
|
||||
{
|
||||
uint32_t seg_needed = 0;
|
||||
unsigned int i;
|
||||
|
@ -275,7 +279,7 @@ static int defrag_have_all_segments(struct gprs_sndcp_entity *sne)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct defrag_queue_entry *defrag_get_seg(struct gprs_sndcp_entity *sne,
|
||||
static struct defrag_queue_entry *defrag_get_seg(const struct gprs_sndcp_entity *sne,
|
||||
uint32_t seg_nr)
|
||||
{
|
||||
struct defrag_queue_entry *dqe;
|
||||
|
@ -289,13 +293,62 @@ static struct defrag_queue_entry *defrag_get_seg(struct gprs_sndcp_entity *sne,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns talloced buffer containing decompressed data, NULL on error. */
|
||||
static uint8_t *decompress_segment(struct gprs_sndcp_entity *sne, void *ctx,
|
||||
const uint8_t *compressed_data, unsigned int compressed_data_len,
|
||||
unsigned int *decompressed_data_len)
|
||||
{
|
||||
int rc;
|
||||
uint8_t *expnd = NULL;
|
||||
*decompressed_data_len = 0;
|
||||
|
||||
#if DEBUG_IP_PACKETS == 1
|
||||
DEBUGP(DSNDCP, "\n");
|
||||
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
|
||||
DEBUGP(DSNDCP, "===================================================\n");
|
||||
#endif
|
||||
|
||||
expnd = talloc_zero_size(ctx, compressed_data_len * MAX_DATADECOMPR_FAC +
|
||||
MAX_HDRDECOMPR_INCR);
|
||||
memcpy(expnd, compressed_data, compressed_data_len);
|
||||
|
||||
/* Apply data decompression */
|
||||
rc = gprs_sndcp_dcomp_expand(expnd, compressed_data_len, sne->defrag.dcomp,
|
||||
sne->defrag.data);
|
||||
if (rc < 0) {
|
||||
LOGP(DSNDCP, LOGL_ERROR,
|
||||
"Data decompression failed!\n");
|
||||
talloc_free(expnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Apply header decompression */
|
||||
rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp, sne->defrag.proto);
|
||||
if (rc < 0) {
|
||||
LOGP(DSNDCP, LOGL_ERROR,
|
||||
"TCP/IP Header decompression failed!\n");
|
||||
talloc_free(expnd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*decompressed_data_len = rc;
|
||||
|
||||
#if DEBUG_IP_PACKETS == 1
|
||||
debug_ip_packet(expnd, *decompressed_data_len, 1, "defrag_segments()");
|
||||
DEBUGP(DSNDCP, "===================================================\n");
|
||||
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
|
||||
DEBUGP(DSNDCP, "\n");
|
||||
#endif
|
||||
return expnd;
|
||||
}
|
||||
|
||||
/* Perform actual defragmentation and create an output packet */
|
||||
static int defrag_segments(struct gprs_sndcp_entity *sne)
|
||||
{
|
||||
struct msgb *msg;
|
||||
unsigned int seg_nr;
|
||||
uint8_t *npdu;
|
||||
int npdu_len;
|
||||
unsigned int npdu_len;
|
||||
int rc;
|
||||
uint8_t *expnd = NULL;
|
||||
|
||||
|
@ -336,53 +389,20 @@ static int defrag_segments(struct gprs_sndcp_entity *sne)
|
|||
* hands it off to the correct GTP tunnel + GGSN via gtp_data_req() */
|
||||
|
||||
/* Decompress packet */
|
||||
#if DEBUG_IP_PACKETS == 1
|
||||
DEBUGP(DSNDCP, " \n");
|
||||
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
|
||||
DEBUGP(DSNDCP, "===================================================\n");
|
||||
#endif
|
||||
if (any_pcomp_or_dcomp_active(sgsn)) {
|
||||
|
||||
expnd = talloc_zero_size(msg, npdu_len * MAX_DATADECOMPR_FAC +
|
||||
MAX_HDRDECOMPR_INCR);
|
||||
memcpy(expnd, npdu, npdu_len);
|
||||
|
||||
/* Apply data decompression */
|
||||
rc = gprs_sndcp_dcomp_expand(expnd, npdu_len, sne->defrag.dcomp,
|
||||
sne->defrag.data);
|
||||
if (rc < 0) {
|
||||
LOGP(DSNDCP, LOGL_ERROR,
|
||||
"Data decompression failed!\n");
|
||||
talloc_free(expnd);
|
||||
return -EIO;
|
||||
expnd = decompress_segment(sne, msg, npdu, npdu_len, &npdu_len);
|
||||
if (!expnd) {
|
||||
rc = -EIO;
|
||||
goto ret_free;
|
||||
}
|
||||
|
||||
/* Apply header decompression */
|
||||
rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp,
|
||||
sne->defrag.proto);
|
||||
if (rc < 0) {
|
||||
LOGP(DSNDCP, LOGL_ERROR,
|
||||
"TCP/IP Header decompression failed!\n");
|
||||
talloc_free(expnd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Modify npu length, expnd is handed directly handed
|
||||
* over to gsn_rx_sndcp_ud_ind(), see below */
|
||||
npdu_len = rc;
|
||||
} else
|
||||
} else {
|
||||
expnd = npdu;
|
||||
#if DEBUG_IP_PACKETS == 1
|
||||
debug_ip_packet(expnd, npdu_len, 1, "defrag_segments()");
|
||||
DEBUGP(DSNDCP, "===================================================\n");
|
||||
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
|
||||
DEBUGP(DSNDCP, " \n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Hand off packet to gtp */
|
||||
rc = sgsn_rx_sndcp_ud_ind(&sne->ra_id, sne->lle->llme->tlli,
|
||||
sne->nsapi, msg, npdu_len, expnd);
|
||||
/* Hand off packet to SGSN (SNDCP SN-UNITDATA.ind), which will forward it to GGSN (GTP): */
|
||||
rc = sndcp_sn_unitdata_ind(sne, msg, npdu_len, expnd);
|
||||
|
||||
ret_free:
|
||||
/* we must free the memory we allocated above; ownership is not transferred
|
||||
* downwards in the call above */
|
||||
msgb_free(msg);
|
||||
|
@ -522,7 +542,7 @@ int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
|
|||
}
|
||||
|
||||
/* Entry point for the SNSM-DEACTIVATE.indication */
|
||||
int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
|
||||
int sndcp_sm_deactivate_ind(const struct gprs_llc_lle *lle, uint8_t nsapi)
|
||||
{
|
||||
struct gprs_sndcp_entity *sne;
|
||||
|
||||
|
@ -545,7 +565,7 @@ int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
|
|||
}
|
||||
|
||||
/* Clean up all gprs_sndcp_entities related to llme (OS#4824) */
|
||||
void gprs_sndcp_sm_deactivate_ind_by_llme(struct gprs_llc_llme *llme)
|
||||
void gprs_sndcp_sm_deactivate_ind_by_llme(const struct gprs_llc_llme *llme)
|
||||
{
|
||||
struct gprs_sndcp_entity *sne, *sne2;
|
||||
|
||||
|
@ -665,7 +685,7 @@ static int sndcp_send_ud_frag(struct sndcp_frag_state *fs,
|
|||
}
|
||||
|
||||
/* Request transmission of a SN-PDU over specified LLC Entity + SAPI */
|
||||
int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
|
||||
int sndcp_sn_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
|
||||
void *mmcontext)
|
||||
{
|
||||
struct gprs_sndcp_entity *sne;
|
||||
|
@ -723,13 +743,14 @@ int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi
|
|||
|
||||
sne = gprs_sndcp_entity_by_lle(lle, nsapi);
|
||||
if (!sne) {
|
||||
LOGP(DSNDCP, LOGL_ERROR, "Cannot find SNDCP Entity\n");
|
||||
LOGP(DSNDCP, LOGL_ERROR, "Cannot find SNDCP Entity (lle=%p, TLLI=%08x, SAPI=%u, NSAPI=%u)\n",
|
||||
lle, lle->llme->tlli, lle->sapi, nsapi);
|
||||
msgb_free(msg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Check if we need to fragment this N-PDU into multiple SN-PDUs */
|
||||
if (msg->len > lle->params.n201_u -
|
||||
if (msg->len > lle->params.n201_u -
|
||||
(sizeof(*sch) + sizeof(*suh) + sizeof(*scomph))) {
|
||||
/* initialize the fragmenter state */
|
||||
fs.msg = msg;
|
||||
|
@ -774,7 +795,7 @@ int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi
|
|||
}
|
||||
|
||||
/* Section 5.1.2.17 LL-UNITDATA.ind */
|
||||
int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
|
||||
int sndcp_ll_unitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
|
||||
uint8_t *hdr, uint16_t len)
|
||||
{
|
||||
struct gprs_sndcp_entity *sne;
|
||||
|
@ -844,63 +865,40 @@ int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
|
|||
LOGP(DSNDCP, LOGL_ERROR, "Short SNDCP N-PDU: %d\n", npdu_len);
|
||||
return -EIO;
|
||||
}
|
||||
/* actually send the N-PDU to the SGSN core code, which then
|
||||
* hands it off to the correct GTP tunnel + GGSN via gtp_data_req() */
|
||||
/* actually send the N-PDU to the SGSN core code (SNDCP SN-UNITDATA.ind) */
|
||||
|
||||
/* Decompress packet */
|
||||
#if DEBUG_IP_PACKETS == 1
|
||||
DEBUGP(DSNDCP, " \n");
|
||||
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
|
||||
DEBUGP(DSNDCP, "===================================================\n");
|
||||
#endif
|
||||
if (any_pcomp_or_dcomp_active(sgsn)) {
|
||||
|
||||
expnd = talloc_zero_size(msg, npdu_len * MAX_DATADECOMPR_FAC +
|
||||
MAX_HDRDECOMPR_INCR);
|
||||
memcpy(expnd, npdu, npdu_len);
|
||||
|
||||
/* Apply data decompression */
|
||||
rc = gprs_sndcp_dcomp_expand(expnd, npdu_len, sne->defrag.dcomp,
|
||||
sne->defrag.data);
|
||||
if (rc < 0) {
|
||||
LOGP(DSNDCP, LOGL_ERROR,
|
||||
"Data decompression failed!\n");
|
||||
talloc_free(expnd);
|
||||
return -EIO;
|
||||
expnd = decompress_segment(sne, msg, npdu, npdu_len, (unsigned int *)&npdu_len);
|
||||
if (!expnd) {
|
||||
rc = -EIO;
|
||||
goto ret_free;
|
||||
}
|
||||
|
||||
/* Apply header decompression */
|
||||
rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp,
|
||||
sne->defrag.proto);
|
||||
if (rc < 0) {
|
||||
LOGP(DSNDCP, LOGL_ERROR,
|
||||
"TCP/IP Header decompression failed!\n");
|
||||
talloc_free(expnd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Modify npu length, expnd is handed directly handed
|
||||
* over to gsn_rx_sndcp_ud_ind(), see below */
|
||||
npdu_len = rc;
|
||||
} else
|
||||
} else {
|
||||
expnd = npdu;
|
||||
#if DEBUG_IP_PACKETS == 1
|
||||
debug_ip_packet(expnd, npdu_len, 1, "sndcp_llunitdata_ind()");
|
||||
DEBUGP(DSNDCP, "===================================================\n");
|
||||
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
|
||||
DEBUGP(DSNDCP, " \n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Hand off packet to gtp */
|
||||
rc = sgsn_rx_sndcp_ud_ind(&sne->ra_id, lle->llme->tlli,
|
||||
sne->nsapi, msg, npdu_len, expnd);
|
||||
rc = sndcp_sn_unitdata_ind(sne, msg, npdu_len, expnd);
|
||||
|
||||
ret_free:
|
||||
if (any_pcomp_or_dcomp_active(sgsn))
|
||||
talloc_free(expnd);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* 5.1.1.4 SN-UNITDATA.indication
|
||||
* Called by SNDCP when it has received/re-assembled a N-PDU
|
||||
*/
|
||||
int sndcp_sn_unitdata_ind(struct gprs_sndcp_entity *sne,
|
||||
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu)
|
||||
{
|
||||
/* Hand it off N-PDU to the correct GTP tunnel + GGSN: */
|
||||
return sgsn_gtp_data_req(&sne->ra_id, sne->lle->llme->tlli,
|
||||
sne->nsapi, msg, npdu_len, npdu);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Section 5.1.2.1 LL-RESET.ind */
|
||||
static int sndcp_ll_reset_ind(struct gprs_sndcp_entity *se)
|
||||
|
@ -1056,7 +1054,7 @@ int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi)
|
|||
|
||||
/* Handle header compression entites */
|
||||
static int handle_pcomp_entities(struct gprs_sndcp_comp_field *comp_field,
|
||||
struct gprs_llc_lle *lle)
|
||||
const struct gprs_llc_lle *lle)
|
||||
{
|
||||
/* Note: This functions also transforms the comp_field into its
|
||||
* echo form (strips comp values, resets propose bit etc...)
|
||||
|
@ -1106,7 +1104,7 @@ static int handle_pcomp_entities(struct gprs_sndcp_comp_field *comp_field,
|
|||
|
||||
/* Hanle data compression entites */
|
||||
static int handle_dcomp_entities(struct gprs_sndcp_comp_field *comp_field,
|
||||
struct gprs_llc_lle *lle)
|
||||
const struct gprs_llc_lle *lle)
|
||||
{
|
||||
/* See note in handle_pcomp_entities() */
|
||||
|
||||
|
@ -1148,7 +1146,7 @@ static int handle_dcomp_entities(struct gprs_sndcp_comp_field *comp_field,
|
|||
* (See also: TS 144 065, Section 6.8 XID parameter negotiation) */
|
||||
int sndcp_sn_xid_ind(struct gprs_llc_xid_field *xid_field_indication,
|
||||
struct gprs_llc_xid_field *xid_field_response,
|
||||
struct gprs_llc_lle *lle)
|
||||
const struct gprs_llc_lle *lle)
|
||||
{
|
||||
/* Note: This function computes the SNDCP-XID response that is sent
|
||||
* back to the ms when a ms originated XID is received. The
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <osmocom/gsupclient/gsup_client.h>
|
||||
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
|
||||
|
@ -48,8 +48,6 @@
|
|||
(gsup)->imsi, \
|
||||
## args)
|
||||
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
LLIST_HEAD(_gprs_subscribers);
|
||||
struct llist_head * const gprs_subscribers = &_gprs_subscribers;
|
||||
|
||||
|
@ -378,7 +376,8 @@ static void gprs_subscr_gsup_insert_data(struct gprs_subscr *subscr,
|
|||
}
|
||||
|
||||
OSMO_ASSERT(pdp_data != NULL);
|
||||
pdp_data->pdp_type = pdp_info->pdp_type;
|
||||
pdp_data->pdp_type_org = pdp_info->pdp_type_org;
|
||||
pdp_data->pdp_type_nr = pdp_info->pdp_type_nr;
|
||||
osmo_apn_to_str(pdp_data->apn_str,
|
||||
pdp_info->apn_enc, pdp_info->apn_enc_len);
|
||||
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
/* GGSN context (peer) */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_sm.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
|
||||
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc)
|
||||
{
|
||||
bool pending = osmo_timer_pending(&ggc->echo_timer);
|
||||
|
||||
/* Only enable if allowed by policy and at least 1 pdp ctx exists against ggsn */
|
||||
if (!llist_empty(&ggc->pdp_list) && ggc->echo_interval) {
|
||||
if (!pending)
|
||||
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
|
||||
} else {
|
||||
if (pending)
|
||||
osmo_timer_del(&ggc->echo_timer);
|
||||
}
|
||||
}
|
||||
|
||||
/* GGSN contexts */
|
||||
static void echo_timer_cb(void *data)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc = (struct sgsn_ggsn_ctx *) data;
|
||||
sgsn_ggsn_echo_req(ggc);
|
||||
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
|
||||
}
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(struct sgsn_instance *sgsn, uint32_t id)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc;
|
||||
|
||||
ggc = talloc_zero(sgsn, struct sgsn_ggsn_ctx);
|
||||
if (!ggc)
|
||||
return NULL;
|
||||
|
||||
ggc->id = id;
|
||||
ggc->gtp_version = 1;
|
||||
ggc->remote_restart_ctr = -1;
|
||||
/* if we are called from config file parse, this gsn doesn't exist yet */
|
||||
ggc->gsn = sgsn->gsn;
|
||||
INIT_LLIST_HEAD(&ggc->pdp_list);
|
||||
osmo_timer_setup(&ggc->echo_timer, echo_timer_cb, ggc);
|
||||
llist_add(&ggc->list, &sgsn->ggsn_list);
|
||||
|
||||
return ggc;
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc)
|
||||
{
|
||||
OSMO_ASSERT(llist_empty(&ggc->pdp_list));
|
||||
llist_del(&ggc->list);
|
||||
talloc_free(ggc);
|
||||
}
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(struct sgsn_instance *sgsn, uint32_t id)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc;
|
||||
|
||||
llist_for_each_entry(ggc, &sgsn->ggsn_list, list) {
|
||||
if (id == ggc->id)
|
||||
return ggc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct sgsn_instance *sgsn, struct in_addr *addr)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc;
|
||||
|
||||
llist_for_each_entry(ggc, &sgsn->ggsn_list, list) {
|
||||
if (!memcmp(addr, &ggc->remote_addr, sizeof(*addr)))
|
||||
return ggc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(struct sgsn_instance *sgsn, uint32_t id)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc;
|
||||
|
||||
ggc = sgsn_ggsn_ctx_by_id(sgsn, id);
|
||||
if (!ggc)
|
||||
ggc = sgsn_ggsn_ctx_alloc(sgsn, id);
|
||||
return ggc;
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx)
|
||||
{
|
||||
/* the MM context can be deleted while the GGSN is not reachable or
|
||||
* if has been crashed. */
|
||||
if (pctx->mm && pctx->mm->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL) {
|
||||
gsm48_tx_gsm_deact_pdp_req(pctx, GSM_CAUSE_NET_FAIL, true);
|
||||
sgsn_ggsn_ctx_remove_pdp(pctx->ggsn, pctx);
|
||||
} else {
|
||||
/* FIXME: GPRS paging in case MS is SUSPENDED */
|
||||
LOGPDPCTXP(LOGL_NOTICE, pctx, "Hard-dropping PDP ctx due to GGSN "
|
||||
"recovery\n");
|
||||
/* FIXME: how to tell this to libgtp? */
|
||||
sgsn_pdp_ctx_free(pctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* High-level function to be called in case a GGSN has disappeared or
|
||||
* otherwise lost state (recovery procedure). It will detach all related pdp ctx
|
||||
* from a ggsn and communicate deact to MS. Optionally (!NULL), one pdp ctx can
|
||||
* be kept alive to allow handling later message which contained the Recovery IE. */
|
||||
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
struct sgsn_pdp_ctx *pdp, *pdp2;
|
||||
llist_for_each_entry_safe(pdp, pdp2, &ggsn->pdp_list, ggsn_list) {
|
||||
if (pdp == except)
|
||||
continue;
|
||||
sgsn_ggsn_ctx_drop_pdp(pdp);
|
||||
num++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn)
|
||||
{
|
||||
return sgsn_ggsn_ctx_drop_all_pdp_except(ggsn, NULL);
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
llist_add(&pdp->ggsn_list, &ggc->pdp_list);
|
||||
sgsn_ggsn_ctx_check_echo_timer(ggc);
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
llist_del(&pdp->ggsn_list);
|
||||
sgsn_ggsn_ctx_check_echo_timer(ggc);
|
||||
if (pdp->destroy_ggsn)
|
||||
sgsn_ggsn_ctx_free(pdp->ggsn);
|
||||
pdp->ggsn = NULL;
|
||||
/* Drop references to libgtp since the conn is down */
|
||||
if (pdp->lib)
|
||||
pdp_freepdp(pdp->lib);
|
||||
pdp->lib = NULL;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* TS 29.060 § 7.5.14 RAN Information Management Messages */
|
||||
/*
|
||||
* (C) 2021 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
|
||||
* (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0+
|
||||
|
@ -26,8 +26,6 @@
|
|||
#include <osmocom/sgsn/gtp_mme.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
static bool _eutran_tai_equal(const struct osmo_eutran_tai *t1, const struct osmo_eutran_tai *t2)
|
||||
{
|
||||
return t1->mcc == t2->mcc &&
|
||||
|
@ -39,7 +37,7 @@ static bool _eutran_tai_equal(const struct osmo_eutran_tai *t1, const struct osm
|
|||
struct sgsn_mme_ctx *sgsn_mme_ctx_alloc(struct sgsn_instance *sgsn, const char *name)
|
||||
{
|
||||
struct sgsn_mme_ctx *mme;
|
||||
mme = talloc_zero(tall_sgsn_ctx, struct sgsn_mme_ctx);
|
||||
mme = talloc_zero(sgsn, struct sgsn_mme_ctx);
|
||||
if (!mme)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* GPRS SGSN functionality */
|
||||
/* Mobility Management context */
|
||||
|
||||
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
|
@ -27,6 +27,8 @@
|
|||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
#include <osmocom/core/backtrace.h>
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/ports.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
|
@ -36,7 +38,7 @@
|
|||
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_sm.h>
|
||||
|
@ -47,22 +49,16 @@
|
|||
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
|
||||
#include <pdp.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
|
||||
#define GPRS_LLME_CHECK_TICK 30
|
||||
|
||||
extern struct sgsn_instance *sgsn;
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
LLIST_HEAD(sgsn_mm_ctxts);
|
||||
LLIST_HEAD(sgsn_ggsn_ctxts);
|
||||
LLIST_HEAD(sgsn_apn_ctxts);
|
||||
LLIST_HEAD(sgsn_pdp_ctxts);
|
||||
#include "../../config.h"
|
||||
|
||||
const struct value_string sgsn_ran_type_names[] = {
|
||||
{ MM_CTX_T_GERAN_Gb, "GPRS/EDGE via Gb" },
|
||||
|
@ -95,66 +91,12 @@ static const struct rate_ctr_group_desc mmctx_ctrg_desc = {
|
|||
.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
|
||||
};
|
||||
|
||||
static const struct rate_ctr_desc pdpctx_ctr_description[] = {
|
||||
{ "udata:packets:in", "User Data Messages ( In)" },
|
||||
{ "udata:packets:out", "User Data Messages (Out)" },
|
||||
{ "udata:bytes:in", "User Data Bytes ( In)" },
|
||||
{ "udata:bytes:out", "User Data Bytes (Out)" },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc pdpctx_ctrg_desc = {
|
||||
.group_name_prefix = "sgsn:pdpctx",
|
||||
.group_description = "SGSN PDP Context Statistics",
|
||||
.num_ctr = ARRAY_SIZE(pdpctx_ctr_description),
|
||||
.ctr_desc = pdpctx_ctr_description,
|
||||
.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
|
||||
};
|
||||
|
||||
static const struct rate_ctr_desc sgsn_ctr_description[] = {
|
||||
{ "llc:dl_bytes", "Count sent LLC bytes before giving it to the bssgp layer" },
|
||||
{ "llc:ul_bytes", "Count successful received LLC bytes (encrypt & fcs correct)" },
|
||||
{ "llc:dl_packets", "Count successful sent LLC packets before giving it to the bssgp layer" },
|
||||
{ "llc:ul_packets", "Count successful received LLC packets (encrypt & fcs correct)" },
|
||||
{ "gprs:attach_requested", "Received attach requests" },
|
||||
{ "gprs:attach_accepted", "Sent attach accepts" },
|
||||
{ "gprs:attach_rejected", "Sent attach rejects" },
|
||||
{ "gprs:detach_requested", "Received detach requests" },
|
||||
{ "gprs:detach_acked", "Sent detach acks" },
|
||||
{ "gprs:routing_area_requested", "Received routing area requests" },
|
||||
{ "gprs:routing_area_requested", "Sent routing area acks" },
|
||||
{ "gprs:routing_area_requested", "Sent routing area rejects" },
|
||||
{ "pdp:activate_requested", "Received activate requests" },
|
||||
{ "pdp:activate_rejected", "Sent activate rejects" },
|
||||
{ "pdp:activate_accepted", "Sent activate accepts" },
|
||||
{ "pdp:request_activated", "unused" },
|
||||
{ "pdp:request_activate_rejected", "unused" },
|
||||
{ "pdp:modify_requested", "unused" },
|
||||
{ "pdp:modify_accepted", "unused" },
|
||||
{ "pdp:dl_deactivate_requested", "Sent deactivate requests" },
|
||||
{ "pdp:dl_deactivate_accepted", "Sent deactivate accepted" },
|
||||
{ "pdp:ul_deactivate_requested", "Received deactivate requests" },
|
||||
{ "pdp:ul_deactivate_accepted", "Received deactivate accepts" },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc sgsn_ctrg_desc = {
|
||||
"sgsn",
|
||||
"SGSN Overall Statistics",
|
||||
OSMO_STATS_CLASS_GLOBAL,
|
||||
ARRAY_SIZE(sgsn_ctr_description),
|
||||
sgsn_ctr_description,
|
||||
};
|
||||
|
||||
void sgsn_rate_ctr_init() {
|
||||
sgsn->rate_ctrs = rate_ctr_group_alloc(tall_sgsn_ctx, &sgsn_ctrg_desc, 0);
|
||||
OSMO_ASSERT(sgsn->rate_ctrs);
|
||||
}
|
||||
|
||||
/* look-up an SGSN MM context based on Iu UE context (struct ue_conn_ctx)*/
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx)
|
||||
{
|
||||
struct sgsn_mm_ctx *ctx;
|
||||
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
|
||||
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
|
||||
if (ctx->ran_type == MM_CTX_T_UTRAN_Iu
|
||||
&& uectx == ctx->iu.ue_ctx)
|
||||
return ctx;
|
||||
|
@ -169,7 +111,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
|
|||
{
|
||||
struct sgsn_mm_ctx *ctx;
|
||||
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
|
||||
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
|
||||
if ((tlli == ctx->gb.tlli || tlli == ctx->gb.tlli_new) &&
|
||||
gprs_ra_id_equals(raid, &ctx->ra))
|
||||
return ctx;
|
||||
|
@ -193,7 +135,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
|
|||
if (tlli_type != TLLI_FOREIGN && tlli_type != TLLI_LOCAL)
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
|
||||
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
|
||||
if ((gprs_tmsi2tlli(ctx->p_tmsi, tlli_type) == tlli ||
|
||||
gprs_tmsi2tlli(ctx->p_tmsi_old, tlli_type) == tlli) &&
|
||||
gprs_ra_id_equals(raid, &ctx->ra))
|
||||
|
@ -207,7 +149,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t p_tmsi)
|
|||
{
|
||||
struct sgsn_mm_ctx *ctx;
|
||||
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
|
||||
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
|
||||
if (p_tmsi == ctx->p_tmsi ||
|
||||
(ctx->p_tmsi_old && ctx->p_tmsi_old == p_tmsi))
|
||||
return ctx;
|
||||
|
@ -219,7 +161,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi)
|
|||
{
|
||||
struct sgsn_mm_ctx *ctx;
|
||||
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
|
||||
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
|
||||
if (!strcmp(imsi, ctx->imsi))
|
||||
return ctx;
|
||||
}
|
||||
|
@ -261,7 +203,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t rate_ctr_id)
|
|||
|
||||
INIT_LLIST_HEAD(&ctx->pdp_list);
|
||||
|
||||
llist_add(&ctx->list, &sgsn_mm_ctxts);
|
||||
llist_add(&ctx->list, &sgsn->mm_list);
|
||||
|
||||
return ctx;
|
||||
|
||||
|
@ -432,288 +374,6 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* you don't want to use this directly, call sgsn_create_pdp_ctx() */
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
|
||||
struct sgsn_ggsn_ctx *ggsn,
|
||||
uint8_t nsapi)
|
||||
{
|
||||
struct sgsn_pdp_ctx *pdp;
|
||||
|
||||
pdp = sgsn_pdp_ctx_by_nsapi(mm, nsapi);
|
||||
if (pdp)
|
||||
return NULL;
|
||||
|
||||
pdp = talloc_zero(tall_sgsn_ctx, struct sgsn_pdp_ctx);
|
||||
if (!pdp)
|
||||
return NULL;
|
||||
|
||||
pdp->mm = mm;
|
||||
pdp->ggsn = ggsn;
|
||||
pdp->nsapi = nsapi;
|
||||
pdp->ctrg = rate_ctr_group_alloc(pdp, &pdpctx_ctrg_desc, nsapi);
|
||||
if (!pdp->ctrg) {
|
||||
LOGPDPCTXP(LOGL_ERROR, pdp, "Error allocation counter group\n");
|
||||
talloc_free(pdp);
|
||||
return NULL;
|
||||
}
|
||||
llist_add(&pdp->list, &mm->pdp_list);
|
||||
sgsn_ggsn_ctx_add_pdp(pdp->ggsn, pdp);
|
||||
llist_add(&pdp->g_list, &sgsn_pdp_ctxts);
|
||||
|
||||
return pdp;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will not trigger any GSM DEACT PDP ACK messages, so you
|
||||
* probably want to call sgsn_delete_pdp_ctx() instead if the connection
|
||||
* isn't detached already.
|
||||
*/
|
||||
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
struct sgsn_signal_data sig_data;
|
||||
|
||||
OSMO_ASSERT(pdp->mm != NULL);
|
||||
|
||||
/* There might still be pending callbacks in libgtp. So the parts of
|
||||
* this object relevant to GTP need to remain intact in this case. */
|
||||
|
||||
LOGPDPCTXP(LOGL_INFO, pdp, "Forcing release of PDP context\n");
|
||||
|
||||
if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
|
||||
/* Force the deactivation of the SNDCP layer */
|
||||
if (pdp->mm->gb.llme)
|
||||
sndcp_sm_deactivate_ind(&pdp->mm->gb.llme->lle[pdp->sapi], pdp->nsapi);
|
||||
}
|
||||
|
||||
memset(&sig_data, 0, sizeof(sig_data));
|
||||
sig_data.pdp = pdp;
|
||||
osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_TERMINATE, &sig_data);
|
||||
|
||||
/* Detach from MM context */
|
||||
pdp_ctx_detach_mm_ctx(pdp);
|
||||
if (pdp->ggsn)
|
||||
sgsn_delete_pdp_ctx(pdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't call this function directly unless you know what you are doing.
|
||||
* In normal conditions use sgsn_delete_pdp_ctx and in unspecified or
|
||||
* implementation dependent abnormal ones sgsn_pdp_ctx_terminate.
|
||||
*/
|
||||
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
struct sgsn_signal_data sig_data;
|
||||
|
||||
memset(&sig_data, 0, sizeof(sig_data));
|
||||
sig_data.pdp = pdp;
|
||||
osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_FREE, &sig_data);
|
||||
|
||||
if (osmo_timer_pending(&pdp->timer)) {
|
||||
LOGPDPCTXP(LOGL_ERROR, pdp, "Freeing PDP ctx with timer %u pending\n", pdp->T);
|
||||
osmo_timer_del(&pdp->timer);
|
||||
}
|
||||
|
||||
rate_ctr_group_free(pdp->ctrg);
|
||||
if (pdp->mm)
|
||||
llist_del(&pdp->list);
|
||||
if (pdp->ggsn)
|
||||
sgsn_ggsn_ctx_remove_pdp(pdp->ggsn, pdp);
|
||||
llist_del(&pdp->g_list);
|
||||
|
||||
/* _if_ we still have a library handle, at least set it to NULL
|
||||
* to avoid any dereferences of the now-deleted PDP context from
|
||||
* sgsn_libgtp:cb_data_ind() */
|
||||
if (pdp->lib) {
|
||||
struct pdp_t *lib = pdp->lib;
|
||||
LOGPDPCTXP(LOGL_NOTICE, pdp, "freeing PDP context that still "
|
||||
"has a libgtp handle attached to it, this shouldn't "
|
||||
"happen!\n");
|
||||
osmo_generate_backtrace();
|
||||
lib->priv = NULL;
|
||||
}
|
||||
|
||||
talloc_free(pdp);
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc)
|
||||
{
|
||||
bool pending = osmo_timer_pending(&ggc->echo_timer);
|
||||
|
||||
/* Only enable if allowed by policy and at least 1 pdp ctx exists against ggsn */
|
||||
if (!llist_empty(&ggc->pdp_list) && ggc->echo_interval) {
|
||||
if (!pending)
|
||||
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
|
||||
} else {
|
||||
if (pending)
|
||||
osmo_timer_del(&ggc->echo_timer);
|
||||
}
|
||||
}
|
||||
|
||||
/* GGSN contexts */
|
||||
static void echo_timer_cb(void *data)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc = (struct sgsn_ggsn_ctx *) data;
|
||||
sgsn_ggsn_echo_req(ggc);
|
||||
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
|
||||
}
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc;
|
||||
|
||||
ggc = talloc_zero(tall_sgsn_ctx, struct sgsn_ggsn_ctx);
|
||||
if (!ggc)
|
||||
return NULL;
|
||||
|
||||
ggc->id = id;
|
||||
ggc->gtp_version = 1;
|
||||
ggc->remote_restart_ctr = -1;
|
||||
/* if we are called from config file parse, this gsn doesn't exist yet */
|
||||
ggc->gsn = sgsn->gsn;
|
||||
INIT_LLIST_HEAD(&ggc->pdp_list);
|
||||
osmo_timer_setup(&ggc->echo_timer, echo_timer_cb, ggc);
|
||||
llist_add(&ggc->list, &sgsn_ggsn_ctxts);
|
||||
|
||||
return ggc;
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc)
|
||||
{
|
||||
OSMO_ASSERT(llist_empty(&ggc->pdp_list));
|
||||
llist_del(&ggc->list);
|
||||
talloc_free(ggc);
|
||||
}
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc;
|
||||
|
||||
llist_for_each_entry(ggc, &sgsn_ggsn_ctxts, list) {
|
||||
if (id == ggc->id)
|
||||
return ggc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc;
|
||||
|
||||
llist_for_each_entry(ggc, &sgsn_ggsn_ctxts, list) {
|
||||
if (!memcmp(addr, &ggc->remote_addr, sizeof(*addr)))
|
||||
return ggc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggc;
|
||||
|
||||
ggc = sgsn_ggsn_ctx_by_id(id);
|
||||
if (!ggc)
|
||||
ggc = sgsn_ggsn_ctx_alloc(id);
|
||||
return ggc;
|
||||
}
|
||||
|
||||
/* APN contexts */
|
||||
|
||||
static struct apn_ctx *sgsn_apn_ctx_alloc(const char *ap_name, const char *imsi_prefix)
|
||||
{
|
||||
struct apn_ctx *actx;
|
||||
|
||||
actx = talloc_zero(tall_sgsn_ctx, struct apn_ctx);
|
||||
if (!actx)
|
||||
return NULL;
|
||||
actx->name = talloc_strdup(actx, ap_name);
|
||||
actx->imsi_prefix = talloc_strdup(actx, imsi_prefix);
|
||||
|
||||
llist_add_tail(&actx->list, &sgsn_apn_ctxts);
|
||||
|
||||
return actx;
|
||||
}
|
||||
|
||||
void sgsn_apn_ctx_free(struct apn_ctx *actx)
|
||||
{
|
||||
llist_del(&actx->list);
|
||||
talloc_free(actx);
|
||||
}
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi)
|
||||
{
|
||||
struct apn_ctx *actx;
|
||||
struct apn_ctx *found_actx = NULL;
|
||||
size_t imsi_prio = 0;
|
||||
size_t name_prio = 0;
|
||||
size_t name_req_len = strlen(name);
|
||||
|
||||
llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
|
||||
size_t name_ref_len, imsi_ref_len;
|
||||
const char *name_ref_start, *name_match_start;
|
||||
|
||||
imsi_ref_len = strlen(actx->imsi_prefix);
|
||||
if (strncmp(actx->imsi_prefix, imsi, imsi_ref_len) != 0)
|
||||
continue;
|
||||
|
||||
if (imsi_ref_len < imsi_prio)
|
||||
continue;
|
||||
|
||||
/* IMSI matches */
|
||||
|
||||
name_ref_start = &actx->name[0];
|
||||
if (name_ref_start[0] == '*') {
|
||||
/* Suffix match */
|
||||
name_ref_start += 1;
|
||||
name_ref_len = strlen(name_ref_start);
|
||||
if (name_ref_len > name_req_len)
|
||||
continue;
|
||||
} else {
|
||||
name_ref_len = strlen(name_ref_start);
|
||||
if (name_ref_len != name_req_len)
|
||||
continue;
|
||||
}
|
||||
|
||||
name_match_start = name + (name_req_len - name_ref_len);
|
||||
if (strcasecmp(name_match_start, name_ref_start) != 0)
|
||||
continue;
|
||||
|
||||
/* IMSI and name match */
|
||||
|
||||
if (imsi_ref_len == imsi_prio && name_ref_len < name_prio)
|
||||
/* Lower priority, skip */
|
||||
continue;
|
||||
|
||||
imsi_prio = imsi_ref_len;
|
||||
name_prio = name_ref_len;
|
||||
found_actx = actx;
|
||||
}
|
||||
return found_actx;
|
||||
}
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix)
|
||||
{
|
||||
struct apn_ctx *actx;
|
||||
|
||||
llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
|
||||
if (strcasecmp(name, actx->name) == 0 &&
|
||||
strcasecmp(imsi_prefix, actx->imsi_prefix) == 0)
|
||||
return actx;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix)
|
||||
{
|
||||
struct apn_ctx *actx;
|
||||
|
||||
actx = sgsn_apn_ctx_by_name(name, imsi_prefix);
|
||||
if (!actx)
|
||||
actx = sgsn_apn_ctx_alloc(name, imsi_prefix);
|
||||
|
||||
return actx;
|
||||
}
|
||||
|
||||
uint32_t sgsn_alloc_ptmsi(void)
|
||||
{
|
||||
struct sgsn_mm_ctx *mm;
|
||||
|
@ -749,7 +409,7 @@ restart:
|
|||
goto restart;
|
||||
}
|
||||
|
||||
llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
|
||||
llist_for_each_entry(mm, &sgsn->mm_list, list) {
|
||||
if (mm->p_tmsi == ptmsi) {
|
||||
if (!max_retries--)
|
||||
goto failed;
|
||||
|
@ -764,64 +424,6 @@ failed:
|
|||
return GSM_RESERVED_TMSI;
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx)
|
||||
{
|
||||
/* the MM context can be deleted while the GGSN is not reachable or
|
||||
* if has been crashed. */
|
||||
if (pctx->mm && pctx->mm->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL) {
|
||||
gsm48_tx_gsm_deact_pdp_req(pctx, GSM_CAUSE_NET_FAIL, true);
|
||||
sgsn_ggsn_ctx_remove_pdp(pctx->ggsn, pctx);
|
||||
} else {
|
||||
/* FIXME: GPRS paging in case MS is SUSPENDED */
|
||||
LOGPDPCTXP(LOGL_NOTICE, pctx, "Hard-dropping PDP ctx due to GGSN "
|
||||
"recovery\n");
|
||||
/* FIXME: how to tell this to libgtp? */
|
||||
sgsn_pdp_ctx_free(pctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* High-level function to be called in case a GGSN has disappeared or
|
||||
* otherwise lost state (recovery procedure). It will detach all related pdp ctx
|
||||
* from a ggsn and communicate deact to MS. Optionally (!NULL), one pdp ctx can
|
||||
* be kept alive to allow handling later message which contained the Recovery IE. */
|
||||
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
struct sgsn_pdp_ctx *pdp, *pdp2;
|
||||
llist_for_each_entry_safe(pdp, pdp2, &ggsn->pdp_list, ggsn_list) {
|
||||
if (pdp == except)
|
||||
continue;
|
||||
sgsn_ggsn_ctx_drop_pdp(pdp);
|
||||
num++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn)
|
||||
{
|
||||
return sgsn_ggsn_ctx_drop_all_pdp_except(ggsn, NULL);
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
llist_add(&pdp->ggsn_list, &ggc->pdp_list);
|
||||
sgsn_ggsn_ctx_check_echo_timer(ggc);
|
||||
}
|
||||
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
llist_del(&pdp->ggsn_list);
|
||||
sgsn_ggsn_ctx_check_echo_timer(ggc);
|
||||
if (pdp->destroy_ggsn)
|
||||
sgsn_ggsn_ctx_free(pdp->ggsn);
|
||||
pdp->ggsn = NULL;
|
||||
/* Drop references to libgtp since the conn is down */
|
||||
if (pdp->lib)
|
||||
pdp_freepdp(pdp->lib);
|
||||
pdp->lib = NULL;
|
||||
}
|
||||
|
||||
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
|
||||
{
|
||||
OSMO_ASSERT(mmctx != NULL);
|
||||
|
@ -896,7 +498,7 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
|
|||
insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
|
||||
continue;
|
||||
}
|
||||
if (!llist_empty(&sgsn_apn_ctxts)) {
|
||||
if (!llist_empty(&sgsn->apn_list)) {
|
||||
apn_ctx = sgsn_apn_ctx_match(req_apn_str, mmctx->imsi);
|
||||
/* Not configured */
|
||||
if (apn_ctx == NULL)
|
||||
|
@ -949,13 +551,13 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
|
|||
|
||||
if (apn_ctx != NULL) {
|
||||
ggsn = apn_ctx->ggsn;
|
||||
} else if (llist_empty(&sgsn_apn_ctxts)) {
|
||||
} else if (llist_empty(&sgsn->apn_list)) {
|
||||
/* No configuration -> use GGSN 0 */
|
||||
ggsn = sgsn_ggsn_ctx_by_id(0);
|
||||
ggsn = sgsn_ggsn_ctx_by_id(sgsn, 0);
|
||||
} else if (allow_any_apn &&
|
||||
(selected_apn_str == NULL || strlen(selected_apn_str) == 0)) {
|
||||
/* No APN given and no default configuration -> Use GGSN 0 */
|
||||
ggsn = sgsn_ggsn_ctx_by_id(0);
|
||||
ggsn = sgsn_ggsn_ctx_by_id(sgsn, 0);
|
||||
} else {
|
||||
/* No matching configuration found */
|
||||
LOGMMCTXP(LOGL_NOTICE, mmctx,
|
||||
|
@ -980,72 +582,3 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
|
|||
|
||||
return ggsn;
|
||||
}
|
||||
|
||||
static void sgsn_llme_cleanup_free(struct gprs_llc_llme *llme)
|
||||
{
|
||||
struct sgsn_mm_ctx *mmctx = NULL;
|
||||
|
||||
llist_for_each_entry(mmctx, &sgsn_mm_ctxts, list) {
|
||||
if (llme == mmctx->gb.llme) {
|
||||
gsm0408_gprs_access_cancelled(mmctx, SGSN_ERROR_CAUSE_NONE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No MM context found */
|
||||
LOGP(DGPRS, LOGL_INFO, "Deleting orphaned LLME, TLLI 0x%08x\n",
|
||||
llme->tlli);
|
||||
gprs_llgmm_unassign(llme);
|
||||
}
|
||||
|
||||
static void sgsn_llme_check_cb(void *data_)
|
||||
{
|
||||
struct gprs_llc_llme *llme, *llme_tmp;
|
||||
struct timespec now_tp;
|
||||
time_t now, age;
|
||||
time_t max_age = gprs_max_time_to_idle();
|
||||
|
||||
int rc;
|
||||
|
||||
rc = osmo_clock_gettime(CLOCK_MONOTONIC, &now_tp);
|
||||
OSMO_ASSERT(rc >= 0);
|
||||
now = now_tp.tv_sec;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Checking for inactive LLMEs, time = %u\n", (unsigned)now);
|
||||
|
||||
llist_for_each_entry_safe(llme, llme_tmp, &gprs_llc_llmes, list) {
|
||||
if (llme->age_timestamp == GPRS_LLME_RESET_AGE)
|
||||
llme->age_timestamp = now;
|
||||
|
||||
age = now - llme->age_timestamp;
|
||||
|
||||
if (age > max_age || age < 0) {
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Inactivity timeout for TLLI 0x%08x, age %d\n",
|
||||
llme->tlli, (int)age);
|
||||
sgsn_llme_cleanup_free(llme);
|
||||
}
|
||||
}
|
||||
|
||||
osmo_timer_schedule(&sgsn->llme_timer, GPRS_LLME_CHECK_TICK, 0);
|
||||
}
|
||||
|
||||
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx)
|
||||
{
|
||||
struct sgsn_instance *inst;
|
||||
inst = talloc_zero(talloc_ctx, struct sgsn_instance);
|
||||
inst->cfg.gtp_statedir = talloc_strdup(inst, "./");
|
||||
inst->cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
|
||||
inst->cfg.require_authentication = true; /* only applies if auth_policy is REMOTE */
|
||||
inst->cfg.gsup_server_port = OSMO_GSUP_PORT;
|
||||
|
||||
INIT_LLIST_HEAD(&inst->mme_list);
|
||||
return inst;
|
||||
}
|
||||
|
||||
void sgsn_inst_init(struct sgsn_instance *sgsn)
|
||||
{
|
||||
osmo_timer_setup(&sgsn->llme_timer, sgsn_llme_check_cb, NULL);
|
||||
osmo_timer_schedule(&sgsn->llme_timer, GPRS_LLME_CHECK_TICK, 0);
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/* PDP context functionality */
|
||||
|
||||
/* (C) 2009 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 <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/signal.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/gprs_llc_xid.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_sm.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
|
||||
static const struct rate_ctr_desc pdpctx_ctr_description[] = {
|
||||
{ "udata:packets:in", "User Data Messages ( In)" },
|
||||
{ "udata:packets:out", "User Data Messages (Out)" },
|
||||
{ "udata:bytes:in", "User Data Bytes ( In)" },
|
||||
{ "udata:bytes:out", "User Data Bytes (Out)" },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc pdpctx_ctrg_desc = {
|
||||
.group_name_prefix = "sgsn:pdpctx",
|
||||
.group_description = "SGSN PDP Context Statistics",
|
||||
.num_ctr = ARRAY_SIZE(pdpctx_ctr_description),
|
||||
.ctr_desc = pdpctx_ctr_description,
|
||||
.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
|
||||
};
|
||||
|
||||
/* you don't want to use this directly, call sgsn_create_pdp_ctx() */
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
|
||||
struct sgsn_ggsn_ctx *ggsn,
|
||||
uint8_t nsapi)
|
||||
{
|
||||
struct sgsn_pdp_ctx *pdp;
|
||||
|
||||
pdp = sgsn_pdp_ctx_by_nsapi(mm, nsapi);
|
||||
if (pdp)
|
||||
return NULL;
|
||||
|
||||
pdp = talloc_zero(sgsn, struct sgsn_pdp_ctx);
|
||||
if (!pdp)
|
||||
return NULL;
|
||||
|
||||
pdp->mm = mm;
|
||||
pdp->ggsn = ggsn;
|
||||
pdp->nsapi = nsapi;
|
||||
pdp->ctrg = rate_ctr_group_alloc(pdp, &pdpctx_ctrg_desc, nsapi);
|
||||
if (!pdp->ctrg) {
|
||||
LOGPDPCTXP(LOGL_ERROR, pdp, "Error allocation counter group\n");
|
||||
talloc_free(pdp);
|
||||
return NULL;
|
||||
}
|
||||
llist_add(&pdp->list, &mm->pdp_list);
|
||||
sgsn_ggsn_ctx_add_pdp(pdp->ggsn, pdp);
|
||||
llist_add(&pdp->g_list, &sgsn->pdp_list);
|
||||
|
||||
return pdp;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will not trigger any GSM DEACT PDP ACK messages, so you
|
||||
* probably want to call sgsn_delete_pdp_ctx() instead if the connection
|
||||
* isn't detached already.
|
||||
*/
|
||||
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
struct sgsn_signal_data sig_data;
|
||||
|
||||
OSMO_ASSERT(pdp->mm != NULL);
|
||||
|
||||
/* There might still be pending callbacks in libgtp. So the parts of
|
||||
* this object relevant to GTP need to remain intact in this case. */
|
||||
|
||||
LOGPDPCTXP(LOGL_INFO, pdp, "Forcing release of PDP context\n");
|
||||
|
||||
if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
|
||||
/* Force the deactivation of the SNDCP layer */
|
||||
if (pdp->mm->gb.llme)
|
||||
sndcp_sm_deactivate_ind(&pdp->mm->gb.llme->lle[pdp->sapi], pdp->nsapi);
|
||||
}
|
||||
|
||||
memset(&sig_data, 0, sizeof(sig_data));
|
||||
sig_data.pdp = pdp;
|
||||
osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_TERMINATE, &sig_data);
|
||||
|
||||
/* Detach from MM context */
|
||||
pdp_ctx_detach_mm_ctx(pdp);
|
||||
if (pdp->ggsn)
|
||||
sgsn_delete_pdp_ctx(pdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't call this function directly unless you know what you are doing.
|
||||
* In normal conditions use sgsn_delete_pdp_ctx and in unspecified or
|
||||
* implementation dependent abnormal ones sgsn_pdp_ctx_terminate.
|
||||
*/
|
||||
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
struct sgsn_signal_data sig_data;
|
||||
|
||||
memset(&sig_data, 0, sizeof(sig_data));
|
||||
sig_data.pdp = pdp;
|
||||
osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_FREE, &sig_data);
|
||||
|
||||
if (osmo_timer_pending(&pdp->timer)) {
|
||||
LOGPDPCTXP(LOGL_ERROR, pdp, "Freeing PDP ctx with timer %u pending\n", pdp->T);
|
||||
osmo_timer_del(&pdp->timer);
|
||||
}
|
||||
|
||||
rate_ctr_group_free(pdp->ctrg);
|
||||
if (pdp->mm)
|
||||
llist_del(&pdp->list);
|
||||
if (pdp->ggsn)
|
||||
sgsn_ggsn_ctx_remove_pdp(pdp->ggsn, pdp);
|
||||
llist_del(&pdp->g_list);
|
||||
|
||||
/* _if_ we still have a library handle, at least set it to NULL
|
||||
* to avoid any dereferences of the now-deleted PDP context from
|
||||
* sgsn_libgtp:cb_data_ind() */
|
||||
if (pdp->lib) {
|
||||
struct pdp_t *lib = pdp->lib;
|
||||
LOGPDPCTXP(LOGL_NOTICE, pdp, "freeing PDP context that still "
|
||||
"has a libgtp handle attached to it, this shouldn't "
|
||||
"happen!\n");
|
||||
osmo_generate_backtrace();
|
||||
lib->priv = NULL;
|
||||
}
|
||||
|
||||
talloc_free(pdp);
|
||||
}
|
|
@ -0,0 +1,220 @@
|
|||
/* SGSN instance */
|
||||
|
||||
/* (C) 2009 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 <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
#include <osmocom/core/backtrace.h>
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/ports.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/gsup.h>
|
||||
|
||||
#include <osmocom/crypt/gprs_cipher.h>
|
||||
#include <osmocom/crypt/utran_cipher.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_sm.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
#include <osmocom/sgsn/signal.h>
|
||||
#include <osmocom/sgsn/gprs_gmm_attach.h>
|
||||
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
|
||||
#include <pdp.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define GPRS_LLME_CHECK_TICK 30
|
||||
|
||||
extern struct osmo_tdef sgsn_T_defs[];
|
||||
|
||||
static const struct rate_ctr_desc sgsn_ctr_description[] = {
|
||||
{ "llc:dl_bytes", "Count sent LLC bytes before giving it to the bssgp layer" },
|
||||
{ "llc:ul_bytes", "Count successful received LLC bytes (encrypt & fcs correct)" },
|
||||
{ "llc:dl_packets", "Count successful sent LLC packets before giving it to the bssgp layer" },
|
||||
{ "llc:ul_packets", "Count successful received LLC packets (encrypt & fcs correct)" },
|
||||
{ "gprs:attach_requested", "Received attach requests" },
|
||||
{ "gprs:attach_accepted", "Sent attach accepts" },
|
||||
{ "gprs:attach_rejected", "Sent attach rejects" },
|
||||
{ "gprs:detach_requested", "Received detach requests" },
|
||||
{ "gprs:detach_acked", "Sent detach acks" },
|
||||
{ "gprs:routing_area_requested", "Received routing area requests" },
|
||||
{ "gprs:routing_area_requested", "Sent routing area acks" },
|
||||
{ "gprs:routing_area_requested", "Sent routing area rejects" },
|
||||
{ "pdp:activate_requested", "Received activate requests" },
|
||||
{ "pdp:activate_rejected", "Sent activate rejects" },
|
||||
{ "pdp:activate_accepted", "Sent activate accepts" },
|
||||
{ "pdp:request_activated", "unused" },
|
||||
{ "pdp:request_activate_rejected", "unused" },
|
||||
{ "pdp:modify_requested", "unused" },
|
||||
{ "pdp:modify_accepted", "unused" },
|
||||
{ "pdp:dl_deactivate_requested", "Sent deactivate requests" },
|
||||
{ "pdp:dl_deactivate_accepted", "Sent deactivate accepted" },
|
||||
{ "pdp:ul_deactivate_requested", "Received deactivate requests" },
|
||||
{ "pdp:ul_deactivate_accepted", "Received deactivate accepts" },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc sgsn_ctrg_desc = {
|
||||
"sgsn",
|
||||
"SGSN Overall Statistics",
|
||||
OSMO_STATS_CLASS_GLOBAL,
|
||||
ARRAY_SIZE(sgsn_ctr_description),
|
||||
sgsn_ctr_description,
|
||||
};
|
||||
|
||||
static void sgsn_llme_cleanup_free(struct gprs_llc_llme *llme)
|
||||
{
|
||||
struct sgsn_mm_ctx *mmctx = NULL;
|
||||
|
||||
llist_for_each_entry(mmctx, &sgsn->mm_list, list) {
|
||||
if (llme == mmctx->gb.llme) {
|
||||
gsm0408_gprs_access_cancelled(mmctx, SGSN_ERROR_CAUSE_NONE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No MM context found */
|
||||
LOGP(DGPRS, LOGL_INFO, "Deleting orphaned LLME, TLLI 0x%08x\n",
|
||||
llme->tlli);
|
||||
gprs_llgmm_unassign(llme);
|
||||
}
|
||||
|
||||
static void sgsn_llme_check_cb(void *data_)
|
||||
{
|
||||
struct gprs_llc_llme *llme, *llme_tmp;
|
||||
struct timespec now_tp;
|
||||
time_t now, age;
|
||||
time_t max_age = gprs_max_time_to_idle();
|
||||
|
||||
int rc;
|
||||
|
||||
rc = osmo_clock_gettime(CLOCK_MONOTONIC, &now_tp);
|
||||
OSMO_ASSERT(rc >= 0);
|
||||
now = now_tp.tv_sec;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Checking for inactive LLMEs, time = %u\n", (unsigned)now);
|
||||
|
||||
llist_for_each_entry_safe(llme, llme_tmp, &gprs_llc_llmes, list) {
|
||||
if (llme->age_timestamp == GPRS_LLME_RESET_AGE)
|
||||
llme->age_timestamp = now;
|
||||
|
||||
age = now - llme->age_timestamp;
|
||||
|
||||
if (age > max_age || age < 0) {
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Inactivity timeout for TLLI 0x%08x, age %d\n",
|
||||
llme->tlli, (int)age);
|
||||
sgsn_llme_cleanup_free(llme);
|
||||
}
|
||||
}
|
||||
|
||||
osmo_timer_schedule(&sgsn->llme_timer, GPRS_LLME_CHECK_TICK, 0);
|
||||
}
|
||||
|
||||
static int sgsn_instance_talloc_destructor(struct sgsn_instance *sgi)
|
||||
{
|
||||
sgsn_cdr_release(sgi);
|
||||
osmo_timer_del(&sgi->llme_timer);
|
||||
rate_ctr_group_free(sgi->rate_ctrs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx)
|
||||
{
|
||||
struct sgsn_instance *inst;
|
||||
inst = talloc_zero(talloc_ctx, struct sgsn_instance);
|
||||
|
||||
talloc_set_destructor(inst, sgsn_instance_talloc_destructor);
|
||||
|
||||
inst->cfg.gtp_statedir = talloc_strdup(inst, "./");
|
||||
inst->cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
|
||||
inst->cfg.gea_encryption_mask = (1 << GPRS_ALGO_GEA0); /* no encryption */
|
||||
inst->cfg.uea_encryption_mask = (1 << OSMO_UTRAN_UEA2) | (1 << OSMO_UTRAN_UEA1);
|
||||
inst->cfg.require_authentication = true; /* only applies if auth_policy is REMOTE */
|
||||
inst->cfg.gsup_server_port = OSMO_GSUP_PORT;
|
||||
|
||||
inst->cfg.T_defs = sgsn_T_defs;
|
||||
osmo_tdefs_reset(inst->cfg.T_defs);
|
||||
inst->cfg.T_defs_gtp = gtp_T_defs;
|
||||
osmo_tdefs_reset(inst->cfg.T_defs_gtp);
|
||||
|
||||
inst->rate_ctrs = rate_ctr_group_alloc(inst, &sgsn_ctrg_desc, 0);
|
||||
OSMO_ASSERT(inst->rate_ctrs);
|
||||
|
||||
INIT_LLIST_HEAD(&inst->apn_list);
|
||||
INIT_LLIST_HEAD(&inst->ggsn_list);
|
||||
INIT_LLIST_HEAD(&inst->mme_list);
|
||||
INIT_LLIST_HEAD(&inst->mm_list);
|
||||
INIT_LLIST_HEAD(&inst->pdp_list);
|
||||
|
||||
osmo_timer_setup(&inst->llme_timer, sgsn_llme_check_cb, NULL);
|
||||
osmo_timer_schedule(&inst->llme_timer, GPRS_LLME_CHECK_TICK, 0);
|
||||
/* These are mostly setting up stuff not related to VTY cfg, so they can be set up here: */
|
||||
sgsn_auth_init(inst);
|
||||
sgsn_cdr_init(inst);
|
||||
return inst;
|
||||
}
|
||||
|
||||
/* To be called after VTY config parsing: */
|
||||
int sgsn_inst_init(struct sgsn_instance *sgsn)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* start control interface after reading config for
|
||||
* ctrl_vty_get_bind_addr() */
|
||||
sgsn->ctrlh = ctrl_interface_setup(NULL, OSMO_CTRL_PORT_SGSN, NULL);
|
||||
if (!sgsn->ctrlh) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "Failed to create CTRL interface.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = sgsn_ctrl_cmds_install();
|
||||
if (rc != 0) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "Failed to install CTRL commands.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = gprs_subscr_init(sgsn);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot set up SGSN\n");
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include <osmocom/gsm/apn.h>
|
||||
|
||||
#include <osmocom/sgsn/vty.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
|
||||
#include <gtp.h>
|
||||
#include <pdp.h>
|
||||
|
@ -38,10 +41,6 @@
|
|||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/* TODO...avoid going through a global */
|
||||
extern struct sgsn_instance *sgsn;
|
||||
extern struct ctrl_handle *g_ctrlh;
|
||||
|
||||
/**
|
||||
* The CDR module will generate an entry like:
|
||||
*
|
||||
|
@ -64,7 +63,7 @@ extern struct ctrl_handle *g_ctrlh;
|
|||
|
||||
static void send_cdr_trap(char *value)
|
||||
{
|
||||
if (ctrl_cmd_send_trap(g_ctrlh, "cdr-v1", value) < 0)
|
||||
if (ctrl_cmd_send_trap(sgsn->ctrlh, "cdr-v1", value) < 0)
|
||||
LOGP(DGPRS, LOGL_ERROR, "Failed to create and send TRAP cdr-v1\n");
|
||||
}
|
||||
|
||||
|
@ -299,3 +298,8 @@ int sgsn_cdr_init(struct sgsn_instance *sgsn)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sgsn_cdr_release(struct sgsn_instance *sgsn)
|
||||
{
|
||||
osmo_signal_unregister_handler(SS_SGSN, handle_sgsn_sig, sgsn);
|
||||
}
|
||||
|
|
|
@ -21,20 +21,19 @@
|
|||
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/control_cmd.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
#include <pdp.h>
|
||||
|
||||
extern vector ctrl_node_vec;
|
||||
|
||||
static int get_subscriber_list(struct ctrl_cmd *cmd, void *d)
|
||||
{
|
||||
struct sgsn_mm_ctx *mm;
|
||||
|
||||
cmd->reply = talloc_strdup(cmd, "");
|
||||
llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
|
||||
llist_for_each_entry(mm, &sgsn->mm_list, list) {
|
||||
char *addr = NULL;
|
||||
struct sgsn_pdp_ctx *pdp;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "bscconfig.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/select.h>
|
||||
|
@ -45,9 +45,9 @@
|
|||
#include <osmocom/sgsn/signal.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_gb.h>
|
||||
#include <osmocom/sgsn/gprs_ns.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_sm.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
|
@ -55,8 +55,11 @@
|
|||
#include <osmocom/sgsn/gprs_ranap.h>
|
||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
|
||||
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/gtp_mme.h>
|
||||
#include <osmocom/sgsn/sgsn_rim.h>
|
||||
#include <osmocom/sgsn/gprs_bssgp.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
|
||||
#include <gtp.h>
|
||||
#include <pdp.h>
|
||||
|
@ -414,7 +417,7 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
|
|||
}
|
||||
|
||||
/* Check for cause value if it was really successful */
|
||||
if (cause != GTPCAUSE_ACC_REQ) {
|
||||
if (!gtp_cause_successful(cause)) {
|
||||
reject_cause = cause_map(gtp2sm_cause_map, cause,
|
||||
GSM_CAUSE_ACT_REJ_GGSN);
|
||||
goto reject;
|
||||
|
@ -593,12 +596,12 @@ static int echo_conf(void *cbp, bool timeout)
|
|||
}
|
||||
|
||||
/* Any message received by GGSN contains a recovery IE */
|
||||
static int cb_recovery2(struct sockaddr_in *peer, struct pdp_t *pdp, uint8_t recovery)
|
||||
static int cb_recovery3(struct gsn_t *gsn, struct sockaddr_in *peer, struct pdp_t *pdp, uint8_t recovery)
|
||||
{
|
||||
struct sgsn_ggsn_ctx *ggsn;
|
||||
struct sgsn_pdp_ctx *pctx = NULL;
|
||||
|
||||
ggsn = sgsn_ggsn_ctx_by_addr(&peer->sin_addr);
|
||||
ggsn = sgsn_ggsn_ctx_by_addr(sgsn, &peer->sin_addr);
|
||||
if (!ggsn) {
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Received Recovery IE for unknown GGSN\n");
|
||||
return -EINVAL;
|
||||
|
@ -692,9 +695,46 @@ static int cb_gtp_ran_info_relay_ind(struct sockaddr_in *peer, union gtpie_membe
|
|||
|
||||
LOGMME(mme, DGTP, LOGL_INFO, "Rx GTP RAN Information Relay\n");
|
||||
|
||||
int rc;
|
||||
unsigned int len = 0;
|
||||
struct msgb *msg = msgb_alloc(4096, "gtpcv1_ran_info");
|
||||
struct bssgp_ran_information_pdu pdu;
|
||||
struct msgb *msg = bssgp_msgb_alloc();
|
||||
|
||||
uint8_t rim_ra_encoded[256];
|
||||
unsigned int rim_ra_encoded_len = 0;
|
||||
struct bssgp_rim_routing_info rim_ra;
|
||||
|
||||
unsigned int rim_ra_discr_encoded_len = 0;
|
||||
uint8_t rim_ra_discr;
|
||||
|
||||
/* Read RIM Routing Address Discriminator (optional) */
|
||||
rc = gtpie_gettlv(ie, GTPIE_RIM_RA_DISCR, 0, &rim_ra_discr_encoded_len, &rim_ra_discr,
|
||||
sizeof(rim_ra_discr));
|
||||
if (rc || rim_ra_discr_encoded_len <= 0) {
|
||||
LOGMME(mme, DGTP, LOGL_NOTICE, "Rx GTP RAN Information Relay: No RIM Routing Address Discriminator IE found!\n");
|
||||
|
||||
/* It is not an error when the RIM ROUTING ADDRESS DISCRIMINATOR IE is missing. The RIM ROUTING ADDRESS
|
||||
* DISCRIMINATOR IE is an optional IE. When it is missing, the RIM Routing Address shall be processed
|
||||
* as an RNC address ("0001") See also: 3GPP TS 29.060 */
|
||||
rim_ra_discr = BSSGP_RIM_ROUTING_INFO_UTRAN;
|
||||
}
|
||||
|
||||
/* Read RIM Routing Address (optional) */
|
||||
rc = gtpie_gettlv(ie, GTPIE_RIM_ROUT_ADDR, 0, &rim_ra_encoded_len, rim_ra_encoded, sizeof(rim_ra_encoded));
|
||||
if (rc || rim_ra_encoded_len <= 0) {
|
||||
LOGMME(mme, DGTP, LOGL_ERROR, "Rx GTP RAN Information Relay: No RIM Routing Address IE found!\n");
|
||||
|
||||
/* TODO: The (usually included) RIM ROUTING ADDRESS field is an optional field. However, we cannot
|
||||
* proceed without a destination address. A possible way to fix this would be a default route that
|
||||
* can be configured via the VTY. */
|
||||
goto ret_error;
|
||||
} else {
|
||||
rc = bssgp_parse_rim_ra(&rim_ra, rim_ra_encoded, rim_ra_encoded_len, rim_ra_discr);
|
||||
if (rc < 0) {
|
||||
LOGMME(mme, DGTP, LOGL_ERROR,
|
||||
"Rx GTP RAN Information Relay: Failed parsing RIM Routing Address/RIM Routing Address Discriminator IE!\n");
|
||||
goto ret_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (gtpie_gettlv(ie, GTPIE_RAN_T_CONTAIN, 0, &len, msgb_data(msg), 4096) || len <= 0) {
|
||||
LOGMME(mme, DGTP, LOGL_ERROR, "Rx GTP RAN Information Relay: No Transparent Container IE found!\n");
|
||||
|
@ -703,13 +743,8 @@ static int cb_gtp_ran_info_relay_ind(struct sockaddr_in *peer, union gtpie_membe
|
|||
msgb_put(msg, len);
|
||||
msgb_bssgph(msg) = msg->data;
|
||||
msgb_nsei(msg) = 0;
|
||||
if (bssgp_parse_rim_pdu(&pdu, msg) < 0) {
|
||||
LOGMME(mme, DGTP, LOGL_ERROR, "Rx GTP RAN Information Relay: Failed parsing Transparent Container IE!\n");
|
||||
goto ret_error;
|
||||
}
|
||||
|
||||
msgb_free(msg);
|
||||
return sgsn_rim_rx_from_gtp(&pdu, mme);
|
||||
return sgsn_rim_rx_from_gtp(msg, &rim_ra);
|
||||
|
||||
ret_error:
|
||||
msgb_free(msg);
|
||||
|
@ -768,15 +803,24 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
|
|||
msgb_free(msg);
|
||||
return -1;
|
||||
case ST_GMM_REGISTERED_NORMAL:
|
||||
OSMO_ASSERT(mm->gb.mm_state_fsm->state != ST_MM_IDLE);
|
||||
if (mm->gb.mm_state_fsm->state == ST_MM_STANDBY) {
|
||||
switch (mm->gb.mm_state_fsm->state) {
|
||||
case ST_MM_IDLE:
|
||||
LOGP(DGPRS, LOGL_ERROR, "Dropping DL packet for MS in MM state %s\n",
|
||||
osmo_fsm_inst_state_name(mm->gb.mm_state_fsm));
|
||||
msgb_free(msg);
|
||||
return -1;
|
||||
case ST_MM_READY:
|
||||
/* Go ahead */
|
||||
break;
|
||||
case ST_MM_STANDBY:
|
||||
LOGMMCTXP(LOGL_INFO, mm, "Paging MS in GMM state %s, MM state %s\n",
|
||||
osmo_fsm_inst_state_name(mm->gmm_fsm),
|
||||
osmo_fsm_inst_state_name(mm->gb.mm_state_fsm));
|
||||
gprs_gb_page_ps_ra(mm);
|
||||
}
|
||||
sgsn_bssgp_page_ps_ra(mm);
|
||||
|
||||
/* FIXME: queue the packet we received from GTP */
|
||||
/* FIXME: queue the packet we received from GTP */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state "
|
||||
|
@ -793,12 +837,12 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
|
|||
/* It is easier to have a global count */
|
||||
pdp->cdr_bytes_out += len;
|
||||
|
||||
return sndcp_unitdata_req(msg, &mm->gb.llme->lle[pdp->sapi],
|
||||
return sndcp_sn_unitdata_req(msg, &mm->gb.llme->lle[pdp->sapi],
|
||||
pdp->nsapi, mm);
|
||||
}
|
||||
|
||||
/* Called by SNDCP when it has received/re-assembled a N-PDU */
|
||||
int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
|
||||
int sgsn_gtp_data_req(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
|
||||
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu)
|
||||
{
|
||||
struct sgsn_mm_ctx *mmctx;
|
||||
|
@ -901,7 +945,7 @@ int sgsn_gtp_init(struct sgsn_instance *sgi)
|
|||
/* Register callbackcs with libgtp */
|
||||
gtp_set_cb_delete_context(gsn, cb_delete_context);
|
||||
gtp_set_cb_conf(gsn, cb_conf);
|
||||
gtp_set_cb_recovery2(gsn, cb_recovery2);
|
||||
gtp_set_cb_recovery3(gsn, cb_recovery3);
|
||||
gtp_set_cb_data_ind(gsn, cb_data_ind);
|
||||
gtp_set_cb_unsup_ind(gsn, cb_unsup_ind);
|
||||
gtp_set_cb_extheader_ind(gsn, cb_extheader_ind);
|
||||
|
|
|
@ -59,17 +59,18 @@
|
|||
#include <osmocom/sgsn/vty.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/gprs_sndcp.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_ranap.h>
|
||||
#include <osmocom/sgsn/gprs_gb.h>
|
||||
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/ports.h>
|
||||
#include <osmocom/sgsn/gprs_ns.h>
|
||||
#include <osmocom/sgsn/gprs_bssgp.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
|
||||
#include <gtp.h>
|
||||
#include <osmocom/sgsn/sgsn_rim.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
#include "../../config.h"
|
||||
|
||||
#if BUILD_IU
|
||||
#include <osmocom/sigtran/osmo_ss7.h>
|
||||
|
@ -81,7 +82,6 @@
|
|||
#include <getopt.h>
|
||||
|
||||
void *tall_sgsn_ctx;
|
||||
struct ctrl_handle *g_ctrlh;
|
||||
|
||||
struct gprs_ns2_inst *sgsn_nsi;
|
||||
static int daemonize = 0;
|
||||
|
@ -97,34 +97,11 @@ const char *openbsc_copyright =
|
|||
|
||||
struct sgsn_instance *sgsn;
|
||||
|
||||
/* call-back function for the BSSGP protocol */
|
||||
/* call-back function for the BSSGP protocol.
|
||||
* Must be left here so that we can add a new one in tests/sgsn_test */
|
||||
int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
|
||||
{
|
||||
struct osmo_bssgp_prim *bp;
|
||||
bp = container_of(oph, struct osmo_bssgp_prim, oph);
|
||||
|
||||
switch (oph->sap) {
|
||||
case SAP_BSSGP_LL:
|
||||
switch (oph->primitive) {
|
||||
case PRIM_BSSGP_UL_UD:
|
||||
return gprs_llc_rcvmsg(oph->msg, bp->tp);
|
||||
}
|
||||
break;
|
||||
case SAP_BSSGP_GMM:
|
||||
switch (oph->primitive) {
|
||||
case PRIM_BSSGP_GMM_SUSPEND:
|
||||
return gprs_gmm_rx_suspend(bp->ra_id, bp->tlli);
|
||||
case PRIM_BSSGP_GMM_RESUME:
|
||||
return gprs_gmm_rx_resume(bp->ra_id, bp->tlli,
|
||||
bp->u.resume.suspend_ref);
|
||||
}
|
||||
break;
|
||||
case SAP_BSSGP_NM:
|
||||
break;
|
||||
case SAP_BSSGP_RIM:
|
||||
return sgsn_rim_rx_from_gb(bp, oph->msg);
|
||||
}
|
||||
return 0;
|
||||
return sgsn_bssgp_rx_prim(oph);
|
||||
}
|
||||
|
||||
static void signal_handler(int signum)
|
||||
|
@ -434,19 +411,12 @@ int main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
sgsn->cfg.nsi = sgsn_nsi;
|
||||
bssgp_set_bssgp_callback(gprs_gb_send_cb, sgsn_nsi);
|
||||
|
||||
gprs_llc_init("/usr/local/lib/osmocom/crypt/");
|
||||
sgsn_rate_ctr_init();
|
||||
sgsn_inst_init(sgsn);
|
||||
|
||||
bssgp_set_bssgp_callback(sgsn_bssgp_dispatch_ns_unitdata_req_cb, sgsn_nsi);
|
||||
|
||||
gprs_ns2_vty_init(sgsn_nsi);
|
||||
bssgp_vty_init();
|
||||
gprs_llc_vty_init();
|
||||
gprs_sndcp_vty_init();
|
||||
sgsn_auth_init(sgsn);
|
||||
sgsn_cdr_init(sgsn);
|
||||
|
||||
handle_options(argc, argv);
|
||||
|
||||
|
@ -472,25 +442,11 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/* start telnet after reading config for vty_get_bind_addr() */
|
||||
rc = telnet_init_dynif(tall_sgsn_ctx, NULL,
|
||||
vty_get_bind_addr(), OSMO_VTY_PORT_SGSN);
|
||||
rc = telnet_init_default(tall_sgsn_ctx, NULL, OSMO_VTY_PORT_SGSN);
|
||||
if (rc < 0)
|
||||
exit(1);
|
||||
|
||||
/* start control interface after reading config for
|
||||
* ctrl_vty_get_bind_addr() */
|
||||
g_ctrlh = ctrl_interface_setup_dynip(NULL, ctrl_vty_get_bind_addr(),
|
||||
OSMO_CTRL_PORT_SGSN, NULL);
|
||||
if (!g_ctrlh) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "Failed to create CTRL interface.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sgsn_ctrl_cmds_install() != 0) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "Failed to install CTRL commands.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gprs_llc_init(sgsn->cfg.crypt_cipher_plugin_path);
|
||||
|
||||
rc = sgsn_gtp_init(sgsn);
|
||||
if (rc) {
|
||||
|
@ -499,9 +455,9 @@ int main(int argc, char **argv)
|
|||
} else
|
||||
LOGP(DGPRS, LOGL_NOTICE, "libGTP v%s initialized\n", gtp_version());
|
||||
|
||||
rc = gprs_subscr_init(sgsn);
|
||||
rc = sgsn_inst_init(sgsn);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot set up subscriber management\n");
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot set up SGSN\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <osmocom/gprs/gprs_bssgp_rim.h>
|
||||
#include <osmocom/sgsn/sgsn_rim.h>
|
||||
#include <osmocom/sgsn/gtp_mme.h>
|
||||
#include <osmocom/sgsn/gtp.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
|
||||
|
@ -20,6 +21,7 @@ static int sgsn_bssgp_fwd_rim_to_geran(const struct bssgp_ran_information_pdu *p
|
|||
struct bssgp_bvc_ctx *bvc_ctx;
|
||||
OSMO_ASSERT(pdu->routing_info_dest.discr == BSSGP_RIM_ROUTING_INFO_GERAN);
|
||||
|
||||
/* Resolve RIM ROUTING ADDRESS to a BVC context */
|
||||
bvc_ctx = btsctx_by_raid_cid(&pdu->routing_info_dest.geran.raid, pdu->routing_info_dest.geran.cid);
|
||||
if (!bvc_ctx) {
|
||||
LOGP(DRIM, LOGL_ERROR, "Unable to find NSEI for destination cell %s\n",
|
||||
|
@ -27,10 +29,27 @@ static int sgsn_bssgp_fwd_rim_to_geran(const struct bssgp_ran_information_pdu *p
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Forward PDU as it is to the correct interface */
|
||||
/* Forward PDU to the NSEI of the resolved BVC context */
|
||||
return bssgp_tx_rim(pdu, bvc_ctx->nsei);
|
||||
}
|
||||
|
||||
static int sgsn_bssgp_fwd_rim_to_geran_encoded(struct msgb *msg, struct bssgp_rim_routing_info *rim_routing_address)
|
||||
{
|
||||
struct bssgp_bvc_ctx *bvc_ctx;
|
||||
OSMO_ASSERT(rim_routing_address->discr == BSSGP_RIM_ROUTING_INFO_GERAN);
|
||||
|
||||
/* Resolve RIM ROUTING ADDRESS to a BVC context */
|
||||
bvc_ctx = btsctx_by_raid_cid(&rim_routing_address->geran.raid, rim_routing_address->geran.cid);
|
||||
if (!bvc_ctx) {
|
||||
LOGP(DRIM, LOGL_ERROR, "Unable to find NSEI for destination cell %s\n",
|
||||
bssgp_rim_ri_name(rim_routing_address));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Forward PDU to the NSEI of the resolved BVC context */
|
||||
return bssgp_tx_rim_encoded(msg, bvc_ctx->nsei);
|
||||
}
|
||||
|
||||
static int sgsn_bssgp_fwd_rim_to_eutran(const struct bssgp_ran_information_pdu *pdu)
|
||||
{
|
||||
struct sgsn_mme_ctx *mme;
|
||||
|
@ -88,36 +107,21 @@ err:
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Receive a RIM PDU from GTPvC1 (EUTRAN) */
|
||||
int sgsn_rim_rx_from_gtp(struct bssgp_ran_information_pdu *pdu, struct sgsn_mme_ctx *mme)
|
||||
/* Receive a RIM PDU from GTPv1C (EUTRAN) */
|
||||
int sgsn_rim_rx_from_gtp(struct msgb *msg, struct bssgp_rim_routing_info *rim_routing_address)
|
||||
{
|
||||
struct sgsn_mme_ctx *mme_tmp;
|
||||
if (pdu->routing_info_src.discr != BSSGP_RIM_ROUTING_INFO_EUTRAN) {
|
||||
LOGMME(mme, DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: Expected src %s, got %s\n",
|
||||
bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_EUTRAN),
|
||||
bssgp_rim_routing_info_discr_str(pdu->routing_info_src.discr));
|
||||
/* TODO: In this code path, we currently only support RIM message forwarding to GERAN (BSSGP). However, it
|
||||
* technically also be possible to route a message back to GTP (BSSGP_RIM_ROUTING_INFO_EUTRAN) or to
|
||||
* IuPS (BSSGP_RIM_ROUTING_INFO_UTRAN) */
|
||||
if (rim_routing_address->discr != BSSGP_RIM_ROUTING_INFO_GERAN) {
|
||||
LOGP(DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: Expected dst %s, got %s\n",
|
||||
bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_GERAN),
|
||||
bssgp_rim_routing_info_discr_str(rim_routing_address->discr));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdu->routing_info_dest.discr != BSSGP_RIM_ROUTING_INFO_GERAN) {
|
||||
LOGMME(mme, DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: Expected dst %s, got %s\n",
|
||||
bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_GERAN),
|
||||
bssgp_rim_routing_info_discr_str(pdu->routing_info_dest.discr));
|
||||
return -EINVAL;
|
||||
}
|
||||
LOGP(DRIM, LOGL_INFO, "Rx GTP RAN Information Relay for dest cell %s\n",
|
||||
bssgp_rim_ri_name(rim_routing_address));
|
||||
|
||||
mme_tmp = sgsn_mme_ctx_by_route(sgsn, &pdu->routing_info_src.eutran.tai);
|
||||
if (!mme_tmp)/* See if we have a default route configured */
|
||||
mme_tmp = sgsn_mme_ctx_by_default_route(sgsn);
|
||||
if (mme != mme_tmp) {
|
||||
LOGP(DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: "
|
||||
"Source MME doesn't have RIM routing configured for TAI: %s\n",
|
||||
bssgp_rim_ri_name(&pdu->routing_info_src));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOGMME(mme, DRIM, LOGL_INFO, "Rx GTP RAN Information Relay for dest cell %s\n",
|
||||
bssgp_rim_ri_name(&pdu->routing_info_dest));
|
||||
|
||||
return sgsn_bssgp_fwd_rim_to_geran(pdu);
|
||||
return sgsn_bssgp_fwd_rim_to_geran_encoded(msg, rim_routing_address);
|
||||
}
|
||||
|
|
|
@ -35,11 +35,14 @@
|
|||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/sgsn/gprs_gb.h>
|
||||
#include <osmocom/sgsn/gprs_ns.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_bssgp.h>
|
||||
#include <osmocom/sgsn/mmctx.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
#include <osmocom/sgsn/gtp_mme.h>
|
||||
#include <osmocom/sgsn/vty.h>
|
||||
#include <osmocom/sgsn/pdpctx.h>
|
||||
#include <osmocom/gsupclient/gsup_client.h>
|
||||
|
||||
#include <osmocom/vty/tdef_vty.h>
|
||||
|
@ -55,14 +58,12 @@
|
|||
#include <pdp.h>
|
||||
#include <gtp.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
#include "../../config.h"
|
||||
|
||||
#ifdef BUILD_IU
|
||||
#include <osmocom/ranap/iu_client.h>
|
||||
#endif
|
||||
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
static struct sgsn_config *g_cfg = NULL;
|
||||
|
||||
const struct value_string sgsn_auth_pol_strs[] = {
|
||||
|
@ -97,7 +98,7 @@ const struct value_string sgsn_auth_pol_strs[] = {
|
|||
#define NONSPEC_X1001_SECS 5 /* wait for a RANAP Release Complete */
|
||||
|
||||
|
||||
static struct osmo_tdef sgsn_T_defs[] = {
|
||||
struct osmo_tdef sgsn_T_defs[] = {
|
||||
{ .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },
|
||||
{ .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },
|
||||
{ .T=3314, .default_val=GSM0408_T3314_SECS, .desc="READY timer. Force to STANDBY on expiry timer (s)" },
|
||||
|
@ -136,6 +137,26 @@ DEFUN(cfg_sgsn_timer, cfg_sgsn_timer_cmd,
|
|||
return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs, argv);
|
||||
}
|
||||
|
||||
DEFUN(show_timer_gtp, show_timer_gtp_cmd,
|
||||
"show timer gtp " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
|
||||
SHOW_STR "Show timers\n" "GTP (libgtp) timers\n"
|
||||
OSMO_TDEF_VTY_DOC_T)
|
||||
{
|
||||
const char *T_arg = argc > 0 ? argv[0] : NULL;
|
||||
return osmo_tdef_vty_show_cmd(vty, g_cfg->T_defs_gtp, T_arg, NULL);
|
||||
}
|
||||
|
||||
DEFUN(cfg_sgsn_timer_gtp, cfg_sgsn_timer_gtp_cmd,
|
||||
"timer gtp " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
|
||||
"Configure or show timers\n" "GTP (libgtp) timers\n"
|
||||
OSMO_TDEF_VTY_DOC_SET)
|
||||
{
|
||||
/* If any arguments are missing, redirect to 'show' */
|
||||
if (argc < 2)
|
||||
return show_timer(self, vty, argc, argv);
|
||||
return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs_gtp, argv);
|
||||
}
|
||||
|
||||
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6)
|
||||
{
|
||||
static char str[INET6_ADDRSTRLEN + 10];
|
||||
|
@ -230,7 +251,7 @@ static int config_write_sgsn(struct vty *vty)
|
|||
vty_out(vty, " gtp local-ip %s%s",
|
||||
inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
|
||||
|
||||
llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
|
||||
llist_for_each_entry(gctx, &sgsn->ggsn_list, list) {
|
||||
if (gctx->id == UINT32_MAX)
|
||||
continue;
|
||||
|
||||
|
@ -261,6 +282,17 @@ static int config_write_sgsn(struct vty *vty)
|
|||
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
if (g_cfg->uea_encryption_mask != 0) {
|
||||
vty_out(vty, " encryption uea");
|
||||
|
||||
for (i = 0; i < _OSMO_UTRAN_UEA_NUM; i++)
|
||||
if (g_cfg->uea_encryption_mask >> i & 1)
|
||||
vty_out(vty, " %u", i);
|
||||
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
if (g_cfg->crypt_cipher_plugin_path)
|
||||
vty_out(vty, " encryption cipher-plugin-path %s%s", g_cfg->crypt_cipher_plugin_path, VTY_NEWLINE);
|
||||
if (g_cfg->sgsn_ipa_name)
|
||||
vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
|
||||
if (g_cfg->gsup_server_addr.sin_addr.s_addr)
|
||||
|
@ -289,9 +321,9 @@ static int config_write_sgsn(struct vty *vty)
|
|||
llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
|
||||
vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
|
||||
|
||||
if (llist_empty(&sgsn_apn_ctxts))
|
||||
if (llist_empty(&sgsn->apn_list))
|
||||
vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
|
||||
llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
|
||||
llist_for_each_entry(actx, &sgsn->apn_list, list) {
|
||||
if (strlen(actx->imsi_prefix) > 0)
|
||||
vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
|
||||
actx->name, actx->imsi_prefix, actx->ggsn->id,
|
||||
|
@ -312,6 +344,7 @@ static int config_write_sgsn(struct vty *vty)
|
|||
vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
|
||||
|
||||
osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
|
||||
osmo_tdef_vty_write(vty, g_cfg->T_defs_gtp, " timer gtp ");
|
||||
|
||||
if (g_cfg->pcomp_rfc1144.active) {
|
||||
vty_out(vty, " compression rfc1144 active slots %d%s",
|
||||
|
@ -399,7 +432,7 @@ DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
|
|||
"IPv4 Address\n")
|
||||
{
|
||||
uint32_t id = atoi(argv[0]);
|
||||
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
|
||||
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(sgsn, id);
|
||||
|
||||
inet_aton(argv[1], &ggc->remote_addr);
|
||||
|
||||
|
@ -424,7 +457,7 @@ DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
|
|||
"Version 0\n" "Version 1\n")
|
||||
{
|
||||
uint32_t id = atoi(argv[0]);
|
||||
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
|
||||
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(sgsn, id);
|
||||
|
||||
if (atoi(argv[1]))
|
||||
ggc->gtp_version = 1;
|
||||
|
@ -442,7 +475,7 @@ DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
|
|||
"Interval between echo requests in seconds.\n")
|
||||
{
|
||||
uint32_t id = atoi(argv[0]);
|
||||
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
|
||||
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(sgsn, id);
|
||||
|
||||
ggc->echo_interval = atoi(argv[1]);
|
||||
|
||||
|
@ -461,7 +494,7 @@ DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
|
|||
NO_STR "Send an echo request to this static GGSN every interval.\n")
|
||||
{
|
||||
uint32_t id = atoi(argv[0]);
|
||||
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
|
||||
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(sgsn, id);
|
||||
|
||||
ggc->echo_interval = 0;
|
||||
sgsn_ggsn_ctx_check_echo_timer(ggc);
|
||||
|
@ -502,7 +535,7 @@ static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
|
|||
struct apn_ctx *actx;
|
||||
struct sgsn_ggsn_ctx *ggsn;
|
||||
|
||||
ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
|
||||
ggsn = sgsn_ggsn_ctx_by_id(sgsn, ggsn_id);
|
||||
if (ggsn == NULL) {
|
||||
vty_out(vty, "%% a GGSN with id %d has not been defined%s",
|
||||
ggsn_id, VTY_NEWLINE);
|
||||
|
@ -689,7 +722,7 @@ DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
|
|||
SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
|
||||
{
|
||||
struct sgsn_mm_ctx *mm;
|
||||
llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
|
||||
llist_for_each_entry(mm, &sgsn->mm_list, list)
|
||||
vty_dump_mmctx(vty, "", mm, (argc > 0) ? 1 : 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
@ -701,7 +734,7 @@ DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
|
|||
{
|
||||
struct sgsn_pdp_ctx *pdp;
|
||||
|
||||
llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
|
||||
llist_for_each_entry(pdp, &sgsn->pdp_list, g_list)
|
||||
vty_dump_pdp(vty, "", pdp);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
@ -817,6 +850,27 @@ DEFUN(cfg_encrypt2, cfg_encrypt2_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_encrypt_cipher_plugin_path, cfg_encrypt_cipher_plugin_path_cmd,
|
||||
"encryption cipher-plugin-path PATH",
|
||||
ENCRYPTION_STR
|
||||
"Path to gprs encryption cipher plugin directory\n"
|
||||
"Plugin path\n")
|
||||
{
|
||||
osmo_talloc_replace_string(sgsn, &sgsn->cfg.crypt_cipher_plugin_path, argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_encrypt_cipher_plugin_path, cfg_no_encrypt_cipher_plugin_path_cmd,
|
||||
"no encryption cipher-plugin-path PATH",
|
||||
NO_STR ENCRYPTION_STR
|
||||
"Path to gprs encryption cipher plugin directory\n"
|
||||
"Plugin path\n")
|
||||
{
|
||||
TALLOC_FREE(sgsn->cfg.crypt_cipher_plugin_path);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_authentication, cfg_authentication_cmd,
|
||||
"authentication (optional|required)",
|
||||
"Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
|
||||
|
@ -936,8 +990,17 @@ static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int
|
|||
}
|
||||
|
||||
llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
|
||||
vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
|
||||
pdp->context_id, pdp->pdp_type, pdp->apn_str);
|
||||
char ip_str[INET6_ADDRSTRLEN] = { 0 };
|
||||
|
||||
vty_out(vty, " PDP info: Id: %d, Addr(Org: 0x%02x Type: 0x%02x",
|
||||
pdp->context_id, pdp->pdp_type_org, pdp->pdp_type_nr);
|
||||
|
||||
if (pdp->pdp_address[0].u.sa.sa_family != AF_UNSPEC)
|
||||
vty_out(vty, " Addr[0]: %s", osmo_sockaddr_ntop(&pdp->pdp_address[0].u.sa, ip_str));
|
||||
if (pdp->pdp_address[0].u.sa.sa_family != AF_UNSPEC)
|
||||
vty_out(vty, " Addr[1]: %s", osmo_sockaddr_ntop(&pdp->pdp_address[1].u.sa, ip_str));
|
||||
|
||||
vty_out(vty, ") APN: '%s'", pdp->apn_str);
|
||||
|
||||
if (pdp->qos_subscribed_len)
|
||||
vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
|
||||
|
@ -984,7 +1047,7 @@ DEFUN_HIDDEN(reset_sgsn_state,
|
|||
struct gprs_subscr *subscr, *tmp_subscr;
|
||||
struct sgsn_mm_ctx *mm, *tmp_mm;
|
||||
|
||||
llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
|
||||
llist_for_each_entry_safe(mm, tmp_mm, &sgsn->mm_list, list)
|
||||
{
|
||||
gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
|
||||
}
|
||||
|
@ -1263,7 +1326,7 @@ DEFUN(page_subscr, page_subscr_info_cmd,
|
|||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
gprs_gb_page_ps_ra(mm);
|
||||
sgsn_bssgp_page_ps_ra(mm);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1716,9 +1779,6 @@ int sgsn_vty_init(struct sgsn_config *cfg)
|
|||
{
|
||||
g_cfg = cfg;
|
||||
|
||||
g_cfg->T_defs = sgsn_T_defs;
|
||||
osmo_tdefs_reset(g_cfg->T_defs);
|
||||
|
||||
install_element_ve(&show_sgsn_cmd);
|
||||
//install_element_ve(&show_mmctx_tlli_cmd);
|
||||
install_element_ve(&show_mmctx_imsi_cmd);
|
||||
|
@ -1726,6 +1786,7 @@ int sgsn_vty_init(struct sgsn_config *cfg)
|
|||
install_element_ve(&show_pdpctx_all_cmd);
|
||||
install_element_ve(&show_subscr_cache_cmd);
|
||||
install_element_ve(&show_timer_cmd);
|
||||
install_element_ve(&show_timer_gtp_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
|
||||
install_element(ENABLE_NODE, &update_subscr_create_cmd);
|
||||
|
@ -1753,6 +1814,8 @@ int sgsn_vty_init(struct sgsn_config *cfg)
|
|||
install_element(SGSN_NODE, &cfg_encrypt2_cmd);
|
||||
install_element(SGSN_NODE, &cfg_encrypt_cmd);
|
||||
install_element(SGSN_NODE, &cfg_encryption_uea_cmd);
|
||||
install_element(SGSN_NODE, &cfg_encrypt_cipher_plugin_path_cmd);
|
||||
install_element(SGSN_NODE, &cfg_no_encrypt_cipher_plugin_path_cmd);
|
||||
|
||||
install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
|
||||
install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
|
||||
|
@ -1773,6 +1836,7 @@ int sgsn_vty_init(struct sgsn_config *cfg)
|
|||
install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
|
||||
|
||||
install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
|
||||
install_element(SGSN_NODE, &cfg_sgsn_timer_gtp_cmd);
|
||||
|
||||
install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
|
||||
install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
|
||||
|
@ -1804,9 +1868,6 @@ int sgsn_parse_config(const char *config_file)
|
|||
/* make sure sgsn_vty_init() was called before this */
|
||||
OSMO_ASSERT(g_cfg);
|
||||
|
||||
g_cfg->gea_encryption_mask = 0x1; /* support GEA0 by default unless specific encryption config exists */
|
||||
g_cfg->uea_encryption_mask = (1 << OSMO_UTRAN_UEA0); /* support UEA0 by default unless specific encryption config exists */
|
||||
|
||||
rc = vty_read_config_file(config_file, NULL);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
|
||||
|
|
|
@ -42,15 +42,15 @@ DISTCLEANFILES = \
|
|||
$(NULL)
|
||||
|
||||
if ENABLE_EXT_TESTS
|
||||
python-tests: $(BUILT_SOURCES)
|
||||
python-tests:
|
||||
$(MAKE) vty-test
|
||||
$(MAKE) ctrl-python-test
|
||||
else
|
||||
python-tests: $(BUILT_SOURCES)
|
||||
python-tests:
|
||||
echo "Not running python-based tests (determined at configure-time)"
|
||||
endif
|
||||
|
||||
vty-python-test: $(BUILT_SOURCES)
|
||||
vty-python-test: $(top_builddir)/src/sgsn/osmo-sgsn
|
||||
osmotestvty.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
|
||||
osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
|
||||
$(srcdir)/vty_test_runner.py -w $(abs_top_builddir) -v
|
||||
|
@ -59,7 +59,7 @@ vty-python-test: $(BUILT_SOURCES)
|
|||
# To update the VTY script from current application behavior,
|
||||
# pass -u to vty_script_runner.py by doing:
|
||||
# make vty-transcript-test U=-u
|
||||
vty-transcript-test:
|
||||
vty-transcript-test: $(top_builddir)/src/sgsn/osmo-sgsn
|
||||
osmo_verify_transcript_vty.py -v \
|
||||
-n OsmoSGSN -p 4245 \
|
||||
-r "$(top_builddir)/src/sgsn/osmo-sgsn -c $(top_srcdir)/doc/examples/osmo-sgsn/osmo-sgsn.cfg" \
|
||||
|
@ -71,7 +71,7 @@ vty-test:
|
|||
$(MAKE) vty-python-test
|
||||
$(MAKE) vty-transcript-test
|
||||
|
||||
ctrl-python-test: $(BUILT_SOURCES)
|
||||
ctrl-python-test: $(top_builddir)/src/sgsn/osmo-sgsn
|
||||
$(srcdir)/ctrl_test_runner.py -w $(abs_top_builddir) -v
|
||||
rm -f $(top_builddir)/gsn_restart $(top_builddir)/gtphub_restart_count
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
|
||||
AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS)
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = gprs_test.ok
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ static int nu_is_retransmission(uint16_t nu, uint16_t vur)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void test_8_4_2()
|
||||
static void test_8_4_2(void)
|
||||
{
|
||||
printf("Testing gprs_llc_is_retransmit.\n");
|
||||
|
||||
|
@ -48,6 +48,22 @@ static void test_8_4_2()
|
|||
ASSERT_FALSE(nu_is_retransmission(479, 511)); // wrapped
|
||||
}
|
||||
|
||||
/* GSM 04.08, 10.5.7.3 GPRS Timer */
|
||||
static int gprs_tmr_to_secs(uint8_t tmr)
|
||||
{
|
||||
switch (tmr & GPRS_TMR_UNIT_MASK) {
|
||||
case GPRS_TMR_2SECONDS:
|
||||
return 2 * (tmr & GPRS_TMR_FACT_MASK);
|
||||
default:
|
||||
case GPRS_TMR_MINUTE:
|
||||
return 60 * (tmr & GPRS_TMR_FACT_MASK);
|
||||
case GPRS_TMR_6MINUTE:
|
||||
return 360 * (tmr & GPRS_TMR_FACT_MASK);
|
||||
case GPRS_TMR_DEACTIVATED:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_gprs_timer_enc_dec(void)
|
||||
{
|
||||
int i, u, secs, tmr;
|
||||
|
|
|
@ -12,6 +12,8 @@ AM_CFLAGS = \
|
|||
$(LIBGTP_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = \
|
||||
gtphub_test.ok \
|
||||
$(NULL)
|
||||
|
@ -28,6 +30,7 @@ gtphub_test_LDFLAGS = \
|
|||
-Wl,--wrap=gtphub_resolve_ggsn_addr \
|
||||
-Wl,--wrap=gtphub_ares_init \
|
||||
-Wl,--wrap=gtphub_write \
|
||||
$(AM_LDFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
gtphub_test_LDADD = \
|
||||
|
|
|
@ -27,10 +27,11 @@
|
|||
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
#include <osmocom/sgsn/gtphub.h>
|
||||
#include <osmocom/gtphub/gtphub.h>
|
||||
#include <gtp.h>
|
||||
#include <gtpie.h>
|
||||
|
||||
|
@ -376,7 +377,7 @@ static void test_expiry(void)
|
|||
}
|
||||
|
||||
char resolve_ggsn_got_imsi[GSM23003_IMSI_MAX_DIGITS+1];
|
||||
char resolve_ggsn_got_ni[GSM_APN_LENGTH];
|
||||
char resolve_ggsn_got_ni[APN_MAXLEN+1];
|
||||
|
||||
struct sgsn_sockaddr resolved_ggsn_addr;
|
||||
static int resolve_to_ggsn(const char *addr, uint16_t port)
|
||||
|
@ -577,7 +578,7 @@ time_t now;
|
|||
static struct gtphub _hub;
|
||||
static struct gtphub *hub = &_hub;
|
||||
|
||||
static int setup_test_hub()
|
||||
static int setup_test_hub(void)
|
||||
{
|
||||
/* Not really needed, but to make 100% sure... */
|
||||
ZERO_STRUCT(hub);
|
||||
|
@ -613,7 +614,7 @@ static int setup_test_hub()
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int clear_test_hub()
|
||||
static int clear_test_hub(void)
|
||||
{
|
||||
/* expire all */
|
||||
gtphub_gc(hub, now + (60 * GTPH_EXPIRE_SLOWLY_MINUTES) + 1);
|
||||
|
@ -817,7 +818,7 @@ static void test_echo(void)
|
|||
"87" /* 135: Quality of Service (QoS) Profile */ \
|
||||
"0004" /* length */ \
|
||||
"00" /* priority */ \
|
||||
"0b921f" /* QoS profile data */
|
||||
"0b921f" /* QoS profile data */
|
||||
|
||||
#define MSG_PDP_CTX_RSP(len, tei_h, seq, restart, tei_u, tei_c, gsn_c, gsn_u) \
|
||||
"32" \
|
||||
|
@ -898,7 +899,7 @@ static int msg_from_ggsn(int plane_idx,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int create_pdp_ctx()
|
||||
static int create_pdp_ctx(void)
|
||||
{
|
||||
const char *gtp_req_from_sgsn =
|
||||
MSG_PDP_CTX_REQ("0068",
|
||||
|
|
|
@ -37,6 +37,8 @@ OsmoSGSN(config-sgsn)# list
|
|||
authentication (optional|required)
|
||||
encryption gea <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>]
|
||||
encryption uea <0-2> [<0-2>] [<0-2>]
|
||||
encryption cipher-plugin-path PATH
|
||||
no encryption cipher-plugin-path PATH
|
||||
gsup ipa-name NAME
|
||||
gsup remote-ip A.B.C.D
|
||||
gsup remote-port <0-65535>
|
||||
|
@ -55,6 +57,7 @@ OsmoSGSN(config-sgsn)# list
|
|||
ggsn dynamic
|
||||
grx-dns-add A.B.C.D
|
||||
timer [TNNNN] [(<0-2147483647>|default)]
|
||||
timer gtp [TNNNN] [(<0-2147483647>|default)]
|
||||
no compression rfc1144
|
||||
compression rfc1144 active slots <1-256>
|
||||
compression rfc1144 passive
|
||||
|
@ -117,3 +120,14 @@ sgsn
|
|||
gtp remote-ip 5.6.7.8
|
||||
...
|
||||
OsmoSGSN(config-sgsn)# no mme test1
|
||||
OsmoSGSN(config-sgsn)# encryption gea 0 3
|
||||
OsmoSGSN(config-sgsn)# encryption uea 1 2
|
||||
OsmoSGSN(config-sgsn)# encryption cipher-plugin-path /foo/bar
|
||||
OsmoSGSN(config-sgsn)# show running-config
|
||||
...
|
||||
sgsn
|
||||
...
|
||||
encryption gea 0 3
|
||||
encryption uea 1 2
|
||||
encryption cipher-plugin-path /foo/bar
|
||||
...
|
||||
|
|
|
@ -7,6 +7,7 @@ AM_CFLAGS = \
|
|||
-Wall \
|
||||
-ggdb3 \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOCTRL_CFLAGS) \
|
||||
$(LIBOSMOABIS_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(LIBOSMOGSUPCLIENT_CFLAGS) \
|
||||
|
@ -21,6 +22,8 @@ AM_CFLAGS += \
|
|||
$(NULL)
|
||||
endif
|
||||
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = \
|
||||
sgsn_test.ok \
|
||||
$(NULL)
|
||||
|
@ -29,8 +32,13 @@ check_PROGRAMS = \
|
|||
sgsn_test \
|
||||
$(NULL)
|
||||
|
||||
noinst_HEADERS = \
|
||||
gprs_gb_parse.h \
|
||||
$(NULL)
|
||||
|
||||
sgsn_test_SOURCES = \
|
||||
sgsn_test.c \
|
||||
gprs_gb_parse.c \
|
||||
$(NULL)
|
||||
|
||||
sgsn_test_LDFLAGS = \
|
||||
|
@ -39,18 +47,26 @@ sgsn_test_LDFLAGS = \
|
|||
-Wl,--wrap=gprs_subscr_request_update_location \
|
||||
-Wl,--wrap=gprs_subscr_request_auth_info \
|
||||
-Wl,--wrap=osmo_gsup_client_send \
|
||||
$(AM_LDFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
sgsn_test_LDADD = \
|
||||
$(top_builddir)/src/sgsn/apn.o \
|
||||
$(top_builddir)/src/sgsn/gprs_bssgp.o \
|
||||
$(top_builddir)/src/sgsn/gprs_llc.o \
|
||||
$(top_builddir)/src/sgsn/gprs_gb.o \
|
||||
$(top_builddir)/src/sgsn/gprs_ns.o \
|
||||
$(top_builddir)/src/sgsn/gprs_sndcp.o \
|
||||
$(top_builddir)/src/sgsn/gprs_gmm_attach.o \
|
||||
$(top_builddir)/src/sgsn/gprs_gmm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_gmm_fsm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_mm_state_gb_fsm.o \
|
||||
$(top_builddir)/src/sgsn/gprs_sgsn.o \
|
||||
$(top_builddir)/src/sgsn/gtp_ggsn.o \
|
||||
$(top_builddir)/src/sgsn/gtp_mme.o \
|
||||
$(top_builddir)/src/sgsn/mmctx.o \
|
||||
$(top_builddir)/src/sgsn/pdpctx.o \
|
||||
$(top_builddir)/src/sgsn/sgsn.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_cdr.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_ctrl.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_vty.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_libgtp.o \
|
||||
$(top_builddir)/src/sgsn/sgsn_auth.o \
|
||||
|
@ -66,11 +82,11 @@ sgsn_test_LDADD = \
|
|||
$(top_builddir)/src/sgsn/sgsn_rim.o \
|
||||
$(top_builddir)/src/gprs/gprs_utils.o \
|
||||
$(top_builddir)/src/gprs/gprs_llc_parse.o \
|
||||
$(top_builddir)/src/gprs/gprs_gb_parse.o \
|
||||
$(top_builddir)/src/gprs/crc24.o \
|
||||
$(top_builddir)/src/gprs/sgsn_ares.o \
|
||||
$(LIBOSMOABIS_LIBS) \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOCTRL_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMOGB_LIBS) \
|
||||
$(LIBOSMOGSUPCLIENT_LIBS) \
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_gb_parse.h>
|
||||
#include "gprs_gb_parse.h"
|
||||
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
|
|
@ -19,44 +19,38 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/gsup.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
|
||||
#include <osmocom/gsupclient/gsup_client.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
#include <osmocom/gsm/gsup.h>
|
||||
#include <osmocom/gsupclient/gsup_client.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
#include <osmocom/sgsn/gprs_gb_parse.h>
|
||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/sgsn/gtp_ggsn.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gprs_gb_parse.h"
|
||||
|
||||
void *tall_sgsn_ctx;
|
||||
static struct sgsn_instance sgsn_inst = {
|
||||
.config_file = "osmo_sgsn.cfg",
|
||||
.cfg = {
|
||||
.gtp_statedir = "./",
|
||||
.auth_policy = SGSN_AUTH_POLICY_CLOSED,
|
||||
.gea_encryption_mask = 0x1,
|
||||
},
|
||||
};
|
||||
struct sgsn_instance *sgsn = &sgsn_inst;
|
||||
struct sgsn_instance *sgsn;
|
||||
unsigned sgsn_tx_counter = 0;
|
||||
struct msgb *last_msg = NULL;
|
||||
struct gprs_gb_parse_context last_dl_parse_ctx;
|
||||
|
||||
static void reset_last_msg()
|
||||
static void reset_last_msg(void)
|
||||
{
|
||||
if (last_msg)
|
||||
msgb_free(last_msg);
|
||||
|
@ -65,9 +59,10 @@ static void reset_last_msg()
|
|||
memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx));
|
||||
}
|
||||
|
||||
static void cleanup_test()
|
||||
static void cleanup_test(void)
|
||||
{
|
||||
reset_last_msg();
|
||||
TALLOC_FREE(sgsn);
|
||||
}
|
||||
|
||||
static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx)
|
||||
|
@ -282,7 +277,7 @@ static void show_subscrs(FILE *out)
|
|||
}
|
||||
}
|
||||
|
||||
static void assert_no_subscrs()
|
||||
static void assert_no_subscrs(void)
|
||||
{
|
||||
show_subscrs(stdout);
|
||||
fflush(stdout);
|
||||
|
@ -384,6 +379,7 @@ static void test_auth_triplets(void)
|
|||
uint32_t local_tlli = 0xffeeddcc;
|
||||
|
||||
printf("Testing authentication triplet handling\n");
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* Check for emptiness */
|
||||
OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
|
||||
|
@ -572,6 +568,7 @@ static void test_subscriber_gsup(void)
|
|||
printf("Testing subscriber GSUP handling\n");
|
||||
|
||||
update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* Check for emptiness */
|
||||
OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
|
||||
|
@ -748,6 +745,7 @@ static void test_gmm_detach(void)
|
|||
uint32_t local_tlli;
|
||||
|
||||
printf("Testing GMM detach\n");
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* DTAP - Detach Request (MO) */
|
||||
/* normal detach, power_off = 0 */
|
||||
|
@ -789,6 +787,7 @@ static void test_gmm_detach_power_off(void)
|
|||
uint32_t local_tlli;
|
||||
|
||||
printf("Testing GMM detach (power off)\n");
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* DTAP - Detach Request (MO) */
|
||||
/* normal detach, power_off = 1 */
|
||||
|
@ -829,6 +828,7 @@ static void test_gmm_detach_no_mmctx(void)
|
|||
uint32_t local_tlli;
|
||||
|
||||
printf("Testing GMM detach (no MMCTX)\n");
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* DTAP - Detach Request (MO) */
|
||||
/* normal detach, power_off = 0 */
|
||||
|
@ -865,6 +865,7 @@ static void test_gmm_detach_accept_unexpected(void)
|
|||
uint32_t local_tlli;
|
||||
|
||||
printf("Testing GMM detach accept (unexpected)\n");
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* DTAP - Detach Accept (MT) */
|
||||
/* normal detach */
|
||||
|
@ -901,6 +902,7 @@ static void test_gmm_status_no_mmctx(void)
|
|||
uint32_t local_tlli;
|
||||
|
||||
printf("Testing GMM Status (no MMCTX)\n");
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* DTAP - GMM Status, protocol error */
|
||||
static const unsigned char gmm_status[] = {
|
||||
|
@ -1195,6 +1197,7 @@ static void test_gmm_reject(void)
|
|||
};
|
||||
|
||||
printf("Testing GMM reject\n");
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* reset the PRNG used by sgsn_alloc_ptmsi */
|
||||
srand(1);
|
||||
|
@ -1241,6 +1244,9 @@ static void test_gmm_cancel(void)
|
|||
uint32_t foreign_tlli;
|
||||
uint32_t local_tlli = 0;
|
||||
struct gprs_llc_lle *lle;
|
||||
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
sgsn->cfg.gea_encryption_mask = 0x1;
|
||||
const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
|
||||
|
||||
/* DTAP - Attach Request */
|
||||
|
@ -1271,8 +1277,7 @@ static void test_gmm_cancel(void)
|
|||
};
|
||||
|
||||
printf("Testing cancellation\n");
|
||||
|
||||
sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
|
||||
sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
|
||||
|
||||
foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
|
||||
|
||||
|
@ -1344,6 +1349,7 @@ static void test_apn_matching(void)
|
|||
struct apn_ctx *actx, *actxs[9];
|
||||
|
||||
printf("Testing APN matching\n");
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
|
||||
actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
|
||||
|
@ -1433,9 +1439,6 @@ static void test_apn_matching(void)
|
|||
cleanup_test();
|
||||
}
|
||||
|
||||
struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
|
||||
struct sgsn_subscriber_data *sdata);
|
||||
|
||||
static void test_ggsn_selection(void)
|
||||
{
|
||||
struct apn_ctx *actxs[4];
|
||||
|
@ -1454,6 +1457,7 @@ static void test_ggsn_selection(void)
|
|||
printf("Testing GGSN selection\n");
|
||||
|
||||
osmo_gsup_client_send_cb = my_gsup_client_send_dummy;
|
||||
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
|
||||
|
||||
/* Check for emptiness */
|
||||
OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
|
||||
|
@ -1472,9 +1476,9 @@ static void test_ggsn_selection(void)
|
|||
|
||||
/* TODO: Add PDP info entries to s1 */
|
||||
|
||||
ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
|
||||
ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
|
||||
ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
|
||||
ggcs[0] = sgsn_ggsn_ctx_find_alloc(sgsn, 0);
|
||||
ggcs[1] = sgsn_ggsn_ctx_find_alloc(sgsn, 1);
|
||||
ggcs[2] = sgsn_ggsn_ctx_find_alloc(sgsn, 2);
|
||||
|
||||
actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
|
||||
actxs[0]->ggsn = ggcs[0];
|
||||
|
@ -1485,13 +1489,14 @@ static void test_ggsn_selection(void)
|
|||
|
||||
pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
|
||||
pdp_data->context_id = 1;
|
||||
pdp_data->pdp_type = 0x0121;
|
||||
pdp_data->pdp_type_org = PDP_TYPE_ORG_IETF;
|
||||
pdp_data->pdp_type_nr = PDP_TYPE_N_IETF_IPv4;
|
||||
osmo_strlcpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str));
|
||||
|
||||
/* Resolve GGSNs */
|
||||
|
||||
tp.lv[GSM48_IE_GSM_APN].len =
|
||||
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
|
||||
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
|
||||
|
||||
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
|
||||
OSMO_ASSERT(ggc != NULL);
|
||||
|
@ -1499,7 +1504,7 @@ static void test_ggsn_selection(void)
|
|||
OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
|
||||
|
||||
tp.lv[GSM48_IE_GSM_APN].len =
|
||||
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
|
||||
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
|
||||
|
||||
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
|
||||
OSMO_ASSERT(ggc != NULL);
|
||||
|
@ -1525,7 +1530,7 @@ static void test_ggsn_selection(void)
|
|||
tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
|
||||
|
||||
tp.lv[GSM48_IE_GSM_APN].len =
|
||||
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
|
||||
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Foo.Bar");
|
||||
|
||||
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
|
||||
OSMO_ASSERT(ggc == NULL);
|
||||
|
@ -1542,7 +1547,7 @@ static void test_ggsn_selection(void)
|
|||
osmo_strlcpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str));
|
||||
|
||||
tp.lv[GSM48_IE_GSM_APN].len =
|
||||
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
|
||||
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
|
||||
|
||||
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
|
||||
OSMO_ASSERT(ggc != NULL);
|
||||
|
@ -1550,7 +1555,7 @@ static void test_ggsn_selection(void)
|
|||
OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
|
||||
|
||||
tp.lv[GSM48_IE_GSM_APN].len =
|
||||
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
|
||||
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
|
||||
|
||||
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
|
||||
OSMO_ASSERT(ggc == NULL);
|
||||
|
@ -1652,11 +1657,7 @@ int main(int argc, char **argv)
|
|||
tall_sgsn_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "sgsn");
|
||||
msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
|
||||
|
||||
sgsn_rate_ctr_init();
|
||||
sgsn_auth_init(sgsn);
|
||||
gprs_subscr_init(sgsn);
|
||||
vty_init(&vty_info);
|
||||
sgsn_vty_init(&sgsn->cfg);
|
||||
|
||||
test_llme();
|
||||
test_subscriber();
|
||||
|
@ -1676,7 +1677,7 @@ int main(int argc, char **argv)
|
|||
|
||||
talloc_report_full(osmo_sgsn_ctx, stderr);
|
||||
OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
|
||||
OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 2);
|
||||
OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
|
||||
AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = slhc_test.ok
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
|
||||
AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = sndcp_xid_test.ok
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
|
||||
AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = v42bis_test.ok
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ AM_CFLAGS = \
|
|||
$(LIBCARES_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = \
|
||||
xid_test.ok \
|
||||
$(NULL)
|
||||
|
|
Loading…
Reference in New Issue