aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--README.md127
-rw-r--r--TODO-RELEASE13
-rw-r--r--configure.ac12
-rw-r--r--contrib/osmo-ggsn.init97
-rw-r--r--contrib/osmo-ggsn.spec.in137
-rw-r--r--contrib/systemd/osmo-ggsn.service4
-rw-r--r--debian/changelog45
-rw-r--r--debian/control14
-rw-r--r--debian/libgtp10.install (renamed from debian/libgtp6.install)0
-rwxr-xr-xdebian/osmo-ggsn.init163
-rwxr-xr-xdebian/postinst39
-rwxr-xr-xdebian/rules2
-rw-r--r--doc/examples/osmo-ggsn-kernel-gtp.cfg8
-rw-r--r--doc/examples/osmo-ggsn.cfg8
-rw-r--r--doc/manuals/chapters/configuration.adoc4
-rw-r--r--ggsn/Makefile.am1
-rw-r--r--ggsn/ggsn.c46
-rw-r--r--ggsn/ggsn.h2
-rw-r--r--ggsn/ggsn_vty.c12
-rw-r--r--ggsn/pco.h2
-rw-r--r--ggsn/sgsn.c2
-rw-r--r--ggsn/sgsn.h2
-rw-r--r--gtp/Makefile.am11
-rw-r--r--gtp/gsn.c16
-rw-r--r--gtp/gsn_internal.h3
-rw-r--r--gtp/gtp.c307
-rw-r--r--gtp/gtp_internal.h3
-rw-r--r--gtp/gtpie.c2
-rw-r--r--gtp/pdp.c6
-rw-r--r--gtp/queue.c6
-rw-r--r--gtp/queue.h2
-rw-r--r--include/Makefile.am3
-rw-r--r--include/osmocom/Makefile.am3
-rw-r--r--include/osmocom/gtp/Makefile.am8
-rw-r--r--include/osmocom/gtp/gsn.h (renamed from gtp/gsn.h)6
-rw-r--r--include/osmocom/gtp/gtp.h (renamed from gtp/gtp.h)54
-rw-r--r--include/osmocom/gtp/gtpie.h (renamed from gtp/gtpie.h)0
-rw-r--r--include/osmocom/gtp/pdp.h (renamed from gtp/pdp.h)7
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/gtp-kernel.c5
-rw-r--r--lib/icmpv6.c7
-rw-r--r--lib/icmpv6.h4
-rw-r--r--lib/in46_addr.c2
-rw-r--r--lib/in46_addr.h2
-rw-r--r--lib/ippool.h2
-rw-r--r--lib/util.c2
-rw-r--r--libgtp.pc.in5
-rw-r--r--sgsnemu/Makefile.am1
-rw-r--r--sgsnemu/sgsnemu.c6
-rw-r--r--tests/gtp/gtpie_test.c3
51 files changed, 486 insertions, 733 deletions
diff --git a/Makefile.am b/Makefile.am
index 5db4ac6..ccd1e31 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,6 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = \
+ include \
lib \
gtp \
ggsn \
@@ -24,7 +25,6 @@ EXTRA_DIST = \
README.FreeBSD \
README.MacOSX \
README.md \
- contrib/osmo-ggsn.spec.in \
debian \
git-version-gen \
$(NULL)
diff --git a/README.md b/README.md
index 52f993e..2a924f0 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,8 @@ GPRS Support Node), a core network element of ETSI/3GPP cellular
networks such as GPRS, EDGE, UMTS or HSPA.
**OsmoGGSN** is part of the [Osmocom](https://osmocom.org/) Open Source
-Mobile Communications projects and the successor to OpenGGSN.
-OpenGGSN was developed until 2004 by Mondru AB.
+Mobile Communications projects and the successor to OpenGGSN (which was
+developed until 2004 by Mondru AB).
Homepage
--------
@@ -63,7 +63,7 @@ Contributing
Our coding standards are described at
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
-We us a gerrit based patch submission/review process for managing
+We use a Gerrit based patch submission/review process for managing
contributions. Please see
<https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for
more details
@@ -89,61 +89,33 @@ The tun driver is required for proper operation of openggsn. For Linux
kernels later than 2.4.7 the driver is typically included, but might
need to be configured for automatic loading:
-1. Add the following line to /etc/modules.conf: alias char-major-10-200 tun
-2. depmod -a
+1. Add the following line to `/etc/modules.conf`: `alias char-major-10-200 tun`
+2. `depmod -a`
Installation from binary
------------------------
-OsmoGGSN is built for common versions of Debian and Ubuntu as part of
+OsmoGGSN is built for common versions of Debian, Ubuntu and other distributions part of
the [Osmocom Nightly Builds](https://osmocom.org/projects/cellular-infrastructure/wiki/Nightly_Builds)
-project. If you don't want to do development, it is suggested to simply
-use those binary packages, rather than building yourself from source.
+and [Osmocom Latest Builds](https://osmocom.org/projects/cellular-infrastructure/wiki/Latest_Builds).
+If you don't want to do development, it is suggested to simply use those binary packages, rather than building
+yourself from source.
Installation from source
------------------------
-1. ./configure
-2. make
-3. make install
+```
+./configure
+make
+make install
+```
You need to be root in order to install the package, but not in order
to compile.
-Running
--------
-
-*sgsnemu*
-Start the emulator as root using the command:
-
- sgsnemu -l 10.0.0.50 -r 10.0.0.40 --createif --defaultroute
-
-This will cause the sgsn emulator to bind to local address 10.0.0.50
-and connect to the ggsn found at 10.0.0.40. It will first send off an
-ECHO_REQUEST message. After this it will attempt to establish a pdp
-context. If successful it will create a local interface and set up
-routing. Now you should be able to ping through the connection. Use a
-network analysator such as ethereal to monitor the traffic.
-
-sgsnemu -h will show a list of available options.
-
-sgsnemu -c sgsnemu.conf will use sgsnemu.conf as a configuration
-file. A sample file is provided in examples/sgsnemu.conf.
-
-*ggsn*
-Edit the configuration file ggsn.conf found under openggsn/examples.
-Start the ggsn as root using the command:
-
-ggsn --fg -c examples/ggsn.conf -l 10.0.0.40 --statedir ./
-
-This will run the ggsn in foreground using the local interface
-10.0.0.40. If you don't have a GSM network available for testing you
-can use sgsnemu to test the GGSN.
-
-
Support
-------
@@ -158,9 +130,10 @@ OsmoGGSN is an open source implementation of GPRS Support Nodes
version 1.
OsmoGGSN provides 3 components:
- * gtplib
- * osmo-ggsn
- * sgsnemu
+
+ * *libgtp*, a shared library for the GTPv1C protocol
+ * *osmo-ggsn*, the GGSN itself
+ * *sgsnemu*, a SGSN emulator
*gtplib*
This library contains all functionality relating to the GTP
@@ -196,10 +169,10 @@ Both osmo-ggsn and sgsnemu uses the tun package. You need at least tun
version 1.1. With Linux tun is normally included from kernel version
2.4.7. To configure automatic loading:
-1. Add the following line to /etc/modules.conf: alias char-major-10-200 tun
-2. depmod -a
+1. Add the following line to `/etc/modules.conf`: `alias char-major-10-200 tun`
+2. `depmod -a`
-Alternatively you can execute "modprobe tun" on the commandline.
+Alternatively you can execute `modprobe tun` on the commandline.
Gengetopt
---------
@@ -209,11 +182,13 @@ cmdline.ggo source file. You need at least gengetopt version 2.8. If
you are just going to compile the programs you don't need gengetopt.
To use gengetopt for the sgsnemu do the following:
+```
cd sgsnemu
gengetopt < cmdline.ggo --conf-parser
+```
For more information about gengetopt see
-http://www.gnu.org/software/gengetopt/gengetopt.html
+<http://www.gnu.org/software/gengetopt/gengetopt.html>
Compilation and Installation
@@ -227,27 +202,21 @@ Running osmo-ggsn
Use osmo-ggsn -h for a list of available options. All options available on
the command line can also be given in a configuration file. See
-examples/osmo-ggsn.cfg for the format of this file.
+`doc/examples/osmo-ggsn.cfg` for the format of this file.
Start osmo-ggsn as root using the command:
-osmo-ggsn -c examples/osmo-ggsn.cfg
+`osmo-ggsn -c doc/examples/osmo-ggsn.cfg`
-First a tun network interface will be created. In the above example
-the network interface address is 192.168.0.0 and the mask is
-255.255.255.0. You can check that this interface is up by using
-ifconfig.
+First, a tun network interface will be created for each configured apn.
After tun has been successfully established the ggsn will wait for GTP
-create PDP context requests on the local interface
-10.0.0.40. Currently all requests are accepted, and no password,
-username or APN validation is performed.
+create PDP context requests on the configured `gtp bind-ip` address.
+Currently all requests are accepted, and no password, username validation is performed.
-When receiving a create PDP context request a dynamic IP address will
-be allocated from the address pool determined by --dynip. In the above
-example the first allocated address will be 192.168.0.1, followed by
-192.168.0.2 and so on. The request is confirmed by sending a create
-PDP context response message to the peer (SGSN).
+When receiving a create PDP context request for a given APN, a dynamic IP address will
+be allocated from the address pool defined in the config file section for that apn.
+The request is confirmed by sending a create PDP context response message to the peer (SGSN).
Now IP packets will be forwarded between the tun network interface and
the established GTP tunnel. In order to allow users to access the
@@ -255,22 +224,22 @@ external network routing needs to be set up. If private addresses are
used you need to configure network address translation. See the Linux
Networking HOWTO for details.
-Remember to enable routing:
+Remember to enable routing:
-echo 1 > /proc/sys/net/ipv4/ip_forward
+`echo 1 > /proc/sys/net/ipv4/ip_forward`
-If you installed using a binary RPM package it is possible to start
-osmo-ggsn by using the Sys 5 script:
+If you're using systemd and did `make install` or installed from a bianry package,
+you can start osmo-ggsn by using the included systemd service/unit file:
-/etc/init.d/osmo-ggsn start
+`systemctl start osmo-ggsn`
Running sgsnemu
===============
-Use sgsnemu -h for a list of available options. All options available
+Use `sgsnemu -h` for a list of available options. All options available
on the command line can also be given in a configuration file. See
-examples/sgsnemu.conf for the format of this file.
+`doc/examples/sgsnemu.conf` for the format of this file.
If you want to test a GRX roaming connection you will need to do the
following:
@@ -283,11 +252,11 @@ subnet mask and default route. See the Linux Networking HOWTO for
details.
4. Launch sgsnemu with something like:
-sgsnemu --listen 10.0.0.50 --remote 10.0.0.40 --dns 10.20.38.51 --timelimit 10 --contexts 0
+`sgsnemu --listen 10.0.0.50 --remote 10.0.0.40 --dns 10.20.38.51 --timelimit 10 --contexts 0`
sgsnemu will print something like the following on the screen:
-
+```
Using DNS server: 10.20.38.51 (10.20.38.51)
Local IP address is: 10.0.0.50 (10.0.0.50)
Remote IP address is: 10.0.0.40 (10.0.0.40)
@@ -303,6 +272,7 @@ sgsnemu will print something like the following on the screen:
Waiting for response from ggsn........
Received echo response. Cause value: 0
+```
This is quite good. It means that you managed to send off an echo
request to a remote GGSN, and it was friendly enough to answer you. If
@@ -320,10 +290,11 @@ testing. Also note that you are establishing a connection to the Gi
network, so please be carefull not to route internet traffic onto the
GPRS core network! Assuming you know what you are doing:
-sgsnemu --listen 10.0.0.50 --remote 10.0.0.40 --dns 10.20.38.51 --timelimit 10 --contexts 1 --apn internet --imsi 240011234567890 --msisdn 46702123456 --createif --defaultroute
+`sgsnemu --listen 10.0.0.50 --remote 10.0.0.40 --dns 10.20.38.51 --timelimit 10 --contexts 1 --apn internet --imsi 240011234567890 --msisdn 46702123456 --createif --defaultroute`
sgsnemu will print something like the following on the screen:
+```
Using DNS server: 10.20.38.51 (10.20.38.51)
Local IP address is: 10.0.0.50 (10.0.0.50)
Remote IP address is: 10.0.0.40 (10.0.0.40)
@@ -344,7 +315,7 @@ sgsnemu will print something like the following on the screen:
Setting up interface and routing
/sbin/ifconfig tun0 192.168.0.1
/sbin/route add -net 192.168.0.0 netmask 255.255.255.0 gw 192.168.0.1
-
+```
Now a context is established to the remote GGSN. The IP address of the
context is 192.168.0.1. You should be able to ping a known address on
@@ -358,13 +329,13 @@ do this is to use policy routing. Also note that you are effectively
connecting the same computer to both the Gn and Gi network, so please
be carefull not to route internet traffic onto the GPRS core network
and please protect yourself against hackers! For this reason it is
-advised to always use --contexts 0 when testing a live network.
+advised to always use `--contexts 0` when testing a live network.
-After --timelimit seconds the PDP context is disconnected with the
+After `--timelimit seconds` the PDP context is disconnected with the
following messages from sgsnemu:
-
+```
Disconnecting PDP context #0
Received delete PDP context response. Cause value: 128
Deleting tun interface
-
+```
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 22cfd1d..905c234 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -1,11 +1,12 @@
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
-# according to https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
-# In short:
+# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
+# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
# LIBVERSION=c:r:a
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
-# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0.
+# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
-#library what description / commit summary line
-libgtp REMOVE remove GTP cause defines of reserved values
-libgtpnl > 1.2.5 gtp_tunnel_set_family()
+#library what description / commit summary line
+libgtp append new field dir_tun_flags in struct pdp_t (older users not using the field should be fine since struct pdp_t is allocated internally)
+libgtp ABI break new field cb_create_context_ind in struct gsn_t
+libgtp new API gtp_set_cb_update_context_ind(), gtp_update_context_resp() \ No newline at end of file
diff --git a/configure.ac b/configure.ac
index ae93974..945075a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -71,7 +71,7 @@ AC_ARG_ENABLE([gtp-linux],
[enable_gtp_linux="$enableval"], [enable_gtp_linux="no"])
AS_IF([test "x$enable_gtp_linux" = "xyes"], [
- PKG_CHECK_MODULES([LIBGTPNL], [libgtpnl >= 1.2.0])
+ PKG_CHECK_MODULES([LIBGTPNL], [libgtpnl >= 1.3.0])
])
AM_CONDITIONAL([ENABLE_GTP_KERNEL], [test "$enable_gtp_linux" = "yes"])
@@ -154,9 +154,9 @@ adl_FUNC_GETOPT_LONG
AM_INIT_AUTOMAKE([foreign])
-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(LIBOSMOCORE, libosmocore >= 1.10.0)
+PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.10.0)
+PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.10.0)
AC_ARG_ENABLE(sanitize,
[AS_HELP_STRING(
@@ -262,10 +262,12 @@ AC_CONFIG_FILES([Makefile
doc/manuals/Makefile
contrib/Makefile
contrib/systemd/Makefile
- contrib/osmo-ggsn.spec
tests/Makefile
tests/lib/Makefile
tests/gtp/Makefile
+ include/Makefile
+ include/osmocom/Makefile
+ include/osmocom/gtp/Makefile
libgtp.pc])
AC_OUTPUT
diff --git a/contrib/osmo-ggsn.init b/contrib/osmo-ggsn.init
deleted file mode 100644
index 2deb378..0000000
--- a/contrib/osmo-ggsn.init
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/bin/sh
-#
-# osmo-ggsn This shell script takes care of starting and stopping
-# osmo-ggsn.
-#
-# chkconfig: - 65 35
-# description: osmo-ggsn is a Gateway GPRS Support Node.
-
-# Source function library.
-. /etc/rc.d/init.d/functions
-
-# Source networking configuration.
-. /etc/sysconfig/network
-
-if [ -f /etc/sysconfig/osmo-ggsn ]; then
- . /etc/sysconfig/osmo-ggsn
-fi
-
-# Check that networking is up.
-[ ${NETWORKING} = "no" ] && exit 0
-
-[ -f /usr/bin/osmo-ggsn ] || exit 0
-[ -f /etc/osmo-ggsn.cfg ] || exit 0
-
-RETVAL=0
-prog="osmo-ggsn"
-
-start() {
- # Start daemons.
- echo -n $"Starting $prog: "
-
- # Load tun module
- /sbin/modprobe tun >/dev/null 2>&1
-
- # Enable routing of packets: WARNING!!!
- # Users should enable this explicitly
- # echo 1 > /proc/sys/net/ipv4/ip_forward
-
- # Check for runtime directory of nonvolatile data
- if [ ! -d /var/lib/osmo-ggsn ]; then
- mkdir /var/lib/osmo-ggsn
- fi
-
- # Check for GTP restart counter
- if [ ! -d /var/lib/osmo-ggsn/gsn_restart ]; then
- echo 0 > /var/lib/osmo-ggsn/gsn_restart
- fi
-
-
- daemon /usr/bin/osmo-ggsn
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/osmo-ggsn
- return $RETVAL
-}
-
-stop() {
- # Stop daemons.
- echo -n $"Shutting down $prog: "
- killproc osmo-ggsn
- RETVAL=$?
- echo
- [ $RETVAL = 0 ] && rm -f /var/lock/subsys/osmo-ggsn /var/run/osmo-ggsn.pid
- return $RETVAL
-}
-
-# See how we were called.
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- restart|reload)
- stop
- start
- RETVAL=$?
- ;;
- condrestart)
- if [ -f /var/lock/subsys/osmo-ggsn ] ; then
- stop
- start
- RETVAL=$?
- fi
- ;;
- status)
- status osmo-ggsn
- RETVAL=$?
- ;;
- *)
- echo $"Usage: $0 {start|stop|restart|condrestart|status}"
- exit 1
-esac
-
-exit $RETVAL
-
diff --git a/contrib/osmo-ggsn.spec.in b/contrib/osmo-ggsn.spec.in
deleted file mode 100644
index 8334e4b..0000000
--- a/contrib/osmo-ggsn.spec.in
+++ /dev/null
@@ -1,137 +0,0 @@
-#
-# spec file for package osmo-ggsn
-#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
-#
-# 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/4114
-%define _lto_cflags %{nil}
-
-Name: osmo-ggsn
-Version: @VERSION@
-Release: 0
-Summary: GPRS Support Node
-License: GPL-2.0-only AND LGPL-2.1-or-later
-Group: Productivity/Telephony/Servers
-URL: https://osmocom.org/projects/openggsn
-Source: %{name}-%{version}.tar.xz
-BuildRequires: libtool >= 2
-BuildRequires: pkgconfig >= 0.20
-%if 0%{?suse_version}
-BuildRequires: systemd-rpm-macros
-%endif
-BuildRequires: pkgconfig(libgtpnl) >= 1.2.0
-BuildRequires: pkgconfig(libosmocore) >= 1.9.0
-BuildRequires: pkgconfig(libosmoctrl) >= 1.9.0
-BuildRequires: pkgconfig(libosmovty) >= 1.9.0
-Obsoletes: openggsn
-%{?systemd_requires}
-
-%description
-Osmo-GGSN is a C-language implementation of a GGSN (Gateway GPRS
-Support Node), a core network element of ETSI/3GPP cellular networks
-such as GPRS, EDGE, UMTS or HSPA.
-
-%package -n libgtp6
-Summary: Library implementing GTP between SGSN and GGSN
-License: GPL-2.0-only
-Group: System/Libraries
-
-%description -n libgtp6
-libgtp implements the GPRS Tunneling Protocol between SGSN and GGSN.
-
-%package -n libgtp-devel
-Summary: Development files for the GTP library
-License: GPL-2.0-only
-Group: Development/Libraries/C and C++
-Requires: libgtp6 = %{version}
-
-%description -n libgtp-devel
-libgtp implements the GPRS Tunneling Protocol between SGSN and GGSN.
-
-This subpackage contains libraries and header files for developing
-applications that want to make use of libgtp.
-
-%package -n gtp-echo-responder
-Summary: Small program answering GTP ECHO Request with GTP ECHO Response
-License: MIT
-Group: System/Libraries
-
-%description -n gtp-echo-responder
-Small program answering GTP ECHO Request with GTP ECHO Response for both GTPCv1
-and GTPCv2.
-
-%prep
-%setup -q
-
-%build
-echo "%{version}" >.tarball-version
-autoreconf -fi
-%configure \
- --enable-gtp-linux \
- --disable-static \
- --docdir="%{_docdir}/%{name}" \
- --with-systemdsystemunitdir=%{_unitdir} \
- --includedir="%{_includedir}/%{name}"
-make %{?_smp_mflags} V=1
-
-%install
-%make_install
-find %{buildroot} -type f -name "*.la" -delete -print
-
-%check
-make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
-
-%if 0%{?suse_version}
-%pre
-%service_add_pre %{name}.service
-
-%post
-%service_add_post %{name}.service
-
-%preun
-%service_del_preun %{name}.service
-
-%postun
-%service_del_postun %{name}.service
-%endif
-
-%post -n libgtp6 -p /sbin/ldconfig
-%postun -n libgtp6 -p /sbin/ldconfig
-
-%files
-%license COPYING
-%doc AUTHORS README.md
-%{_bindir}/osmo-ggsn
-%{_bindir}/sgsnemu
-%{_mandir}/man8/osmo-ggsn.8%{?ext_man}
-%{_mandir}/man8/sgsnemu.8%{?ext_man}
-%{_unitdir}/%{name}.service
-%dir %{_docdir}/%{name}/examples
-%{_docdir}/%{name}/examples/osmo-ggsn-kernel-gtp.cfg
-%{_docdir}/%{name}/examples/osmo-ggsn.cfg
-%{_docdir}/%{name}/examples/sgsnemu.conf
-%dir %{_sysconfdir}/osmocom
-%config(noreplace) %{_sysconfdir}/osmocom/osmo-ggsn.cfg
-
-%files -n libgtp6
-%{_libdir}/libgtp.so.6*
-
-%files -n libgtp-devel
-%{_includedir}/%{name}/
-%{_libdir}/libgtp.so
-%{_libdir}/pkgconfig/libgtp.pc
-
-%files -n gtp-echo-responder
-%{_bindir}/gtp-echo-responder
-
-%changelog
diff --git a/contrib/systemd/osmo-ggsn.service b/contrib/systemd/osmo-ggsn.service
index 1a7acba..cf7b7e6 100644
--- a/contrib/systemd/osmo-ggsn.service
+++ b/contrib/systemd/osmo-ggsn.service
@@ -11,6 +11,10 @@ WorkingDirectory=%S/osmocom
ExecStart=/usr/bin/osmo-ggsn -c /etc/osmocom/osmo-ggsn.cfg
RestartSec=2
RestartPreventExitStatus=1
+User=osmocom
+Group=osmocom
+# For setting up the gtp0/tun0 devices
+AmbientCapabilities=CAP_NET_ADMIN
[Install]
WantedBy=multi-user.target
diff --git a/debian/changelog b/debian/changelog
index 9eb37fd..d36f674 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,48 @@
+osmo-ggsn (1.12.0) unstable; urgency=medium
+
+ [ Daniel Willmann ]
+ * libgtp: Remove defines for reserved causes in gtp.h
+
+ [ Pau Espin Pedrol ]
+ * pco: Improve IPCP spec reference documentation
+
+ [ Oliver Smith ]
+ * Fix a typo
+ * gtp_new: deduplicate create_and_bind_socket code
+ * kernel-gtp: support IPv6 on outer layer
+ * kernel-gtp: support IPv6 on inner layer
+ * Revert "kernel-gtp: support IPv6 on outer layer"
+ * Cosmetic: Makefile.am: make SUBDIRS diff friendly
+ * Cosmetic: AM_CFLAGS: make diff friendly
+ * Cosmetic: {lib,gtp}/Makefile.am: diff friendly
+ * lib/gtp-kernel.c: initialize ret with 0
+ * lib/gtp-kernel.c: check rc of in46a_from_eua
+ * doc: fix typo ndoe -> node
+ * Add clear error for kernel not supporting IPv6
+ * contrib: remove rpm spec file
+ * libgtp: move includes to osmocom/include/gtp
+ * gtp/gsn_internal.h: new file
+ * gtp/gtp.c: move gtp_create_context_resp down
+ * gtp: remove unused conversion functions
+ * gtp: move conversion functions up
+ * gtp/gtp_internal.h: new file
+ * ggsn/ggsn_vty: create state-dir
+ * doc: set state-dir to /var/lib/osmocom/osmo-ggsn
+ * contrib/systemd: run as osmocom user
+ * Use uniform log format for default config files
+ * {contrib,debian}/osmo-ggsn.init: remove
+
+ [ Harald Welte ]
+ * Add funding link to github mirror
+ * README.md: Improve markdown formatting
+ * README.md: Add Forum + Issue Tracker sections
+ * README.md: Major overhaul
+
+ [ Vadim Yanitskiy ]
+ * README.md: cosmetic: fix a typo
+
+ -- Oliver Smith <osmith@sysmocom.de> Wed, 24 Jul 2024 15:13:31 +0200
+
osmo-ggsn (1.11.0) unstable; urgency=medium
[ Daniel Willmann ]
diff --git a/debian/control b/debian/control
index e802d62..e2f801e 100644
--- a/debian/control
+++ b/debian/control
@@ -7,9 +7,9 @@ Build-Depends: debhelper (>= 10),
pkg-config,
libdpkg-perl, git,
dh-autoreconf,
- libosmocore-dev (>= 1.9.0),
- osmo-gsm-manuals-dev,
- libgtpnl-dev (>= 1.2.0)
+ libosmocore-dev (>= 1.10.0),
+ osmo-gsm-manuals-dev (>= 1.6.0),
+ libgtpnl-dev (>= 1.3.0)
Standards-Version: 3.9.6
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn
@@ -24,7 +24,7 @@ Description: Osmocom Gateway GPRS Support Node (GGSN)
operators as the interface between the Internet and the rest of the
mobile network infrastructure.
-Package: libgtp6
+Package: libgtp10
Architecture: any
Multi-Arch: same
Section: libs
@@ -49,7 +49,7 @@ Architecture: any
Multi-Arch: same
Section: libdevel
Depends: ${misc:Depends},
- libgtp6 (= ${binary:Version})
+ libgtp10 (= ${binary:Version})
Description: Development files for libgtp
OsmoGGSN is a Gateway GPRS Support Node (GGSN). It is used by mobile
operators as the interface between the Internet and the rest of the
@@ -62,7 +62,7 @@ Package: osmo-ggsn-dbg
Section: debug
Architecture: any
Priority: extra
-Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp6 (= ${binary:Version}), osmo-ggsn (= ${binary:Version})
+Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp10 (= ${binary:Version}), osmo-ggsn (= ${binary:Version})
Multi-Arch: same
Description: Debug symbols for OsmoGGSN
OsmoGGSN is a Gateway GPRS Support Node (GGSN). It is used by mobile
@@ -82,7 +82,7 @@ Package: libgtp-dbg
Section: debug
Architecture: any
Priority: extra
-Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp6 (= ${binary:Version})
+Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp10 (= ${binary:Version})
Multi-Arch: same
Description: Debug symbols for OsmoGGSN
OsmoGGSN is a Gateway GPRS Support Node (GGSN). It is used by mobile
diff --git a/debian/libgtp6.install b/debian/libgtp10.install
index 3ddde58..3ddde58 100644
--- a/debian/libgtp6.install
+++ b/debian/libgtp10.install
diff --git a/debian/osmo-ggsn.init b/debian/osmo-ggsn.init
deleted file mode 100755
index 6fe1b87..0000000
--- a/debian/osmo-ggsn.init
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/bin/sh
-### BEGIN INIT INFO
-# Provides: osmo-ggsn
-# Required-Start: $network $local_fs $remote_fs
-# Required-Stop: $network $remote_fs
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: Gateway GPRS Support Node
-# Description: Gateway GPRS Support Node
-### END INIT INFO
-
-# Author: Harald Welte <laforge@gnumonks.org>
-
-# PATH should only include /usr/* if it runs after the mountnfs.sh script
-PATH=/sbin:/usr/sbin:/bin:/usr/bin
-DESC="OsmoGGSN Gateway GPRS Support Node"
-NAME=ggsn
-DAEMON=/usr/bin/osmo-ggsn
-DAEMON_ARGS="" # Arguments to run the daemon with
-PIDFILE=/var/run/$NAME.pid
-SCRIPTNAME=/etc/init.d/osmo-ggsn
-
-# Exit if the package is not installed
-[ -x $DAEMON ] || exit 0
-
-# Read configuration variable file if it is present
-[ -r /etc/default/osmo-ggsn ] && . /etc/default/osmo-ggsn
-
-# Load the VERBOSE setting and other rcS variables
-. /lib/init/vars.sh
-# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
-. /lib/lsb/init-functions
-
-DAEMON_ARGS="$DAEMON_ARGS"
-
-#
-# Function that starts the daemon/service
-#
-do_start()
-{
- # Return
- # 0 if daemon has been started
- # 1 if daemon was already running
- # 2 if daemon could not be started
- start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
- || return 1
-
- # Check for runtime directory of nonvolatile data
- if [ ! -d /var/lib/osmo-ggsn ]; then
- mkdir /var/lib/osmo-ggsn
- fi
-
- # Check for GTP restart counter
- if [ ! -f /var/lib/osmo-ggsn/gsn_restart ]; then
- echo 0 > /var/lib/osmo-ggsn/gsn_restart
- fi
-
- start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
- $DAEMON_ARGS \
- || return 2
- # Add code here, if necessary, that waits for the process to be ready
- # to handle requests from services started subsequently which depend
- # on this one. As a last resort, sleep for some time.
-}
-
-#
-# Function that stops the daemon/service
-#
-do_stop()
-{
- # Return
- # 0 if daemon has been stopped
- # 1 if daemon was already stopped
- # 2 if daemon could not be stopped
- # other if a failure occurred
- start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
- RETVAL="$?"
- [ "$RETVAL" = 2 ] && return 2
- # Wait for children to finish too if this is a daemon that forks
- # and if the daemon is only ever run from this initscript.
- # If the above conditions are not satisfied then add some other code
- # that waits for the process to drop all resources that could be
- # needed by services started subsequently. A last resort is to
- # sleep for some time.
- start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
- [ "$?" = 2 ] && return 2
- # Many daemons don't delete their pidfiles when they exit.
- rm -f $PIDFILE
- return "$RETVAL"
-}
-
-#
-# Function that sends a SIGHUP to the daemon/service
-#
-do_reload() {
- #
- # If the daemon can reload its configuration without
- # restarting (for example, when it is sent a SIGHUP),
- # then implement that here.
- #
- start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
- return 0
-}
-
-case "$1" in
- start)
- [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
- do_start
- case "$?" in
- 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
- 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
- esac
- ;;
- stop)
- [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
- do_stop
- case "$?" in
- 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
- 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
- esac
- ;;
- status)
- status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
- ;;
- #reload|force-reload)
- #
- # If do_reload() is not implemented then leave this commented out
- # and leave 'force-reload' as an alias for 'restart'.
- #
- #log_daemon_msg "Reloading $DESC" "$NAME"
- #do_reload
- #log_end_msg $?
- #;;
- restart|force-reload)
- #
- # If the "reload" option is implemented then remove the
- # 'force-reload' alias
- #
- log_daemon_msg "Restarting $DESC" "$NAME"
- do_stop
- case "$?" in
- 0|1)
- do_start
- case "$?" in
- 0) log_end_msg 0 ;;
- 1) log_end_msg 1 ;; # Old process is still running
- *) log_end_msg 1 ;; # Failed to start
- esac
- ;;
- *)
- # Failed to stop
- log_end_msg 1
- ;;
- esac
- ;;
- *)
- #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
- echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
- exit 3
- ;;
-esac
-
-:
diff --git a/debian/postinst b/debian/postinst
new file mode 100755
index 0000000..9cd0c77
--- /dev/null
+++ b/debian/postinst
@@ -0,0 +1,39 @@
+#!/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)
+ if dpkg --compare-versions "$2" le "1.13.0"; then
+ if [ -e /etc/osmocom/osmo-ggsn.cfg ]; then
+ chown -v osmocom:osmocom /etc/osmocom/osmo-ggsn.cfg
+ chmod -v 0660 /etc/osmocom/osmo-ggsn.cfg
+ fi
+
+ if [ -d /etc/osmocom ]; then
+ chown -v root:osmocom /etc/osmocom
+ chmod -v 2775 /etc/osmocom
+ fi
+
+ mkdir -p /var/lib/osmocom
+ chown -R -v osmocom:osmocom /var/lib/osmocom
+ fi
+ ;;
+esac
+
+# dh_installdeb(1) will replace this with shell code automatically
+# generated by other debhelper scripts.
+#DEBHELPER#
+
diff --git a/debian/rules b/debian/rules
index c11700c..48397a8 100755
--- a/debian/rules
+++ b/debian/rules
@@ -16,7 +16,7 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all
override_dh_strip:
dh_strip -posmo-ggsn --dbg-package=osmo-ggsn-dbg
- dh_strip -plibgtp6 --dbg-package=libgtp-dbg
+ dh_strip -plibgtp10 --dbg-package=libgtp-dbg
override_dh_auto_configure:
dh_auto_configure -- \
diff --git a/doc/examples/osmo-ggsn-kernel-gtp.cfg b/doc/examples/osmo-ggsn-kernel-gtp.cfg
index 28eb207..bed52b9 100644
--- a/doc/examples/osmo-ggsn-kernel-gtp.cfg
+++ b/doc/examples/osmo-ggsn-kernel-gtp.cfg
@@ -3,10 +3,12 @@
!!
!
log stderr
- logging filter all 1
logging color 1
- logging print category 0
+ logging print category-hex 0
+ logging print category 1
logging timestamp 0
+ logging print file basename last
+ logging print level 1
logging level ip info
logging level tun info
logging level ggsn info
@@ -36,7 +38,7 @@ line vty
no login
!
ggsn ggsn0
- gtp state-dir /tmp
+ gtp state-dir /var/lib/osmocom/osmo-ggsn
gtp bind-ip 127.0.0.2
apn internet
gtpu-mode kernel-gtp
diff --git a/doc/examples/osmo-ggsn.cfg b/doc/examples/osmo-ggsn.cfg
index 02523e9..53cebc1 100644
--- a/doc/examples/osmo-ggsn.cfg
+++ b/doc/examples/osmo-ggsn.cfg
@@ -3,10 +3,12 @@
!!
!
log stderr
- logging filter all 1
logging color 1
- logging print category 0
+ logging print category-hex 0
+ logging print category 1
logging timestamp 0
+ logging print file basename last
+ logging print level 1
logging level ip info
logging level tun info
logging level ggsn info
@@ -36,7 +38,7 @@ line vty
no login
!
ggsn ggsn0
- gtp state-dir /tmp
+ gtp state-dir /var/lib/osmocom/osmo-ggsn
gtp bind-ip 127.0.0.2
apn internet
gtpu-mode tun
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index 5314d10..f0889d3 100644
--- a/doc/manuals/chapters/configuration.adoc
+++ b/doc/manuals/chapters/configuration.adoc
@@ -16,7 +16,7 @@ your configuration file, like in below example:
.Example: Single GGSN configuration section
----
ggsn ggsn0
- gtp state-dir /tmp
+ gtp state-dir /var/lib/osmocom/osmo-ggsn
gtp bind-ip 127.0.0.6
apn internet
gtpu-mode tun
@@ -58,7 +58,7 @@ The following two mandatory configuration statements have to be given
for every GGSN instance:
----
-OsmoGGSN(config-ggsn)# gtp state-dir /var/lib/ggsn/ggsn0 <1>
+OsmoGGSN(config-ggsn)# gtp state-dir /var/lib/osmocom/osmo-ggsn <1>
OsmoGGSN(config-ggsn)# gtp bind-ip 127.0.0.6 <2>
----
<1> Store the GSN restart state in the specified directory
diff --git a/ggsn/Makefile.am b/ggsn/Makefile.am
index 0c6f334..ad6b2b2 100644
--- a/ggsn/Makefile.am
+++ b/ggsn/Makefile.am
@@ -7,6 +7,7 @@ AM_CFLAGS = \
-fno-builtin \
-Wall \
-DSBINDIR='"$(sbindir)"' \
+ -I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOCTRL_CFLAGS) \
$(LIBOSMOVTY_CFLAGS) \
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 0603773..a6cfc58 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -46,17 +46,19 @@
#include <osmocom/ctrl/control_if.h>
#include <osmocom/gsm/apn.h>
+#include <osmocom/gtp/pdp.h>
+#include <osmocom/gtp/gtp.h>
+
#include "../lib/tun.h"
#include "../lib/ippool.h"
#include "../lib/syserr.h"
#include "../lib/in46_addr.h"
#include "../lib/gtp-kernel.h"
#include "../lib/util.h"
-#include "../gtp/pdp.h"
-#include "../gtp/gtp.h"
#include "../lib/icmpv6.h"
#include "pco.h"
#include "ggsn.h"
+#include "../gtp/gtp_internal.h"
static int ggsn_tun_fd_cb(struct osmo_fd *fd, unsigned int what);
static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len);
@@ -423,7 +425,7 @@ static struct sgsn_peer* ggsn_find_or_create_sgsn(struct ggsn_ctx *ggsn, struct
return sgsn;
}
-int create_context_ind(struct pdp_t *pdp)
+static int create_context_ind(struct pdp_t *pdp)
{
static char name_buf[256];
struct gsn_t *gsn = pdp->gsn;
@@ -580,6 +582,41 @@ err_wrong_af:
return 0;
}
+static int update_context_ind(struct pdp_t *pdp)
+{
+ char apn_name[256];
+ struct gsn_t *gsn = pdp->gsn;
+ struct ggsn_ctx *ggsn = gsn->priv;
+ struct apn_ctx *apn;
+ bool apn_found = false;
+ int rc;
+
+ if (!osmo_apn_to_str(apn_name, pdp->apn_use.v, pdp->apn_use.l)) {
+ LOGPPDP(LOGL_ERROR, pdp, "Unable to decode associated APN len=%d buf: %s\n",
+ pdp->apn_use.l, osmo_hexdump(pdp->apn_use.v, pdp->apn_use.l));
+ return gtp_update_context_resp(ggsn->gsn, pdp, GTPCAUSE_MISSING_APN);
+ }
+
+ llist_for_each_entry (apn, &ggsn->apn_list, list) {
+ if (strncmp(apn_name, apn->cfg.name, sizeof(apn_name)) != 0)
+ continue;
+ apn_found = true;
+ break;
+ }
+ if (!apn_found) {
+ LOGPPDP(LOGL_ERROR, pdp, "Unable to find associated APN %s\n", apn_name);
+ return gtp_update_context_resp(ggsn->gsn, pdp, GTPCAUSE_MISSING_APN);
+ }
+
+ if (apn->cfg.gtpu_mode == APN_GTPU_MODE_KERNEL_GTP) {
+ /* Update the kernel with the potentially new remote data IP address + TEID */
+ gtp_kernel_tunnel_del(pdp, apn->tun.cfg.dev_name);
+ gtp_kernel_tunnel_add(pdp, apn->tun.cfg.dev_name);
+ }
+ rc = gtp_update_context_resp(ggsn->gsn, pdp, GTPCAUSE_ACC_REQ);
+ return rc;
+}
+
/* Internet-originated IP packet, needs to be sent via GTP towards MS */
static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
{
@@ -846,8 +883,9 @@ int ggsn_start(struct ggsn_ctx *ggsn)
OSMO_ASSERT(rc == 0);
gtp_set_cb_data_ind(ggsn->gsn, encaps_tun);
- gtp_set_cb_delete_context(ggsn->gsn, delete_context);
gtp_set_cb_create_context_ind(ggsn->gsn, create_context_ind);
+ gtp_set_cb_update_context_ind(ggsn->gsn, update_context_ind);
+ gtp_set_cb_delete_context(ggsn->gsn, delete_context);
gtp_set_cb_conf(ggsn->gsn, cb_conf);
gtp_set_cb_recovery3(ggsn->gsn, cb_recovery3);
diff --git a/ggsn/ggsn.h b/ggsn/ggsn.h
index 1abbc9a..7a3204f 100644
--- a/ggsn/ggsn.h
+++ b/ggsn/ggsn.h
@@ -8,12 +8,12 @@
#include <osmocom/core/timer.h>
#include <osmocom/core/tdef.h>
#include <osmocom/ctrl/control_if.h>
+#include <osmocom/gtp/gtp.h>
#include "../lib/tun.h"
#include "../lib/ippool.h"
#include "../lib/syserr.h"
#include "../lib/in46_addr.h"
-#include "../gtp/gtp.h"
#include "sgsn.h"
diff --git a/ggsn/ggsn_vty.c b/ggsn/ggsn_vty.c
index 7414b6a..da67591 100644
--- a/ggsn/ggsn_vty.c
+++ b/ggsn/ggsn_vty.c
@@ -22,6 +22,8 @@
#include <inttypes.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
@@ -35,13 +37,14 @@
#include <osmocom/vty/misc.h>
#include <osmocom/vty/tdef_vty.h>
-#include "../gtp/gtp.h"
-#include "../gtp/pdp.h"
+#include <osmocom/gtp/gtp.h>
+#include <osmocom/gtp/pdp.h>
#include "../lib/util.h"
#include "ggsn.h"
#include "sgsn.h"
+#include "../gtp/gtp_internal.h"
#define PREFIX_STR "Prefix (Network/Netmask)\n"
#define IFCONFIG_STR "GGSN-based interface configuration\n"
@@ -223,6 +226,11 @@ DEFUN(cfg_ggsn_state_dir, cfg_ggsn_state_dir_cmd,
{
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
+ if (mkdir(argv[0], 0755) == -1 && errno != EEXIST) {
+ vty_out(vty, "%% Failed to create state-dir: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
osmo_talloc_replace_string(ggsn, &ggsn->cfg.state_dir, argv[0]);
return CMD_SUCCESS;
diff --git a/ggsn/pco.h b/ggsn/pco.h
index 2f95d09..bedfa8a 100644
--- a/ggsn/pco.h
+++ b/ggsn/pco.h
@@ -2,7 +2,7 @@
#include <stdint.h>
-#include "../gtp/pdp.h"
+#include <osmocom/gtp/pdp.h>
/* 3GPP TS 24.008 10.5.6.3 */
enum pco_protocols {
diff --git a/ggsn/sgsn.c b/ggsn/sgsn.c
index 15548ef..b324fd7 100644
--- a/ggsn/sgsn.c
+++ b/ggsn/sgsn.c
@@ -1,6 +1,6 @@
#include "sgsn.h"
#include "ggsn.h"
-
+#include "../gtp/gtp_internal.h"
static bool sgsn_peer_attempt_free(struct sgsn_peer *sgsn)
{
diff --git a/ggsn/sgsn.h b/ggsn/sgsn.h
index d2c3c0c..3bc94e3 100644
--- a/ggsn/sgsn.h
+++ b/ggsn/sgsn.h
@@ -8,7 +8,7 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
-#include "../gtp/pdp.h"
+#include <osmocom/gtp/pdp.h>
struct ggsn_ctx;
struct pdp_priv_t;
diff --git a/gtp/Makefile.am b/gtp/Makefile.am
index 666befe..db1942d 100644
--- a/gtp/Makefile.am
+++ b/gtp/Makefile.am
@@ -2,30 +2,27 @@
# Please read chapter "Library interface versions" of the libtool documentation
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
# If major=current-age is increased, remember to update the dh_strip line in debian/rules!
-LIBVERSION=9:1:3
+LIBVERSION=10:0:0
lib_LTLIBRARIES = libgtp.la
-include_HEADERS = gtp.h gsn.h pdp.h gtpie.h
-
AM_CFLAGS = \
-fno-builtin \
-Wall \
-DSBINDIR='"$(sbindir)"' \
+ -I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \
$(NULL)
libgtp_la_SOURCES = \
gsn.c \
- gsn.h \
+ gsn_internal.h \
gtp.c \
- gtp.h \
+ gtp_internal.h \
gtpie.c \
- gtpie.h \
lookupa.c \
lookupa.h \
pdp.c \
- pdp.h \
queue.c \
queue.h \
$(NULL)
diff --git a/gtp/gsn.c b/gtp/gsn.c
index e66dc99..612baf2 100644
--- a/gtp/gsn.c
+++ b/gtp/gsn.c
@@ -57,10 +57,12 @@
/* #include <stdint.h> ISO C99 types */
-#include "pdp.h"
-#include "gtp.h"
-#include "gtpie.h"
+#include <osmocom/gtp/pdp.h>
+#include <osmocom/gtp/gtp.h>
+#include <osmocom/gtp/gtpie.h>
+
#include "queue.h"
+#include "gsn_internal.h"
/* Error reporting functions */
@@ -495,6 +497,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
/* Initialise call back functions */
(*gsn)->cb_create_context_ind = 0;
+ (*gsn)->cb_update_context_ind = 0;
(*gsn)->cb_delete_context = 0;
(*gsn)->cb_unsup_ind = 0;
(*gsn)->cb_conf = 0;
@@ -561,6 +564,13 @@ int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
return 0;
}
+int gtp_set_cb_update_context_ind(struct gsn_t *gsn,
+ int (*cb_update_context_ind)(struct pdp_t *pdp))
+{
+ gsn->cb_update_context_ind = cb_update_context_ind;
+ return 0;
+}
+
int gtp_retrans(struct gsn_t *gsn)
{
/* dummy API, deprecated. */
diff --git a/gtp/gsn_internal.h b/gtp/gsn_internal.h
new file mode 100644
index 0000000..deb60c3
--- /dev/null
+++ b/gtp/gsn_internal.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void gtp_queue_timer_start(struct gsn_t *gsn);
diff --git a/gtp/gtp.c b/gtp/gtp.c
index 43e56b5..02cf8a3 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -55,10 +55,13 @@
/* #include <stdint.h> ISO C99 types */
-#include "pdp.h"
-#include "gtp.h"
-#include "gtpie.h"
+#include <osmocom/gtp/pdp.h>
+#include <osmocom/gtp/gtp.h>
+#include <osmocom/gtp/gtpie.h>
+
#include "queue.h"
+#include "gsn_internal.h"
+#include "gtp_internal.h"
/* Error reporting functions */
@@ -638,8 +641,8 @@ int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
}
/* Send off an echo reply */
-int gtp_echo_resp(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd, void *pack, unsigned len)
+static int gtp_echo_resp(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, int fd, void *pack, unsigned len)
{
union gtp_packet packet;
unsigned int length = get_default_gtp(version, GTP_ECHO_RSP, &packet);
@@ -650,8 +653,8 @@ int gtp_echo_resp(struct gsn_t *gsn, int version,
}
/* Handle a received echo request */
-int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
- int fd, void *pack, unsigned len)
+static int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
+ int fd, void *pack, unsigned len)
{
/* Check if it was a duplicate request */
@@ -663,8 +666,8 @@ int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
}
/* Handle a received echo reply */
-int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
- void *pack, unsigned len)
+static int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
+ void *pack, unsigned len)
{
union gtpie_member *ie[GTPIE_SIZE];
unsigned char recovery;
@@ -716,8 +719,8 @@ int gtp_echo_conf(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
* only listen to the GTP0 port, and therefore will never receive
* anything else than GTP0 */
-int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
- int fd, void *pack, unsigned len)
+static int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
+ int fd, void *pack, unsigned len)
{
union gtp_packet packet;
@@ -727,8 +730,8 @@ int gtp_unsup_req(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
}
/* Handle a Version Not Supported message */
-int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
- void *pack, unsigned len)
+static int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
+ void *pack, unsigned len)
{
if (gsn->cb_unsup_ind)
@@ -821,6 +824,40 @@ int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *peer,
}
/* ***********************************************************
+ * Conversion functions
+ *************************************************************/
+
+/* ***********************************************************
+ * IP address conversion functions
+ * There exist several types of address representations:
+ * - eua: End User Address. (29.060, 7.7.27, message type 128)
+ * Used for signalling address to mobile station. Supports IPv4
+ * IPv6 x.25 etc. etc.
+ * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
+ * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
+ * - in_addr: IPv4 address struct.
+ * - sockaddr_in: Socket API representation of IP address and
+ * port number.
+ *************************************************************/
+
+int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
+{
+ memset(dst, 0, sizeof(struct in_addr));
+ if (gsna->l != 4)
+ return EOF; /* Return if not IPv4 */
+ memcpy(dst, gsna->v, gsna->l);
+ return 0;
+}
+
+static int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
+{
+ memset(gsna, 0, sizeof(struct ul16_t));
+ gsna->l = 4;
+ memcpy(gsna->v, src, gsna->l);
+ return 0;
+}
+
+/* ***********************************************************
* Session management messages
* Messages: create, update and delete PDP context
*
@@ -988,22 +1025,9 @@ int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
return 0;
}
-/* API: Application response to context indication */
-int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
-{
-
- /* Now send off a reply to the peer */
- gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
-
- if (!gtp_cause_successful(cause))
- gtp_freepdp(gsn, pdp);
-
- return 0;
-}
-
/* Send Create PDP Context Response */
-int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
- uint8_t cause)
+static int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
+ uint8_t cause)
{
union gtp_packet packet;
unsigned int length =
@@ -1064,10 +1088,23 @@ int gtp_create_pdp_resp(struct gsn_t *gsn, int version, struct pdp_t *pdp,
pdp->fd, pdp->seq, pdp->tid);
}
+/* API: Application response to context indication */
+int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
+{
+
+ /* Now send off a reply to the peer */
+ gtp_create_pdp_resp(gsn, pdp->version, pdp, cause);
+
+ if (!gtp_cause_successful(cause))
+ gtp_freepdp(gsn, pdp);
+
+ return 0;
+}
+
/* Handle Create PDP Context Request */
-int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len)
+static int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, int fd,
+ void *pack, unsigned len)
{
struct pdp_t *pdp, *pdp_old;
struct pdp_t pdp_buf;
@@ -1390,8 +1427,8 @@ recover_ret:
}
/* Handle Create PDP Context Response */
-int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, void *pack, unsigned len)
+static int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, void *pack, unsigned len)
{
struct pdp_t *pdp;
union gtpie_member *ie[GTPIE_SIZE];
@@ -1649,15 +1686,21 @@ int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_OMC_ID,
pdp->omcid.l, pdp->omcid.v);
+ /* Direct Tunnel Flags */
+ if ((pdp->version == 1) && pdp->dir_tun_flags.l)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_DIR_TUN_FLAGS,
+ pdp->dir_tun_flags.l, pdp->dir_tun_flags.v);
+
gtp_req(gsn, pdp->version, pdp, &packet, length, inetaddr, cbp);
return 0;
}
+
/* Send Update PDP Context Response */
static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
struct sockaddr_in *peer, int fd,
- void *pack, unsigned len,
+ uint16_t seq, uint64_t tid,
struct pdp_t *pdp, uint8_t cause)
{
@@ -1710,10 +1753,30 @@ static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
pdp->qos_neg.l, pdp->qos_neg.v);
/* TODO: Charging gateway address */
+
+ /* Direct Tunnel Flags */
+ if ((gsn->mode == GTP_MODE_SGSN) && (version == 1) && pdp->dir_tun_flags.l)
+ gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_DIR_TUN_FLAGS,
+ pdp->dir_tun_flags.l, pdp->dir_tun_flags.v);
}
return gtp_resp(version, gsn, pdp, &packet, length, peer,
- fd, get_seq(pack), get_tid(pack));
+ fd, seq, tid);
+}
+
+
+/* API: Application response to context indication */
+int gtp_update_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
+{
+
+ /* Now send off a reply to the peer */
+ gtp_update_pdp_resp(gsn, pdp->version, &pdp->sa_peer,
+ pdp->fd, pdp->seq, pdp->tid, pdp, cause);
+
+ if (!gtp_cause_successful(cause))
+ gtp_freepdp(gsn, pdp);
+
+ return 0;
}
/* Handle Update PDP Context Request */
@@ -1721,13 +1784,15 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
struct sockaddr_in *peer, int fd,
void *pack, unsigned len)
{
- struct pdp_t *pdp;
+ struct pdp_t *pdp = NULL;
struct pdp_t pdp_backup;
union gtpie_member *ie[GTPIE_SIZE];
uint8_t recovery;
+ int rc;
uint16_t seq = get_seq(pack);
int hlen = get_hlen(pack);
+ uint64_t tid = get_tid(pack);
uint64_t imsi;
uint8_t nsapi;
@@ -1745,8 +1810,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
if (0 == version)
return EOF;
else
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, NULL,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, NULL,
GTPCAUSE_INVALID_MESSAGE);
}
@@ -1761,8 +1826,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
"Unknown PDP context: TID=0x%" PRIx64 "\n",
get_tid(pack));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, NULL,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, NULL,
GTPCAUSE_NON_EXIST);
}
@@ -1774,8 +1839,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, NULL,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, NULL,
GTPCAUSE_MAN_IE_MISSING);
}
@@ -1788,7 +1853,7 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
"Unknown PDP context: TEI=0x%" PRIx32 "\n",
get_tei(pack));
return gtp_update_pdp_resp(gsn, version, peer,
- fd, pack, len, NULL,
+ fd, seq, tid, NULL,
GTPCAUSE_NON_EXIST);
}
} else {
@@ -1799,7 +1864,7 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
"Unknown PDP context: IMSI=0x%" PRIx64
" NSAPI=%" PRIu8 "\n", imsi, nsapi);
return gtp_update_pdp_resp(gsn, version, peer,
- fd, pack, len, NULL,
+ fd, seq, tid, NULL,
GTPCAUSE_NON_EXIST);
}
}
@@ -1808,6 +1873,12 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
return EOF;
}
+ /* Update internal state to be used when user calls gtp_update_context_resp(): */
+ pdp->seq = seq;
+ pdp->sa_peer = *peer;
+ pdp->fd = fd;
+ pdp->version = version;
+
/* Make a backup copy in case anything is wrong */
memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
@@ -1818,8 +1889,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
}
@@ -1835,8 +1906,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
@@ -1845,21 +1916,22 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
}
if (version == 1) {
- /* TEID (mandatory) */
- if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
+ /* TEID (mandatory SGSN->GGSN, Optional SGSN<-GGSN) */
+ if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn) &&
+ gsn->mode == GTP_MODE_GGSN) {
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
@@ -1875,8 +1947,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
}
@@ -1903,45 +1975,60 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
"Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq, tid,
pdp, GTPCAUSE_MAN_IE_MISSING);
}
- /* SGSN address for user traffic (mandatory) */
+ /* SGSN address for user traffic (mandatory SGSN->GGSN, optional SGSN<-GGSN) */
if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
- &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
+ &pdp->gsnru.v, sizeof(pdp->gsnru.v)) &&
+ gsn->mode == GTP_MODE_GGSN) {
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
"Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq, tid,
pdp, GTPCAUSE_MAN_IE_MISSING);
}
if (version == 1) {
- /* QoS (mandatory) */
+ /* QoS (mandatory SGSN->GGSN, optional SGSN<-GGSN) */
if (gtpie_gettlv(ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_req.l,
- &pdp->qos_req.v, sizeof(pdp->qos_req.v))) {
+ &pdp->qos_req.v, sizeof(pdp->qos_req.v)) &&
+ gsn->mode == GTP_MODE_GGSN) {
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
- /* TFT (conditional) */
+ /* TFT (conditional SGSN->GGSN, optional SGSN<-GGSN) */
if (gtpie_gettlv(ie, GTPIE_TFT, 0, &pdp->tft.l,
&pdp->tft.v, sizeof(pdp->tft.v))) {
}
/* OMC identity */
+
+ /* Direct Tunnel Flags */
+ if (gtpie_gettlv(ie, GTPIE_DIR_TUN_FLAGS, 0, &pdp->dir_tun_flags.l,
+ &pdp->dir_tun_flags.v, sizeof(pdp->dir_tun_flags.v))) {
+ }
+ }
+
+ /* Callback function to validate login */
+ if (gsn->cb_update_context_ind != 0)
+ rc = gsn->cb_update_context_ind(pdp);
+ else {
+ /* Confirm to peer that things were "successful" */
+ rc = gtp_update_pdp_resp(gsn, version, peer, fd, seq, tid, pdp,
+ GTPCAUSE_ACC_REQ);
}
/* Confirm to peer that things were "successful" */
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_ACC_REQ);
+ return rc;
}
/* Handle Update PDP Context Response */
@@ -2046,6 +2133,11 @@ static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
&pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
goto err_missing;
}
+
+ /* Direct Tunnel Flags */
+ if (gtpie_gettlv(ie, GTPIE_DIR_TUN_FLAGS, 0, &pdp->dir_tun_flags.l,
+ &pdp->dir_tun_flags.v, sizeof(pdp->dir_tun_flags.v))) {
+ }
}
}
@@ -2157,11 +2249,11 @@ int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
}
/* Send Delete PDP Context Response */
-int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len,
- struct pdp_t *pdp, struct pdp_t *linked_pdp,
- uint8_t cause, int teardown)
+static int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, int fd,
+ void *pack, unsigned len,
+ struct pdp_t *pdp, struct pdp_t *linked_pdp,
+ uint8_t cause, int teardown)
{
union gtp_packet packet;
unsigned int length =
@@ -2202,9 +2294,9 @@ int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
}
/* Handle Delete PDP Context Request */
-int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len)
+static int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, int fd,
+ void *pack, unsigned len)
{
struct pdp_t *pdp = NULL;
struct pdp_t *linked_pdp = NULL;
@@ -2301,8 +2393,8 @@ int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
}
/* Handle Delete PDP Context Response */
-int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, void *pack, unsigned len)
+static int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
+ struct sockaddr_in *peer, void *pack, unsigned len)
{
union gtpie_member *ie[GTPIE_SIZE];
uint8_t cause;
@@ -2762,8 +2854,7 @@ int gtp_decaps1c(struct gsn_t *gsn)
}
if ((gsn->mode == GTP_MODE_GGSN) &&
- ((pheader->type == GTP_CREATE_PDP_RSP) ||
- (pheader->type == GTP_UPDATE_PDP_RSP))) {
+ (pheader->type == GTP_CREATE_PDP_RSP)) {
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNEXPECT);
GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
status,
@@ -2773,8 +2864,7 @@ int gtp_decaps1c(struct gsn_t *gsn)
}
if ((gsn->mode == GTP_MODE_SGSN) &&
- ((pheader->type == GTP_CREATE_PDP_REQ) ||
- (pheader->type == GTP_UPDATE_PDP_REQ))) {
+ (pheader->type == GTP_CREATE_PDP_REQ)) {
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_UNEXPECT);
GTP_LOGPKG(LOGL_ERROR, &peer, buffer,
status,
@@ -3050,61 +3140,6 @@ int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp, void *pack, unsigned len)
return 0;
}
-/* ***********************************************************
- * Conversion functions
- *************************************************************/
-
-/* ***********************************************************
- * IP address conversion functions
- * There exist several types of address representations:
- * - eua: End User Address. (29.060, 7.7.27, message type 128)
- * Used for signalling address to mobile station. Supports IPv4
- * IPv6 x.25 etc. etc.
- * - gsna: GSN Address. (29.060, 7.7.32, message type 133): IP address
- * of GSN. If length is 4 it is IPv4. If length is 16 it is IPv6.
- * - in_addr: IPv4 address struct.
- * - sockaddr_in: Socket API representation of IP address and
- * port number.
- *************************************************************/
-
-int ipv42eua(struct ul66_t *eua, struct in_addr *src)
-{
- eua->v[0] = PDP_EUA_ORG_IETF;
- eua->v[1] = PDP_EUA_TYPE_v4;
- if (src) {
- eua->l = 6;
- memcpy(&eua->v[2], src, 4);
- } else {
- eua->l = 2;
- }
- return 0;
-}
-
-int eua2ipv4(struct in_addr *dst, struct ul66_t *eua)
-{
- if ((eua->l != 6) || (eua->v[0] != PDP_EUA_ORG_IETF) || (eua->v[1] != PDP_EUA_TYPE_v4))
- return -1; /* Not IPv4 address */
- memcpy(dst, &eua->v[2], 4);
- return 0;
-}
-
-int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna)
-{
- memset(dst, 0, sizeof(struct in_addr));
- if (gsna->l != 4)
- return EOF; /* Return if not IPv4 */
- memcpy(dst, gsna->v, gsna->l);
- return 0;
-}
-
-int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src)
-{
- memset(gsna, 0, sizeof(struct ul16_t));
- gsna->l = 4;
- memcpy(gsna->v, src, gsna->l);
- return 0;
-}
-
/* TS 29.060 has yet again a different encoding for IMSIs than
* what we have in other places, so we cannot use the gsm48
* decoding functions. Also, libgtp uses an uint64_t in
diff --git a/gtp/gtp_internal.h b/gtp/gtp_internal.h
new file mode 100644
index 0000000..c8f22dc
--- /dev/null
+++ b/gtp/gtp_internal.h
@@ -0,0 +1,3 @@
+#pragma once
+
+uint64_t gtp_imsi_str2gtp(const char *str);
diff --git a/gtp/gtpie.c b/gtp/gtpie.c
index e413d11..3212a8a 100644
--- a/gtp/gtpie.c
+++ b/gtp/gtpie.c
@@ -37,7 +37,7 @@
#include <netinet/in.h>
#include <string.h>
-#include "gtpie.h"
+#include <osmocom/gtp/gtpie.h>
/*! Encode a TLV type Information Element.
* \param[inout] p Pointer to output packet to which IE is appended
diff --git a/gtp/pdp.c b/gtp/pdp.c
index 2be2dd3..9626ce8 100644
--- a/gtp/pdp.c
+++ b/gtp/pdp.c
@@ -28,8 +28,10 @@
#include <netinet/in.h>
#include <string.h>
#include <inttypes.h>
-#include "pdp.h"
-#include "gtp.h"
+
+#include <osmocom/gtp/pdp.h>
+#include <osmocom/gtp/gtp.h>
+
#include "lookupa.h"
#include "queue.h"
diff --git a/gtp/queue.c b/gtp/queue.c
index 4c25913..157c226 100644
--- a/gtp/queue.c
+++ b/gtp/queue.c
@@ -27,8 +27,10 @@
#include <sys/time.h>
#include <netinet/in.h>
#include <string.h>
-#include "pdp.h"
-#include "gtp.h"
+
+#include <osmocom/gtp/pdp.h>
+#include <osmocom/gtp/gtp.h>
+
#include "queue.h"
/*! \brief dump a queue_t to stdout */
diff --git a/gtp/queue.h b/gtp/queue.h
index 9f62482..7fde079 100644
--- a/gtp/queue.h
+++ b/gtp/queue.h
@@ -19,7 +19,7 @@
#include <osmocom/core/linuxlist.h>
-#include "gtp.h"
+#include <osmocom/gtp/gtp.h>
#define QUEUE_DEBUG 0 /* Print debug information */
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..9d963a0
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+ osmocom \
+ $(NULL)
diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am
new file mode 100644
index 0000000..2a96bba
--- /dev/null
+++ b/include/osmocom/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+ gtp \
+ $(NULL)
diff --git a/include/osmocom/gtp/Makefile.am b/include/osmocom/gtp/Makefile.am
new file mode 100644
index 0000000..db696e5
--- /dev/null
+++ b/include/osmocom/gtp/Makefile.am
@@ -0,0 +1,8 @@
+libgtp_HEADERS = \
+ gsn.h \
+ gtp.h \
+ gtpie.h \
+ pdp.h \
+ $(NULL)
+
+libgtpdir = $(includedir)/osmocom/gtp
diff --git a/gtp/gsn.h b/include/osmocom/gtp/gsn.h
index 8e47ce3..006fdfd 100644
--- a/gtp/gsn.h
+++ b/include/osmocom/gtp/gsn.h
@@ -99,6 +99,7 @@ struct gsn_t {
/* Call back functions */
int (*cb_delete_context) (struct pdp_t *);
int (*cb_create_context_ind) (struct pdp_t *);
+ int (*cb_update_context_ind)(struct pdp_t *pdp);
int (*cb_unsup_ind) (struct sockaddr_in * peer);
int (*cb_extheader_ind) (struct sockaddr_in * peer);
int (*cb_ran_info_relay_ind) (struct sockaddr_in *peer, union gtpie_member **ie);
@@ -134,6 +135,8 @@ extern int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
int (*cb_create_context_ind) (struct
pdp_t *
pdp));
+extern int gtp_set_cb_update_context_ind(struct gsn_t *gsn,
+ int (*cb_update_context_ind)(struct pdp_t *pdp));
extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
int (*cb_data_ind) (struct pdp_t * pdp,
void *pack, unsigned len));
@@ -175,7 +178,4 @@ extern int gtp_fd(struct gsn_t *gsn);
extern int gtp_retrans(struct gsn_t *gsn) OSMO_DEPRECATED("This API is a no-op, libgtp already does the job internally");
extern int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout) OSMO_DEPRECATED("This API is a no-op and will return a 1 day timeout");
-/* Internal APIs: */
-void gtp_queue_timer_start(struct gsn_t *gsn);
-
#endif /* !_GSN_H */
diff --git a/gtp/gtp.h b/include/osmocom/gtp/gtp.h
index 7465cf1..001a696 100644
--- a/gtp/gtp.h
+++ b/include/osmocom/gtp/gtp.h
@@ -248,6 +248,9 @@ extern int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, struct in_addr *inetaddr);
+extern int gtp_update_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
+ int cause);
+
extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, int teardown)
OSMO_DEPRECATED("Use gtp_delete_context_req2() instead, to avoid freeing pdp ctx before reply");
@@ -265,61 +268,12 @@ extern int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *p
extern int gtp_decaps0(struct gsn_t *gsn);
extern int gtp_decaps1c(struct gsn_t *gsn);
extern int gtp_decaps1u(struct gsn_t *gsn);
-/* Internal functions (not part of the API) */
extern int gtp_echo_req(struct gsn_t *gsn, int version, void *cbp,
struct in_addr *inetaddrs);
-extern int gtp_echo_resp(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len);
-extern int gtp_echo_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len);
-extern int gtp_echo_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, void *pack, unsigned len);
-
-extern int gtp_unsup_req(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer,
- int fd, void *pack, unsigned len);
-extern int gtp_unsup_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
- void *pack, unsigned len);
-
-extern int gtp_create_pdp_resp(struct gsn_t *gsn, int version,
- struct pdp_t *pdp, uint8_t cause);
-
-extern int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len);
-
-extern int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer,
- void *pack, unsigned len);
-extern int gtp_update_pdp_req(struct gsn_t *gsn, int version, void *cbp,
- struct in_addr *inetaddr, struct pdp_t *pdp);
-
-extern int gtp_delete_pdp_req(struct gsn_t *gsn, int version, void *cbp,
- struct pdp_t *pdp);
-
-extern int gtp_delete_pdp_resp(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len,
- struct pdp_t *pdp, struct pdp_t *linked_pdp,
- uint8_t cause, int teardown);
-
-extern int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer, int fd,
- void *pack, unsigned len);
-
-extern int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
- struct sockaddr_in *peer,
- void *pack, unsigned len);
-
-extern int ipv42eua(struct ul66_t *eua, struct in_addr *src);
-extern int eua2ipv4(struct in_addr *dst, struct ul66_t *eua);
extern int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna);
-extern int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src);
+
extern const char *imsi_gtp2str(const uint64_t *imsi);
-extern uint64_t gtp_imsi_str2gtp(const char *str);
#endif /* !_GTP_H */
diff --git a/gtp/gtpie.h b/include/osmocom/gtp/gtpie.h
index b6fea6e..b6fea6e 100644
--- a/gtp/gtpie.h
+++ b/include/osmocom/gtp/gtpie.h
diff --git a/gtp/pdp.h b/include/osmocom/gtp/pdp.h
index 4dcdde4..da4a382 100644
--- a/gtp/pdp.h
+++ b/include/osmocom/gtp/pdp.h
@@ -46,6 +46,11 @@ struct ul_t {
unsigned char *v;
};
+struct ul1_t {
+ unsigned int l;
+ unsigned char v[1];
+};
+
struct ul16_t {
unsigned int l;
unsigned char v[16];
@@ -244,6 +249,8 @@ struct pdp_t {
bool tx_gpdu_seq; /* Transmit (true) or suppress G-PDU sequence numbers */
struct llist_head qmsg_list_req; /* list of req qmsg_t in retrans queue belonging this pdp ctx */
+
+ struct ul1_t dir_tun_flags; /* Direct Tunnel Flags, TS 29.060 7.7.81 */
};
/* functions related to pdp_t management */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index bef8962..1fdc93f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -19,6 +19,7 @@ AM_CFLAGS = \
-fno-builtin \
-Wall \
-DSBINDIR='"$(sbindir)"' \
+ -I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \
$(NULL)
diff --git a/lib/gtp-kernel.c b/lib/gtp-kernel.c
index 6a14d78..4c8c3ac 100644
--- a/lib/gtp-kernel.c
+++ b/lib/gtp-kernel.c
@@ -23,12 +23,13 @@
#include <time.h>
+#include <osmocom/gtp/pdp.h>
+#include <osmocom/gtp/gtp.h>
+
#include "../lib/tun.h"
#include "../lib/syserr.h"
#include "../lib/util.h"
#include "../lib/ippool.h"
-#include "../gtp/pdp.h"
-#include "../gtp/gtp.h"
#include "gtp-kernel.h"
diff --git a/lib/icmpv6.c b/lib/icmpv6.c
index ac1474d..b6994cd 100644
--- a/lib/icmpv6.c
+++ b/lib/icmpv6.c
@@ -21,10 +21,11 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/utils.h>
-#include "checksum.h"
-#include "../gtp/gtp.h"
-#include "../gtp/pdp.h"
+#include <osmocom/gtp/gtp.h>
+#include <osmocom/gtp/pdp.h>
+
+#include "checksum.h"
#include "ippool.h"
#include "syserr.h"
#include "icmpv6.h"
diff --git a/lib/icmpv6.h b/lib/icmpv6.h
index ee5ef29..5bed5c6 100644
--- a/lib/icmpv6.h
+++ b/lib/icmpv6.h
@@ -5,8 +5,8 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/endian.h>
-#include "../gtp/gtp.h"
-#include "../gtp/pdp.h"
+#include <osmocom/gtp/gtp.h>
+#include <osmocom/gtp/pdp.h>
#define ICMPv6_OPT_TYPE_PREFIX_INFO 0x03
diff --git a/lib/in46_addr.c b/lib/in46_addr.c
index 648fe7e..c5157be 100644
--- a/lib/in46_addr.c
+++ b/lib/in46_addr.c
@@ -10,7 +10,7 @@
*/
#include "../lib/in46_addr.h"
-#include "../gtp/pdp.h"
+#include <osmocom/gtp/pdp.h>
#include <osmocom/core/utils.h>
diff --git a/lib/in46_addr.h b/lib/in46_addr.h
index 5589f94..89e1e22 100644
--- a/lib/in46_addr.h
+++ b/lib/in46_addr.h
@@ -2,7 +2,7 @@
#include <stdint.h>
#include <netinet/in.h>
-#include "../gtp/pdp.h"
+#include <osmocom/gtp/pdp.h>
/* a simple wrapper around an in6_addr to also contain the length of the address,
* thereby implicitly indicating the address family of the address */
diff --git a/lib/ippool.h b/lib/ippool.h
index efb274b..406938e 100644
--- a/lib/ippool.h
+++ b/lib/ippool.h
@@ -13,7 +13,7 @@
#define _IPPOOL_H
#include "../lib/in46_addr.h"
-#include "../gtp/gtp.h"
+#include <osmocom/gtp/gtp.h>
/* Assuming that the address space is fragmented we need a hash table
in order to return the addresses.
diff --git a/lib/util.c b/lib/util.c
index 6bb0d85..f29884a 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -9,7 +9,7 @@
*
*/
-#include "../gtp/pdp.h"
+#include <osmocom/gtp/pdp.h>
#include "ippool.h"
#include "in46_addr.h"
diff --git a/libgtp.pc.in b/libgtp.pc.in
index e6048e9..b6b0652 100644
--- a/libgtp.pc.in
+++ b/libgtp.pc.in
@@ -7,5 +7,8 @@ Name: OsmoGGSN GTP Library
Description: C Utility Library
Version: @VERSION@
Libs: -L${libdir} -lgtp
-Cflags: -I${includedir}/
+# Add two include paths to support:
+# * #include <osmocom/gtp/gtp.h> (like other Osmocom headers)
+# * #include <gtp.h> (legacy compat)
+Cflags: -I${includedir}/osmocom/gtp/ -I${includedir}/
diff --git a/sgsnemu/Makefile.am b/sgsnemu/Makefile.am
index 7e7fdbb..5d88c7f 100644
--- a/sgsnemu/Makefile.am
+++ b/sgsnemu/Makefile.am
@@ -7,6 +7,7 @@ AM_CFLAGS = \
-fno-builtin \
-Wall \
-DSBINDIR='"$(sbindir)"' \
+ -I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \
$(NULL)
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index 7893f4f..152b05b 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -54,13 +54,15 @@
#endif // HAVE_IN6_ADDR_GEN_MODE_NONE
#endif
+#include <osmocom/gtp/pdp.h>
+#include <osmocom/gtp/gtp.h>
+
#include "../lib/tun.h"
#include "../lib/ippool.h"
#include "../lib/syserr.h"
#include "../lib/netns.h"
#include "../lib/icmpv6.h"
-#include "../gtp/pdp.h"
-#include "../gtp/gtp.h"
+#include "../gtp/gtp_internal.h"
#include "cmdline.h"
#define IPADDRLEN 256 /* Character length of addresses */
diff --git a/tests/gtp/gtpie_test.c b/tests/gtp/gtpie_test.c
index ed1f26e..46c0a98 100644
--- a/tests/gtp/gtpie_test.c
+++ b/tests/gtp/gtpie_test.c
@@ -10,8 +10,9 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/bits.h>
+#include <osmocom/gtp/gtpie.h>
+
#include "../../lib/syserr.h"
-#include "../../gtp/gtpie.h"
static const uint8_t in[] = { 1,2,3,4,5,6 };
static uint8_t buf[256];