Compare commits
58 Commits
Author | SHA1 | Date |
---|---|---|
Oliver Smith | 57585767dc | |
Oliver Smith | 488972b442 | |
Oliver Smith | 08239ccac3 | |
Oliver Smith | fbc56063c5 | |
Oliver Smith | c1598e0eb4 | |
Oliver Smith | 519a2e401d | |
Oliver Smith | fbef527222 | |
Oliver Smith | 68f5b086ad | |
Oliver Smith | 3cb3423a59 | |
Oliver Smith | bad5eeba0f | |
Oliver Smith | 1dd16fa12f | |
Oliver Smith | 3372625ad9 | |
Harald Welte | 1f9cc2674f | |
Harald Welte | 4abe361f33 | |
Harald Welte | bb0655d5aa | |
Harald Welte | 4e6fe42731 | |
Oliver Smith | 19a506b705 | |
Oliver Smith | ea6c02ac1f | |
Oliver Smith | ec357c5377 | |
Oliver Smith | 768d6d5be9 | |
Oliver Smith | fa91a10498 | |
Oliver Smith | 6929391ecf | |
Oliver Smith | 9baac03927 | |
Oliver Smith | 9bd2711f39 | |
Oliver Smith | b17fe7bfe9 | |
Oliver Smith | 0917ce4e22 | |
Oliver Smith | 2a0d37cb1d | |
Oliver Smith | f3d541e353 | |
Pau Espin | 8d976444b8 | |
Daniel Willmann | 77734ac81b | |
Oliver Smith | 848ec697e2 | |
Daniel Willmann | 6a2e82542d | |
Daniel Willmann | a625bdd136 | |
Pau Espin | 08bb5182a4 | |
Oliver Smith | 4963d1c2ea | |
Oliver Smith | 37daa5d003 | |
Oliver Smith | c4c4d90b85 | |
Oliver Smith | 59f1539ece | |
Oliver Smith | eff88c08e7 | |
Oliver Smith | 92ac7249f9 | |
Vadim Yanitskiy | 5cf6b75dc9 | |
Vadim Yanitskiy | 4aa2e417c9 | |
Vadim Yanitskiy | f14c056310 | |
Vadim Yanitskiy | bf69ddbfef | |
Vadim Yanitskiy | 70a4e2e6f8 | |
Vadim Yanitskiy | 99afe979ef | |
Oliver Smith | 35066fb0b0 | |
Pau Espin | 55fe62f634 | |
Pau Espin | 4fac842826 | |
arehbein | 97f60e3dca | |
Max | a727e6ed38 | |
Pau Espin | 3a55b89777 | |
Pau Espin | 9f1f747d8e | |
Pau Espin | b9036af7ca | |
Pau Espin | 724ecc6680 | |
Pau Espin | 0d3bd3435f | |
Max | 3ed252b58e | |
Max | ac802e63d7 |
|
@ -0,0 +1 @@
|
|||
open_collective: osmocom
|
|
@ -82,3 +82,7 @@ doc/manuals/build
|
|||
doc/manuals/vty/ggsn_vty_reference.xml
|
||||
|
||||
contrib/osmo-ggsn.spec
|
||||
/debian/gtp-echo-responder-dbg/
|
||||
/debian/gtp-echo-responder/
|
||||
/debian/osmo-ggsn-doc/
|
||||
/utils/gtp-echo-responder
|
||||
|
|
13
Makefile.am
13
Makefile.am
|
@ -1,5 +1,15 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
SUBDIRS = lib gtp ggsn sgsnemu doc contrib utils tests
|
||||
SUBDIRS = \
|
||||
include \
|
||||
lib \
|
||||
gtp \
|
||||
ggsn \
|
||||
sgsnemu \
|
||||
doc \
|
||||
contrib \
|
||||
utils \
|
||||
tests \
|
||||
$(NULL)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libgtp.pc
|
||||
|
@ -15,7 +25,6 @@ EXTRA_DIST = \
|
|||
README.FreeBSD \
|
||||
README.MacOSX \
|
||||
README.md \
|
||||
contrib/osmo-ggsn.spec.in \
|
||||
debian \
|
||||
git-version-gen \
|
||||
$(NULL)
|
||||
|
|
163
README.md
163
README.md
|
@ -5,15 +5,14 @@ This repository contains 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.
|
||||
|
||||
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.
|
||||
**OsmoGGSN** is part of the [Osmocom](https://osmocom.org/) Open Source
|
||||
Mobile Communications projects and the successor to OpenGGSN (which was
|
||||
developed until 2004 by Mondru AB).
|
||||
|
||||
Homepage
|
||||
--------
|
||||
|
||||
The official homepage of the project is
|
||||
https://osmocom.org/projects/openggsn/wiki
|
||||
The official homepage of the project is <https://osmocom.org/projects/openggsn/wiki>.
|
||||
|
||||
GIT Repository
|
||||
--------------
|
||||
|
@ -27,35 +26,50 @@ There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/o
|
|||
Documentation
|
||||
-------------
|
||||
|
||||
There currently is no other documentation other than the wiki on the
|
||||
homepage. It would be great if somebody would work towards a user
|
||||
manual that can become part of the osmo-gsm-manuals project.
|
||||
The user manual and VTY reference are optionally built in PDF form
|
||||
as part of the build process. Pre-rendered versions are available here:
|
||||
|
||||
* [osmo-ggsn user manual](https://ftp.osmocom.org/docs/osmo-ggsn/master/osmoggsn-usermanual.pdf)
|
||||
* [osmo-ggsn VTY reference](https://ftp.osmocom.org/docs/osmo-ggsn/master/osmoggsn-vty-reference.pdf)
|
||||
|
||||
Forum
|
||||
-----
|
||||
|
||||
We welcome any pySim related discussions in the
|
||||
[Cellular Network Infrastructure -> 2G/3G Core Network](https://discourse.osmocom.org/c/cni/2g-3g-cn/)
|
||||
section of the osmocom discourse (web based Forum).
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
|
||||
Discussions related to OsmoGGSN are happening on the
|
||||
osmocom-net-gprs@lists.osmocom.org mailing list, please see
|
||||
https://lists.osmocom.org/mailman/listinfo/osmocom-net-gprs for
|
||||
<https://lists.osmocom.org/mailman/listinfo/osmocom-net-gprs> for
|
||||
subscription options and the list archive.
|
||||
|
||||
Please observe the [Osmocom Mailing List
|
||||
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
|
||||
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-ggsn project on osmocom.org](https://osmocom.org/projects/openggsn/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
|
||||
------------
|
||||
|
||||
Our coding standards are described at
|
||||
https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
|
||||
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
|
||||
|
||||
We us a gerrit based patch submission/review process for managing
|
||||
contributions. Please see
|
||||
https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for
|
||||
<https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for
|
||||
more details
|
||||
|
||||
The current patch queue for OsmoGGSN can be seen at
|
||||
https://gerrit.osmocom.org/#/q/project:osmo-ggsn+status:open
|
||||
<https://gerrit.osmocom.org/#/q/project:osmo-ggsn+status:open>
|
||||
|
||||
|
||||
QuickStart
|
||||
|
@ -75,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
|
||||
-------
|
||||
|
||||
|
@ -144,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
|
||||
|
@ -182,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
|
||||
---------
|
||||
|
@ -195,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
|
||||
|
@ -213,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
|
||||
|
@ -241,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:
|
||||
|
@ -269,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)
|
||||
|
@ -289,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
|
||||
|
@ -306,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)
|
||||
|
@ -330,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
|
||||
|
@ -344,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
|
||||
|
||||
```
|
||||
|
|
|
@ -7,3 +7,6 @@
|
|||
# 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
|
||||
libgtp REMOVE ABI change (removed API: ipv42eua, eua2ipv4)
|
||||
libgtpnl > 1.2.5 gtp_tunnel_set_family()
|
||||
|
|
10
configure.ac
10
configure.ac
|
@ -154,9 +154,9 @@ adl_FUNC_GETOPT_LONG
|
|||
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
|
||||
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(LIBOSMOCORE, libosmocore >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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.7.0
|
||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.7.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.7.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
|
|
@ -1,13 +1,20 @@
|
|||
[Unit]
|
||||
Description=OsmoGGSN
|
||||
After=networking.service
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
StateDirectory=osmocom
|
||||
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
|
||||
|
|
|
@ -1,3 +1,58 @@
|
|||
osmo-ggsn (1.11.0) unstable; urgency=medium
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* gtp: Add net GTP cause values and a function to check for success
|
||||
|
||||
-- Oliver Smith <osmith@sysmocom.de> Tue, 28 Nov 2023 13:38:29 +0100
|
||||
|
||||
osmo-ggsn (1.10.2) unstable; urgency=medium
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* Do not hard-code -g and -O2 in CFLAGS
|
||||
* tests: use -no-install libtool flag to avoid ./lt-* scripts
|
||||
|
||||
[ Oliver Smith ]
|
||||
* doc/manuals/chapters/configuration: fix typo
|
||||
* debian: set compat level to 10
|
||||
* systemd: depend on networking-online.target
|
||||
* README: update documentation section
|
||||
* doc: running: update kernel-gtp limitations
|
||||
* lib/in46_addr: add in46a_from_gsna
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 12 Sep 2023 14:36:10 +0200
|
||||
|
||||
osmo-ggsn (1.10.1) unstable; urgency=medium
|
||||
|
||||
[ Oliver Smith ]
|
||||
* debian/libgtp6.shlibs: new file
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* lib/icmpv6.h: fix struct icmpv6_{radv_hdr,opt_prefix}
|
||||
* gtp/gsn.c: fix 'No newline at end of file'
|
||||
* gtp: use OSMO_ASSERT() in gtp_new()
|
||||
|
||||
-- Vadim Yanitskiy <vyanitskiy@sysmocom.de> Mon, 27 Feb 2023 22:35:47 +0700
|
||||
|
||||
osmo-ggsn (1.10.0) unstable; urgency=medium
|
||||
|
||||
[ Max ]
|
||||
* Set working directory in systemd service file
|
||||
* Ignore .deb build byproducts
|
||||
* ctrl: take both address and port from vty config
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* cosmetic: gtp: Fix typo in comment
|
||||
* Split gsn_t related APIs out of gtp.{c,h}
|
||||
* Use rate_ctr for gsn_t available_counters
|
||||
* ggsn: Introduce tdef and make it configurable over VTY
|
||||
* gtp: Introduce VTY configurable GTP timer X3
|
||||
* Fix typos in comments and VTY descriptions
|
||||
|
||||
[ arehbein ]
|
||||
* osmo-ggsn: Transition to use of 'telnet_init_default'
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 07 Feb 2023 14:29:48 +0100
|
||||
|
||||
osmo-ggsn (1.9.0) unstable; urgency=medium
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
|
|
|
@ -1 +1 @@
|
|||
9
|
||||
10
|
||||
|
|
|
@ -2,12 +2,12 @@ Source: osmo-ggsn
|
|||
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
|
||||
Section: net
|
||||
Priority: optional
|
||||
Build-Depends: debhelper (>= 9),
|
||||
Build-Depends: debhelper (>= 10),
|
||||
autotools-dev,
|
||||
pkg-config,
|
||||
libdpkg-perl, git,
|
||||
dh-autoreconf,
|
||||
libosmocore-dev (>= 1.7.0),
|
||||
libosmocore-dev (>= 1.9.0),
|
||||
osmo-gsm-manuals-dev,
|
||||
libgtpnl-dev (>= 1.2.0)
|
||||
Standards-Version: 3.9.6
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# Most recent version of the package that added new symbols (OS#5318)
|
||||
libgtp 6 libgtp6 (>= 1.8.0)
|
|
@ -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
|
||||
|
||||
:
|
|
@ -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#
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -101,7 +101,7 @@ OsmoGGSN(config-ggsn)# no shutdown ggsn <4>
|
|||
----
|
||||
<1> Change into privileged mode
|
||||
<2> Enter the interactive configuration mode
|
||||
<3> Enter the config ndoe of the GGSN instance `ggsn0`
|
||||
<3> Enter the config node of the GGSN instance `ggsn0`
|
||||
<4> Take the GGSN instance out of shutdown
|
||||
|
||||
|
||||
|
@ -121,7 +121,7 @@ OsmoGGSN(config-ggsn)# shutdown ggsn <4>
|
|||
----
|
||||
<1> Change into privileged mode
|
||||
<2> Enter the interactive configuration mode
|
||||
<3> Enter the config ndoe of the GGSN instance `ggsn0`
|
||||
<3> Enter the config node of the GGSN instance `ggsn0`
|
||||
<4> Shut down the GGSN instance
|
||||
|
||||
|
||||
|
@ -215,8 +215,8 @@ OsmoGGSN(config-ggsn-apn)# no shutdown <5>
|
|||
----
|
||||
<1> Change into privileged mode
|
||||
<2> Enter the interactive configuration mode
|
||||
<3> Enter the config ndoe of the GGSN instance `ggsn0`
|
||||
<4> Enter the config ndoe of the APN `internet`
|
||||
<3> Enter the config node of the GGSN instance `ggsn0`
|
||||
<4> Enter the config node of the APN `internet`
|
||||
<5> Take the APN out of shutdown
|
||||
|
||||
|
||||
|
@ -237,8 +237,8 @@ OsmoGGSN(config-ggsn-apn)# shutdown <5>
|
|||
----
|
||||
<1> Change into privileged mode
|
||||
<2> Enter the interactive configuration mode
|
||||
<3> Enter the config ndoe of the GGSN instance `ggsn0`
|
||||
<4> Enter the config ndoe of the APN `internet`
|
||||
<3> Enter the config node of the GGSN instance `ggsn0`
|
||||
<4> Enter the config node of the APN `internet`
|
||||
<5> Shut down the APN
|
||||
|
||||
[[ggsn_no_root]]
|
||||
|
@ -302,7 +302,7 @@ Name=apn0 <1>
|
|||
Address=192.168.7.1/24 <2>
|
||||
IPMasquerade=yes <3>
|
||||
----
|
||||
<1> The netowrk device name, which must match the one in the apn0.netdev unit file above
|
||||
<1> The network device name, which must match the one in the apn0.netdev unit file above
|
||||
<2> The local IP address configured on the device
|
||||
<3> Requesting systemd to configure IP masquerading for this interface. Depending on your needs,
|
||||
You may not want this if you have proper end-to-end routing set up, and want to have transparent
|
||||
|
|
|
@ -83,7 +83,12 @@ ggsn ggsn0
|
|||
|
||||
=== GTP-U kernel module
|
||||
|
||||
WARNING: As of writing, the kernel module does not support IPv6.
|
||||
WARNING: As of writing, IPv6 support for the kernel module has not been
|
||||
upstreamed yet (OS#1952).
|
||||
|
||||
WARNING: As of writing, it is not possible to configure multiple APNs with
|
||||
gtpu-mode kernel-gpt. This is a limitation in OsmoGGSN, not in the
|
||||
kernel module (OS#6106).
|
||||
|
||||
OsmoGGSN has support to use the Linux kernel GTP-U tunnel driver to accelerate
|
||||
the data/user plane while still implementing the control plane (GTP-C) in
|
||||
|
|
|
@ -2,7 +2,16 @@ bin_PROGRAMS = osmo-ggsn
|
|||
|
||||
AM_LDFLAGS = @EXEC_LDFLAGS@
|
||||
|
||||
AM_CFLAGS = -O2 -D_GNU_SOURCE -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS)
|
||||
AM_CFLAGS = \
|
||||
-D_GNU_SOURCE \
|
||||
-fno-builtin \
|
||||
-Wall \
|
||||
-DSBINDIR='"$(sbindir)"' \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOCTRL_CFLAGS) \
|
||||
$(LIBOSMOVTY_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
osmo_ggsn_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBOSMOVTY_LIBS)
|
||||
|
||||
|
|
18
ggsn/ggsn.c
18
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);
|
||||
|
@ -193,7 +195,7 @@ int apn_start(struct apn_ctx *apn)
|
|||
}
|
||||
LOGPAPN(LOGL_INFO, apn, "Opened TUN device %s\n", apn->tun.tun->devname);
|
||||
|
||||
/* Register with libosmcoore */
|
||||
/* Register with libosmocore */
|
||||
osmo_fd_setup(&apn->tun.fd, apn->tun.tun->fd, OSMO_FD_READ, ggsn_tun_fd_cb, apn, 0);
|
||||
osmo_fd_register(&apn->tun.fd);
|
||||
|
||||
|
@ -202,11 +204,6 @@ int apn_start(struct apn_ctx *apn)
|
|||
break;
|
||||
case APN_GTPU_MODE_KERNEL_GTP:
|
||||
LOGPAPN(LOGL_INFO, apn, "Opening Kernel GTP device %s\n", apn->tun.cfg.dev_name);
|
||||
if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
|
||||
LOGPAPN(LOGL_ERROR, apn, "Kernel GTP currently supports only IPv4\n");
|
||||
apn_stop(apn);
|
||||
return -1;
|
||||
}
|
||||
if (gsn == NULL) {
|
||||
/* skip bringing up the APN now if the GSN is not initialized yet.
|
||||
* This happens during initial load of the config file, as the
|
||||
|
@ -536,10 +533,11 @@ int create_context_ind(struct pdp_t *pdp)
|
|||
|
||||
in46a_to_eua(addr, num_addr, &pdp->eua);
|
||||
|
||||
if (apn->cfg.gtpu_mode == APN_GTPU_MODE_KERNEL_GTP && apn_supports_ipv4(apn)) {
|
||||
/* TODO: In IPv6, EUA doesn't contain the actual IP addr/prefix! */
|
||||
if (apn->cfg.gtpu_mode == APN_GTPU_MODE_KERNEL_GTP) {
|
||||
if (gtp_kernel_tunnel_add(pdp, apn->tun.cfg.dev_name) < 0) {
|
||||
LOGPPDP(LOGL_ERROR, pdp, "Cannot add tunnel to kernel: %s\n", strerror(errno));
|
||||
if (addrv6 && errno == EINVAL)
|
||||
LOGPPDP(LOGL_ERROR, pdp, "Maybe your kernel does not support GTP-U with IPv6 yet?\n");
|
||||
gtp_create_context_resp(gsn, pdp, GTPCAUSE_SYS_FAIL);
|
||||
return 0;
|
||||
}
|
||||
|
|
10
ggsn/ggsn.h
10
ggsn/ggsn.h
|
@ -6,13 +6,14 @@
|
|||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#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"
|
||||
|
||||
|
@ -65,9 +66,9 @@ struct apn_ctx {
|
|||
uint32_t apn_type_mask;
|
||||
/* GTP-U via TUN device or in Linux kernel */
|
||||
enum apn_gtpu_mode gtpu_mode;
|
||||
/* administratively shut-down (true) or not (false) */
|
||||
/* administratively shut down (true) or not (false) */
|
||||
bool shutdown;
|
||||
/* transmit G-PDU sequeence numbers (true) or not (false) */
|
||||
/* transmit G-PDU sequence numbers (true) or not (false) */
|
||||
bool tx_gpdu_seq;
|
||||
} cfg;
|
||||
|
||||
|
@ -127,7 +128,7 @@ struct ggsn_ctx {
|
|||
char *state_dir;
|
||||
/* Time between Echo requests on each SGSN */
|
||||
unsigned int echo_interval;
|
||||
/* administratively shut-down (true) or not (false) */
|
||||
/* administratively shut down (true) or not (false) */
|
||||
bool shutdown;
|
||||
} cfg;
|
||||
|
||||
|
@ -152,6 +153,7 @@ struct apn_ctx *ggsn_find_or_create_apn(struct ggsn_ctx *ggsn, const char *name)
|
|||
/* ggsn_main.c */
|
||||
extern struct ctrl_handle *g_ctrlh;
|
||||
extern void *tall_ggsn_ctx;
|
||||
extern struct osmo_tdef_group ggsn_tdef_group[];
|
||||
|
||||
/* ggsn.c */
|
||||
extern int ggsn_start(struct ggsn_ctx *ggsn);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <osmocom/core/stats.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/tdef.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/control_cmd.h>
|
||||
|
@ -60,6 +61,11 @@ struct ul255_t apn;
|
|||
|
||||
static char *config_file = "osmo-ggsn.cfg";
|
||||
|
||||
struct osmo_tdef_group ggsn_tdef_group[] = {
|
||||
{.name = "gtp", .tdefs = gtp_T_defs, .desc = "GTP (libgtp) timers" },
|
||||
{ }
|
||||
};
|
||||
|
||||
/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
|
||||
static void signal_handler(int s)
|
||||
{
|
||||
|
@ -217,12 +223,11 @@ int main(int argc, char **argv)
|
|||
exit(2);
|
||||
}
|
||||
|
||||
rc = telnet_init_dynif(tall_ggsn_ctx, NULL, vty_get_bind_addr(), OSMO_VTY_PORT_GGSN);
|
||||
rc = telnet_init_default(tall_ggsn_ctx, NULL, OSMO_VTY_PORT_GGSN);
|
||||
if (rc < 0)
|
||||
exit(1);
|
||||
|
||||
g_ctrlh = ctrl_interface_setup_dynip(NULL, ctrl_vty_get_bind_addr(),
|
||||
OSMO_CTRL_PORT_GGSN, NULL);
|
||||
g_ctrlh = ctrl_interface_setup(NULL, OSMO_CTRL_PORT_GGSN, NULL);
|
||||
if (!g_ctrlh) {
|
||||
LOGP(DGGSN, LOGL_ERROR, "Failed to create CTRL interface.\n");
|
||||
exit(1);
|
||||
|
|
|
@ -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>
|
||||
|
@ -33,14 +35,16 @@
|
|||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
#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"
|
||||
|
@ -222,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;
|
||||
|
@ -298,7 +307,7 @@ DEFUN(cfg_ggsn_no_default_apn, cfg_ggsn_no_default_apn_cmd,
|
|||
|
||||
DEFUN(cfg_ggsn_shutdown, cfg_ggsn_shutdown_cmd,
|
||||
"shutdown ggsn",
|
||||
"Put the GGSN in administrative shut-down\n" GGSN_STR)
|
||||
"Put the GGSN in administrative shutdown\n" GGSN_STR)
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
|
||||
|
@ -315,7 +324,7 @@ DEFUN(cfg_ggsn_shutdown, cfg_ggsn_shutdown_cmd,
|
|||
|
||||
DEFUN(cfg_ggsn_no_shutdown, cfg_ggsn_no_shutdown_cmd,
|
||||
"no shutdown ggsn",
|
||||
NO_STR GGSN_STR "Remove the GGSN from administrative shut-down\n")
|
||||
NO_STR GGSN_STR "Remove the GGSN from administrative shutdown\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
|
||||
|
@ -343,7 +352,7 @@ static void show_one_sgsn(struct vty *vty, const struct sgsn_peer *sgsn, const c
|
|||
|
||||
DEFUN(cfg_ggsn_show_sgsn, cfg_ggsn_show_sgsn_cmd,
|
||||
"show sgsn",
|
||||
NO_STR GGSN_STR "Remove the GGSN from administrative shut-down\n")
|
||||
NO_STR GGSN_STR "Remove the GGSN from administrative shutdown\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
struct sgsn_peer *sgsn;
|
||||
|
@ -680,7 +689,7 @@ DEFUN(cfg_apn_no_gpdu_seq, cfg_apn_no_gpdu_seq_cmd,
|
|||
|
||||
DEFUN(cfg_apn_shutdown, cfg_apn_shutdown_cmd,
|
||||
"shutdown",
|
||||
"Put the APN in administrative shut-down\n")
|
||||
"Put the APN in administrative shutdown\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
|
||||
|
@ -697,7 +706,7 @@ DEFUN(cfg_apn_shutdown, cfg_apn_shutdown_cmd,
|
|||
|
||||
DEFUN(cfg_apn_no_shutdown, cfg_apn_no_shutdown_cmd,
|
||||
"no shutdown",
|
||||
NO_STR "Remove the APN from administrative shut-down\n")
|
||||
NO_STR "Remove the APN from administrative shutdown\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
|
||||
|
@ -795,6 +804,7 @@ static int config_write_ggsn(struct vty *vty)
|
|||
vty_out(vty, " gtp control-ip %s%s", in46a_ntoa(&ggsn->cfg.gtpc_addr), VTY_NEWLINE);
|
||||
if (ggsn->cfg.gtpu_addr.v4.s_addr)
|
||||
vty_out(vty, " gtp user-ip %s%s", in46a_ntoa(&ggsn->cfg.gtpu_addr), VTY_NEWLINE);
|
||||
osmo_tdef_vty_groups_write(vty, " ");
|
||||
llist_for_each_entry(apn, &ggsn->apn_list, list)
|
||||
config_write_apn(vty, apn);
|
||||
if (ggsn->cfg.default_apn)
|
||||
|
@ -812,10 +822,7 @@ static const char *print_gsnaddr(const struct ul16_t *in)
|
|||
{
|
||||
struct in46_addr in46;
|
||||
|
||||
in46.len = in->l;
|
||||
OSMO_ASSERT(in->l <= sizeof(in46.v6));
|
||||
memcpy(&in46.v6, in->v, in->l);
|
||||
|
||||
in46a_from_gsna(in, &in46);
|
||||
return in46a_ntoa(&in46);
|
||||
}
|
||||
|
||||
|
@ -1113,6 +1120,8 @@ int ggsn_vty_init(void)
|
|||
install_element(GGSN_NODE, &cfg_ggsn_echo_interval_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
|
||||
|
||||
osmo_tdef_vty_groups_init(GGSN_NODE, ggsn_tdef_group);
|
||||
|
||||
install_node(&apn_node, NULL);
|
||||
install_element(APN_NODE, &cfg_description_cmd);
|
||||
install_element(APN_NODE, &cfg_no_description_cmd);
|
||||
|
|
|
@ -110,6 +110,7 @@ ret_broken:
|
|||
osmo_hexdump_nospc((const uint8_t *)pco_in, pco_in->length));
|
||||
}
|
||||
|
||||
/* Handle IP Control Protocol, RFC 1332, extensions in RFC 1877 */
|
||||
static void process_pco_element_ipcp(const struct pco_element *pco_elem, struct msgb *resp,
|
||||
const struct apn_ctx *apn, struct pdp_t *pdp)
|
||||
{
|
||||
|
|
11
ggsn/pco.h
11
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 {
|
||||
|
@ -42,12 +42,11 @@ struct pco_element {
|
|||
uint8_t data[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/* RFC 1332 */
|
||||
/* RFC 1332 IP Control Protocol options, extensions in RFC 1877 */
|
||||
enum ipcp_options {
|
||||
IPCP_OPT_IPADDR = 3,
|
||||
IPCP_OPT_PRIMARY_DNS = 129,
|
||||
IPCP_OPT_SECONDARY_DNS = 131,
|
||||
IPCP_OPT_IPADDR = 3, /* RFC 1332 3.3 */
|
||||
IPCP_OPT_PRIMARY_DNS = 129, /* RFC 1877 1.1 */
|
||||
IPCP_OPT_SECONDARY_DNS = 131, /* RFC 1877 1.2 */
|
||||
};
|
||||
|
||||
struct ipcp_option_hdr {
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2,14 +2,30 @@
|
|||
# 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=8:1:2
|
||||
LIBVERSION=9:1:3
|
||||
|
||||
lib_LTLIBRARIES = libgtp.la
|
||||
|
||||
include_HEADERS = gtp.h pdp.h gtpie.h
|
||||
AM_CFLAGS = \
|
||||
-fno-builtin \
|
||||
-Wall \
|
||||
-DSBINDIR='"$(sbindir)"' \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = -O2 -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
|
||||
libgtp_la_SOURCES = \
|
||||
gsn.c \
|
||||
gsn_internal.h \
|
||||
gtp.c \
|
||||
gtp_internal.h \
|
||||
gtpie.c \
|
||||
lookupa.c \
|
||||
lookupa.h \
|
||||
pdp.c \
|
||||
queue.c \
|
||||
queue.h \
|
||||
$(NULL)
|
||||
|
||||
libgtp_la_SOURCES = gtp.c gtp.h gtpie.c gtpie.h pdp.c pdp.h lookupa.c lookupa.h queue.c queue.h
|
||||
libgtp_la_LDFLAGS = -version-info $(LIBVERSION) -no-undefined
|
||||
libgtp_la_LIBADD = $(LIBOSMOCORE_LIBS)
|
||||
|
|
|
@ -0,0 +1,578 @@
|
|||
/*
|
||||
* OsmoGGSN - Gateway GPRS Support Node
|
||||
* Copyright (C) 2002, 2003, 2004 Mondru AB.
|
||||
* Copyright (C) 2010-2011, 2016-2017 Harald Welte <laforge@gnumonks.org>
|
||||
* Copyright (C) 2015-2017 sysmocom - s.f.m.c. GmbH
|
||||
*
|
||||
* The contents of this file may be used under the terms of the GNU
|
||||
* General Public License Version 2, provided that the above copyright
|
||||
* notice and this permission notice is included in all copies or
|
||||
* substantial portions of the software.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* gtp.c: Contains all GTP functionality. Should be able to handle multiple
|
||||
* tunnels in the same program.
|
||||
*
|
||||
* TODO:
|
||||
* - Do we need to handle fragmentation?
|
||||
*/
|
||||
|
||||
#ifdef __linux__
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
#include "../config.h"
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* #include <stdint.h> ISO C99 types */
|
||||
|
||||
#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 */
|
||||
|
||||
#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...) \
|
||||
LOGP(ss, level, "addr(%s:%d) " fmt, \
|
||||
inet_ntoa((addr).sin_addr), htons((addr).sin_port), \
|
||||
##args)
|
||||
|
||||
static const struct rate_ctr_desc gsn_ctr_description[] = {
|
||||
[GSN_CTR_ERR_SOCKET] = { "err:socket", "Socket error" },
|
||||
[GSN_CTR_ERR_READFROM] = { "err:readfrom", "readfrom() errors" },
|
||||
[GSN_CTR_ERR_SENDTO] = { "err:sendto", "sendto() errors" },
|
||||
[GSN_CTR_ERR_QUEUEFULL] = { "err:queuefull", "Failed to queue message because queue is full" },
|
||||
[GSN_CTR_ERR_SEQ] = { "err:seq", "Sequence number out of range" },
|
||||
[GSN_CTR_ERR_ADDRESS] = { "err:address", "GSN address conversion failed" },
|
||||
[GSN_CTR_ERR_UNKNOWN_PDP] = { "err:unknown_pdp", "Failed looking up PDP context" },
|
||||
[GSN_CTR_ERR_UNEXPECTED_CAUSE] = { "err:unexpected_cause", "Unexpected cause value received" },
|
||||
[GSN_CTR_ERR_OUT_OF_PDP] = { "err:out_of_pdp", "Out of storage for PDP contexts" },
|
||||
[GSN_CTR_PKT_EMPTY] = { "pkt:empty", "Empty packet received" },
|
||||
[GSN_CTR_PKT_UNSUP] = { "pkt:unsupported", "Unsupported GTP version received" },
|
||||
[GSN_CTR_PKT_TOOSHORT] = { "pkt:too_short", "Packet too short received" },
|
||||
[GSN_CTR_PKT_UNKNOWN] = { "pkt:unknown", "Unknown packet type received" },
|
||||
[GSN_CTR_PKT_UNEXPECT] = { "pkt:unexpected", "Unexpected packet type received" },
|
||||
[GSN_CTR_PKT_DUPLICATE] = { "pkt:duplicate", "Duplicate or unsolicited packet received" },
|
||||
[GSN_CTR_PKT_MISSING] = { "pkt:missing", "Missing IE in packet received" },
|
||||
[GSN_CTR_PKT_INCORRECT] = { "pkt:incorrect", "Incorrect IE in packet received" },
|
||||
[GSN_CTR_PKT_INVALID] = { "pkt:invalid", "Invalid format in packet received" },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc gsn_ctrg_desc = {
|
||||
"gsn",
|
||||
"GSN Statistics",
|
||||
OSMO_STATS_CLASS_PEER,
|
||||
ARRAY_SIZE(gsn_ctr_description),
|
||||
gsn_ctr_description,
|
||||
};
|
||||
static unsigned int gsn_ctr_next_idx = 0;
|
||||
|
||||
/* Global timer definitions for GTP operation, provided for convenience. To make these user configurable, it is convenient to add
|
||||
* gtp_gsn_tdefs as one of your program's osmo_tdef_group entries and call osmo_tdef_vty_init(). */
|
||||
struct osmo_tdef gtp_T_defs[] = {
|
||||
{ .T = GTP_GSN_TIMER_T3_RESPONSE, .default_val = 5, .unit = OSMO_TDEF_S,
|
||||
.desc = "Timer T3-RESPONSE holds the maximum wait time for a response of a request message"
|
||||
},
|
||||
{ .T = GTP_GSN_TIMER_N3_REQUESTS, .default_val = 3, .unit = OSMO_TDEF_CUSTOM,
|
||||
.desc = "Counter N3-REQUESTS holds the maximum number of attempts made by GTP to send a request message"
|
||||
},
|
||||
{ .T = GTP_GSN_TIMER_T3_HOLD_RESPONSE, .default_val = 5 * 3 /* (GTP_GSN_TIMER_T3_RESPONSE * GTP_GSN_TIMER_N3_REQUESTS) */, .unit = OSMO_TDEF_S,
|
||||
.desc = "Time a GTP respoonse message is kept cached to re-transmit it when a duplicate request is received. Value is generally equal to (T3-RESPONSE * N3-REQUESTS) set at the peer"
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
/* API Functions */
|
||||
|
||||
/* Deprecated, use gtp_pdp_newpdp() instead */
|
||||
int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
|
||||
uint64_t imsi, uint8_t nsapi)
|
||||
{
|
||||
int rc;
|
||||
rc = gtp_pdp_newpdp(gsn, pdp, imsi, nsapi, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp)
|
||||
{
|
||||
if (gsn->cb_delete_context)
|
||||
gsn->cb_delete_context(pdp);
|
||||
return pdp_freepdp(pdp);
|
||||
}
|
||||
|
||||
/* Free pdp and all its secondary PDP contexts. Must be called on the primary PDP context. */
|
||||
int gtp_freepdp_teardown(struct gsn_t *gsn, struct pdp_t *pdp)
|
||||
{
|
||||
int n;
|
||||
struct pdp_t *secondary_pdp;
|
||||
OSMO_ASSERT(!pdp->secondary);
|
||||
|
||||
for (n = 0; n < PDP_MAXNSAPI; n++) {
|
||||
if (pdp->secondary_tei[n]) {
|
||||
if (gtp_pdp_getgtp1(gsn, &secondary_pdp,
|
||||
pdp->secondary_tei[n])) {
|
||||
LOGP(DLGTP, LOGL_ERROR,
|
||||
"Unknown secondary PDP context\n");
|
||||
continue;
|
||||
}
|
||||
if (pdp != secondary_pdp) {
|
||||
gtp_freepdp(gsn, secondary_pdp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gtp_freepdp(gsn, pdp);
|
||||
}
|
||||
|
||||
/* gtp_gpdu */
|
||||
|
||||
extern int gtp_fd(struct gsn_t *gsn)
|
||||
{
|
||||
return gsn->fd0;
|
||||
}
|
||||
|
||||
int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer))
|
||||
{
|
||||
gsn->cb_unsup_ind = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer))
|
||||
{
|
||||
gsn->cb_extheader_ind = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_set_cb_ran_info_relay_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer, union gtpie_member **ie))
|
||||
{
|
||||
gsn->cb_ran_info_relay_ind = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API: Initialise delete context callback */
|
||||
/* Called whenever a pdp context is deleted for any reason */
|
||||
int gtp_set_cb_delete_context(struct gsn_t *gsn, int (*cb) (struct pdp_t * pdp))
|
||||
{
|
||||
gsn->cb_delete_context = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_set_cb_conf(struct gsn_t *gsn,
|
||||
int (*cb) (int type, int cause,
|
||||
struct pdp_t * pdp, void *cbp))
|
||||
{
|
||||
gsn->cb_conf = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_set_cb_recovery(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer, uint8_t recovery))
|
||||
{
|
||||
gsn->cb_recovery = cb;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cb_recovery()
|
||||
* pdp may be NULL if Recovery IE was received from a message independent
|
||||
* of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
|
||||
* local setup. In case pdp is known, caller may want to keep that pdp alive to
|
||||
* handle subsequent msg cb as this specific pdp ctx is still valid according to
|
||||
* specs.
|
||||
*/
|
||||
int gtp_set_cb_recovery2(struct gsn_t *gsn,
|
||||
int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery))
|
||||
{
|
||||
gsn->cb_recovery2 = cb_recovery2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cb_recovery()
|
||||
* pdp may be NULL if Recovery IE was received from a message independent
|
||||
* of any PDP ctx (such as Echo Response), or because pdp ctx is unknown to the
|
||||
* local setup. In case pdp is known, caller may want to keep that pdp alive to
|
||||
* handle subsequent msg cb as this specific pdp ctx is still valid according to
|
||||
* specs.
|
||||
*/
|
||||
int gtp_set_cb_recovery3(struct gsn_t *gsn,
|
||||
int (*cb_recovery3) (struct gsn_t *gsn, struct sockaddr_in *peer,
|
||||
struct pdp_t *pdp, uint8_t recovery))
|
||||
{
|
||||
gsn->cb_recovery3 = cb_recovery3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_set_cb_data_ind(struct gsn_t *gsn,
|
||||
int (*cb_data_ind) (struct pdp_t * pdp,
|
||||
void *pack, unsigned len))
|
||||
{
|
||||
gsn->cb_data_ind = cb_data_ind;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int queue_timer_retrans(struct gsn_t *gsn)
|
||||
{
|
||||
/* Retransmit any outstanding packets */
|
||||
/* Remove from queue if maxretrans exceeded */
|
||||
time_t now;
|
||||
struct qmsg_t *qmsg;
|
||||
unsigned int t3_response, n3_requests;
|
||||
|
||||
now = time(NULL);
|
||||
t3_response = osmo_tdef_get(gsn->tdef, GTP_GSN_TIMER_T3_RESPONSE, OSMO_TDEF_S, -1);
|
||||
n3_requests = osmo_tdef_get(gsn->tdef, GTP_GSN_TIMER_N3_REQUESTS, OSMO_TDEF_CUSTOM, -1);
|
||||
|
||||
/* get first element in queue, as long as the timeout of that
|
||||
* element has expired */
|
||||
while ((!queue_getfirst(gsn->queue_req, &qmsg)) &&
|
||||
(qmsg->timeout <= now)) {
|
||||
if (qmsg->retrans > n3_requests) { /* Too many retrans */
|
||||
LOGP(DLGTP, LOGL_NOTICE, "Retransmit req queue timeout of seq %" PRIu16 "\n",
|
||||
qmsg->seq);
|
||||
if (gsn->cb_conf)
|
||||
gsn->cb_conf(qmsg->type, EOF, NULL, qmsg->cbp);
|
||||
queue_freemsg(gsn->queue_req, qmsg);
|
||||
} else {
|
||||
LOGP(DLGTP, LOGL_INFO, "Retransmit (%d) of seq %" PRIu16 "\n",
|
||||
qmsg->retrans, qmsg->seq);
|
||||
if (sendto(qmsg->fd, &qmsg->p, qmsg->l, 0,
|
||||
(struct sockaddr *)&qmsg->peer,
|
||||
sizeof(struct sockaddr_in)) < 0) {
|
||||
rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SENDTO);
|
||||
LOGP(DLGTP, LOGL_ERROR,
|
||||
"Sendto(fd0=%d, msg=%lx, len=%d) failed: Error = %s\n",
|
||||
gsn->fd0, (unsigned long)&qmsg->p,
|
||||
qmsg->l, strerror(errno));
|
||||
}
|
||||
queue_back(gsn->queue_req, qmsg);
|
||||
qmsg->timeout = now + t3_response;
|
||||
qmsg->retrans++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Also clean up reply timeouts */
|
||||
while ((!queue_getfirst(gsn->queue_resp, &qmsg)) &&
|
||||
(qmsg->timeout < now)) {
|
||||
LOGP(DLGTP, LOGL_DEBUG, "Retransmit resp queue seq %"
|
||||
PRIu16 " expired, removing from queue\n", qmsg->seq);
|
||||
queue_freemsg(gsn->queue_resp, qmsg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int queue_timer_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
|
||||
{
|
||||
time_t now, later, diff;
|
||||
struct qmsg_t *qmsg;
|
||||
timeout->tv_usec = 0;
|
||||
|
||||
if (queue_getfirst(gsn->queue_req, &qmsg)) {
|
||||
timeout->tv_sec = 10;
|
||||
} else {
|
||||
now = time(NULL);
|
||||
later = qmsg->timeout;
|
||||
timeout->tv_sec = later - now;
|
||||
if (timeout->tv_sec < 0)
|
||||
timeout->tv_sec = 0; /* No negative allowed */
|
||||
if (timeout->tv_sec > 10)
|
||||
timeout->tv_sec = 10; /* Max sleep for 10 sec */
|
||||
}
|
||||
|
||||
if (queue_getfirst(gsn->queue_resp, &qmsg)) {
|
||||
/* already set by queue_req, do nothing */
|
||||
} else { /* trigger faster if earlier timeout exists in queue_resp */
|
||||
now = time(NULL);
|
||||
later = qmsg->timeout;
|
||||
diff = later - now;
|
||||
if (diff < 0)
|
||||
diff = 0;
|
||||
if (diff < timeout->tv_sec)
|
||||
timeout->tv_sec = diff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gtp_queue_timer_start(struct gsn_t *gsn)
|
||||
{
|
||||
struct timeval next;
|
||||
|
||||
/* Retrieve next retransmission as timeval */
|
||||
queue_timer_retranstimeout(gsn, &next);
|
||||
|
||||
/* re-schedule the timer */
|
||||
osmo_timer_schedule(&gsn->queue_timer, next.tv_sec, next.tv_usec/1000);
|
||||
}
|
||||
|
||||
/* timer callback for libgtp retransmission and ping */
|
||||
static void queue_timer_cb(void *data)
|
||||
{
|
||||
struct gsn_t *gsn = data;
|
||||
|
||||
/* do all the retransmissions as needed */
|
||||
queue_timer_retrans(gsn);
|
||||
|
||||
gtp_queue_timer_start(gsn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief clear the request and response queue. Useful for debugging to reset "some" state.
|
||||
* @param gsn The GGSN instance
|
||||
*/
|
||||
void gtp_clear_queues(struct gsn_t *gsn)
|
||||
{
|
||||
struct qmsg_t *qmsg;
|
||||
|
||||
LOGP(DLGTP, LOGL_INFO, "Clearing req & resp retransmit queues\n");
|
||||
while (!queue_getfirst(gsn->queue_req, &qmsg)) {
|
||||
queue_freemsg(gsn->queue_req, qmsg);
|
||||
}
|
||||
|
||||
while (!queue_getfirst(gsn->queue_resp, &qmsg)) {
|
||||
queue_freemsg(gsn->queue_resp, qmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform restoration and recovery error handling as described in 29.060 */
|
||||
static void log_restart(struct gsn_t *gsn)
|
||||
{
|
||||
FILE *f;
|
||||
int i, rc;
|
||||
int counter = 0;
|
||||
char *filename;
|
||||
|
||||
filename = talloc_asprintf(NULL, "%s/%s", gsn->statedir, RESTART_FILE);
|
||||
OSMO_ASSERT(filename);
|
||||
|
||||
/* We try to open file. On failure we will later try to create file */
|
||||
if (!(f = fopen(filename, "r"))) {
|
||||
LOGP(DLGTP, LOGL_NOTICE,
|
||||
"State information file (%s) not found. Creating new file.\n",
|
||||
filename);
|
||||
} else {
|
||||
rc = fscanf(f, "%d", &counter);
|
||||
if (rc != 1) {
|
||||
LOGP(DLGTP, LOGL_ERROR,
|
||||
"fscanf failed to read counter value\n");
|
||||
goto close_file;
|
||||
}
|
||||
if (fclose(f)) {
|
||||
LOGP(DLGTP, LOGL_ERROR,
|
||||
"fclose failed: Error = %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
gsn->restart_counter = (unsigned char)counter;
|
||||
gsn->restart_counter++;
|
||||
|
||||
/* Keep the umask closely wrapped around our fopen() call in case the
|
||||
* log outputs cause file creation. */
|
||||
i = umask(022);
|
||||
f = fopen(filename, "w");
|
||||
umask(i);
|
||||
if (!f) {
|
||||
LOGP(DLGTP, LOGL_ERROR,
|
||||
"fopen(path=%s, mode=%s) failed: Error = %s\n", filename,
|
||||
"w", strerror(errno));
|
||||
goto free_filename;
|
||||
}
|
||||
|
||||
fprintf(f, "%d\n", gsn->restart_counter);
|
||||
close_file:
|
||||
if (fclose(f))
|
||||
LOGP(DLGTP, LOGL_ERROR,
|
||||
"fclose failed: Error = %s\n", strerror(errno));
|
||||
free_filename:
|
||||
talloc_free(filename);
|
||||
}
|
||||
|
||||
static int create_and_bind_socket(const char *name, struct gsn_t *gsn, int *fd, int domain,
|
||||
const struct in_addr *listen, int port)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int type = SOCK_DGRAM;
|
||||
int protocol = 0;
|
||||
|
||||
*fd = socket(domain, type, protocol);
|
||||
|
||||
if (*fd < 0) {
|
||||
rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SOCKET);
|
||||
LOGP(DLGTP, LOGL_ERROR,
|
||||
"%s socket(domain=%d, type=%d, protocol=%d) failed: Error = %s\n",
|
||||
name, domain, type, protocol, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = domain;
|
||||
addr.sin_addr = *listen;
|
||||
addr.sin_port = htons(port);
|
||||
#if defined(__FreeBSD__) || defined(__APPLE__)
|
||||
addr.sin_len = sizeof(addr);
|
||||
#endif
|
||||
|
||||
if (bind(*fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
rate_ctr_inc2(gsn->ctrg, GSN_CTR_ERR_SOCKET);
|
||||
LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr,
|
||||
"%s bind(fd=%d) failed: Error = %s\n",
|
||||
name, *fd, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
|
||||
int mode)
|
||||
{
|
||||
LOGP(DLGTP, LOGL_NOTICE, "GTP: gtp_newgsn() started at %s\n", inet_ntoa(*listen));
|
||||
|
||||
*gsn = calloc(sizeof(struct gsn_t), 1); /* TODO */
|
||||
|
||||
(*gsn)->statedir = statedir;
|
||||
log_restart(*gsn);
|
||||
|
||||
/* Initialise sequence number */
|
||||
(*gsn)->seq_next = (*gsn)->restart_counter * 1024;
|
||||
|
||||
/* Initialize timers: */
|
||||
(*gsn)->tdef = gtp_T_defs;
|
||||
/* Small hack to properly reset tdef for old clients not using the tdef_group: */
|
||||
OSMO_ASSERT(gtp_T_defs[0].default_val != 0);
|
||||
if (gtp_T_defs[0].val == 0)
|
||||
osmo_tdefs_reset((*gsn)->tdef);
|
||||
|
||||
|
||||
/* Initialise request retransmit queue */
|
||||
queue_new(&(*gsn)->queue_req);
|
||||
queue_new(&(*gsn)->queue_resp);
|
||||
|
||||
/* Initialise pdp table */
|
||||
pdp_init(*gsn);
|
||||
|
||||
/* Initialize internal queue timer */
|
||||
osmo_timer_setup(&(*gsn)->queue_timer, queue_timer_cb, *gsn);
|
||||
|
||||
/* Initialize counter group: */
|
||||
(*gsn)->ctrg = rate_ctr_group_alloc(NULL, &gsn_ctrg_desc, gsn_ctr_next_idx++);
|
||||
|
||||
/* Initialise call back functions */
|
||||
(*gsn)->cb_create_context_ind = 0;
|
||||
(*gsn)->cb_delete_context = 0;
|
||||
(*gsn)->cb_unsup_ind = 0;
|
||||
(*gsn)->cb_conf = 0;
|
||||
(*gsn)->cb_data_ind = 0;
|
||||
|
||||
/* Store function parameters */
|
||||
/* Same IP for user traffic and signalling */
|
||||
(*gsn)->gsnc = *listen;
|
||||
(*gsn)->gsnu = *listen;
|
||||
(*gsn)->mode = mode;
|
||||
|
||||
(*gsn)->fd0 = -1;
|
||||
(*gsn)->fd1c = -1;
|
||||
(*gsn)->fd1u = -1;
|
||||
|
||||
/* Create GTP version 0 socket */
|
||||
if (create_and_bind_socket("GTPv0", *gsn, &(*gsn)->fd0, AF_INET, listen, GTP0_PORT) < 0)
|
||||
goto error;
|
||||
|
||||
/* Create GTP version 1 control plane socket */
|
||||
if (create_and_bind_socket("GTPv1 control plane", *gsn, &(*gsn)->fd1c, AF_INET, listen, GTP1C_PORT) < 0)
|
||||
goto error;
|
||||
|
||||
/* Create GTP version 1 user plane socket */
|
||||
if (create_and_bind_socket("GTPv1 user plane", *gsn, &(*gsn)->fd1u, AF_INET, listen, GTP1U_PORT) < 0)
|
||||
goto error;
|
||||
|
||||
/* Start internal queue timer */
|
||||
gtp_queue_timer_start(*gsn);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
gtp_free(*gsn);
|
||||
*gsn = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gtp_free(struct gsn_t *gsn)
|
||||
{
|
||||
|
||||
/* Cleanup internal queue timer */
|
||||
osmo_timer_del(&gsn->queue_timer);
|
||||
|
||||
/* Clean up retransmit queues */
|
||||
queue_free(gsn->queue_req);
|
||||
queue_free(gsn->queue_resp);
|
||||
|
||||
close(gsn->fd0);
|
||||
close(gsn->fd1c);
|
||||
close(gsn->fd1u);
|
||||
|
||||
rate_ctr_group_free(gsn->ctrg);
|
||||
|
||||
free(gsn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API: Register create context indication callback */
|
||||
int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
|
||||
int (*cb_create_context_ind) (struct pdp_t *
|
||||
pdp))
|
||||
{
|
||||
gsn->cb_create_context_ind = cb_create_context_ind;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_retrans(struct gsn_t *gsn)
|
||||
{
|
||||
/* dummy API, deprecated. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout)
|
||||
{
|
||||
timeout->tv_sec = 24*60*60;
|
||||
timeout->tv_usec = 0;
|
||||
/* dummy API, deprecated. Return a huge timer to do nothing */
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void gtp_queue_timer_start(struct gsn_t *gsn);
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
uint64_t gtp_imsi_str2gtp(const char *str);
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
#include "gtp.h"
|
||||
#include <osmocom/gtp/gtp.h>
|
||||
|
||||
#define QUEUE_DEBUG 0 /* Print debug information */
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
SUBDIRS = \
|
||||
osmocom \
|
||||
$(NULL)
|
|
@ -0,0 +1,3 @@
|
|||
SUBDIRS = \
|
||||
gtp \
|
||||
$(NULL)
|
|
@ -0,0 +1,8 @@
|
|||
libgtp_HEADERS = \
|
||||
gsn.h \
|
||||
gtp.h \
|
||||
gtpie.h \
|
||||
pdp.h \
|
||||
$(NULL)
|
||||
|
||||
libgtpdir = $(includedir)/osmocom/gtp
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* OsmoGGSN - Gateway GPRS Support Node
|
||||
* Copyright (C) 2002, 2003, 2004 Mondru AB.
|
||||
*
|
||||
* The contents of this file may be used under the terms of the GNU
|
||||
* General Public License Version 2, provided that the above copyright
|
||||
* notice and this permission notice is included in all copies or
|
||||
* substantial portions of the software.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _GSN_H
|
||||
#define _GSN_H
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/defs.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/tdef.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
||||
#include "pdp.h"
|
||||
|
||||
#define GTP_MODE_GGSN 1
|
||||
#define GTP_MODE_SGSN 2
|
||||
|
||||
#define RESTART_FILE "gsn_restart"
|
||||
|
||||
extern struct osmo_tdef gtp_T_defs[];
|
||||
|
||||
/* ***********************************************************
|
||||
* Information storage for each gsn instance
|
||||
*
|
||||
* Normally each instance of the application corresponds to
|
||||
* one instance of a gsn.
|
||||
*
|
||||
* In order to avoid global variables in the application, and
|
||||
* also in order to allow several instances of a gsn in the same
|
||||
* application this struct is provided in order to store all
|
||||
* relevant information related to the gsn.
|
||||
*
|
||||
* Note that this does not include information storage for '
|
||||
* each pdp context. This is stored in another struct.
|
||||
*************************************************************/
|
||||
|
||||
enum gsn_rate_ctr_keys {
|
||||
GSN_CTR_ERR_SOCKET,
|
||||
GSN_CTR_ERR_READFROM, /* Number of readfrom errors */
|
||||
GSN_CTR_ERR_SENDTO, /* Number of sendto errors */
|
||||
GSN_CTR_ERR_QUEUEFULL, /* Number of times queue was full */
|
||||
GSN_CTR_ERR_SEQ, /* Number of seq out of range */
|
||||
GSN_CTR_ERR_ADDRESS, /* GSN address conversion failed */
|
||||
GSN_CTR_ERR_UNKNOWN_PDP, /* GSN address conversion failed */
|
||||
GSN_CTR_ERR_UNEXPECTED_CAUSE, /* Unexpected cause value received */
|
||||
GSN_CTR_ERR_OUT_OF_PDP, /* Out of storage for PDP contexts */
|
||||
GSN_CTR_PKT_EMPTY, /* Number of empty packets */
|
||||
GSN_CTR_PKT_UNSUP, /* Number of unsupported version 29.60 11.1.1 */
|
||||
GSN_CTR_PKT_TOOSHORT, /* Number of too short headers 29.60 11.1.2 */
|
||||
GSN_CTR_PKT_UNKNOWN, /* Number of unknown messages 29.60 11.1.3 */
|
||||
GSN_CTR_PKT_UNEXPECT, /* Number of unexpected messages 29.60 11.1.4 */
|
||||
GSN_CTR_PKT_DUPLICATE, /* Number of duplicate or unsolicited replies */
|
||||
GSN_CTR_PKT_MISSING, /* Number of missing information field messages */
|
||||
GSN_CTR_PKT_INCORRECT, /* Number of incorrect information field messages */
|
||||
GSN_CTR_PKT_INVALID, /* Number of invalid message format messages */
|
||||
};
|
||||
|
||||
/* 3GPP TS 29.006 14.1, 14,2 */
|
||||
enum gtp_gsn_timers {
|
||||
GTP_GSN_TIMER_T3_RESPONSE = 3,
|
||||
GTP_GSN_TIMER_N3_REQUESTS = 1003,
|
||||
GTP_GSN_TIMER_T3_HOLD_RESPONSE = -3,
|
||||
};
|
||||
|
||||
struct gsn_t {
|
||||
/* Parameters related to the network interface */
|
||||
|
||||
int fd0; /* GTP0 file descriptor */
|
||||
int fd1c; /* GTP1 control plane file descriptor */
|
||||
int fd1u; /* GTP0 user plane file descriptor */
|
||||
int mode; /* Mode of operation: GGSN or SGSN */
|
||||
struct in_addr gsnc; /* IP address of this gsn for signalling */
|
||||
struct in_addr gsnu; /* IP address of this gsn for user traffic */
|
||||
|
||||
/* Parameters related to signalling messages */
|
||||
uint16_t seq_next; /* Next sequence number to use */
|
||||
int seq_first; /* First packet in queue (oldest timeout) */
|
||||
int seq_last; /* Last packet in queue (youngest timeout) */
|
||||
|
||||
unsigned char restart_counter; /* Increment on restart. Stored on disk */
|
||||
char *statedir; /* Disk location for permanent storage */
|
||||
void *priv; /* used by libgtp users to attach their own state) */
|
||||
struct queue_t *queue_req; /* Request queue */
|
||||
struct queue_t *queue_resp; /* Response queue */
|
||||
|
||||
struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
|
||||
struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
|
||||
|
||||
struct osmo_timer_list queue_timer; /* internal queue_{req,resp} timer */
|
||||
|
||||
/* Call back functions */
|
||||
int (*cb_delete_context) (struct pdp_t *);
|
||||
int (*cb_create_context_ind) (struct pdp_t *);
|
||||
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);
|
||||
int (*cb_conf) (int type, int cause, struct pdp_t * pdp, void *cbp);
|
||||
int (*cb_data_ind) (struct pdp_t * pdp, void *pack, unsigned len);
|
||||
int (*cb_recovery) (struct sockaddr_in * peer, uint8_t recovery);
|
||||
int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery);
|
||||
int (*cb_recovery3) (struct gsn_t *gsn, struct sockaddr_in *peer, struct pdp_t *pdp, uint8_t recovery);
|
||||
|
||||
/* Counters */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
/* Timers: */
|
||||
struct osmo_tdef *tdef;
|
||||
};
|
||||
|
||||
/* External API functions */
|
||||
|
||||
extern int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
|
||||
int mode);
|
||||
|
||||
extern int gtp_free(struct gsn_t *gsn);
|
||||
|
||||
extern int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
|
||||
uint64_t imsi, uint8_t nsapi) OSMO_DEPRECATED("Use gtp_pdp_newpdp() instead");
|
||||
extern int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp);
|
||||
extern int gtp_freepdp_teardown(struct gsn_t *gsn, struct pdp_t *pdp);
|
||||
|
||||
extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
|
||||
void *cbp);
|
||||
|
||||
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_data_ind(struct gsn_t *gsn,
|
||||
int (*cb_data_ind) (struct pdp_t * pdp,
|
||||
void *pack, unsigned len));
|
||||
extern int gtp_set_cb_delete_context(struct gsn_t *gsn,
|
||||
int (*cb_delete_context) (struct pdp_t *
|
||||
pdp));
|
||||
/*extern int gtp_set_cb_create_context(struct gsn_t *gsn,
|
||||
int (*cb_create_context) (struct pdp_t* pdp)); */
|
||||
|
||||
extern int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer));
|
||||
|
||||
extern int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer));
|
||||
|
||||
extern int gtp_set_cb_ran_info_relay_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer, union gtpie_member **ie));
|
||||
|
||||
extern int gtp_set_cb_conf(struct gsn_t *gsn,
|
||||
int (*cb) (int type, int cause, struct pdp_t * pdp,
|
||||
void *cbp));
|
||||
|
||||
int gtp_set_cb_recovery(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer,
|
||||
uint8_t recovery))
|
||||
OSMO_DEPRECATED("Use gtp_set_cb_recovery2() instead, to obtain pdp ctx originating the recovery");
|
||||
int gtp_set_cb_recovery2(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer,
|
||||
struct pdp_t * pdp,
|
||||
uint8_t recovery))
|
||||
OSMO_DEPRECATED("Use gtp_set_cb_recovery3() instead, to obtain gsn handling the recovery");
|
||||
int gtp_set_cb_recovery3(struct gsn_t *gsn,
|
||||
int (*cb) (struct gsn_t * gsn, struct sockaddr_in * peer,
|
||||
struct pdp_t * pdp,
|
||||
uint8_t recovery));
|
||||
void gtp_clear_queues(struct gsn_t *gsn);
|
||||
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");
|
||||
|
||||
#endif /* !_GSN_H */
|
|
@ -13,14 +13,10 @@
|
|||
#define _GTP_H
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/defs.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
|
||||
#include "gtpie.h"
|
||||
#include "pdp.h"
|
||||
|
||||
#define GTP_MODE_GGSN 1
|
||||
#define GTP_MODE_SGSN 2
|
||||
#include "gsn.h"
|
||||
|
||||
#define GTP0_PORT 3386
|
||||
#define GTP1C_PORT 2123
|
||||
|
@ -32,12 +28,10 @@
|
|||
#define GTP1_HEADER_SIZE_SHORT 8
|
||||
#define GTP1_HEADER_SIZE_LONG 12
|
||||
|
||||
#define NAMESIZE 1024
|
||||
#define SYSLOG_PRINTSIZE 255
|
||||
#define ERRMSG_SIZE 255
|
||||
|
||||
#define RESTART_FILE "gsn_restart"
|
||||
#define NAMESIZE 1024
|
||||
|
||||
/* GTP version 1 extension header type definitions. */
|
||||
#define GTP_EXT_PDCP_PDU 0xC0 /* PDCP PDU Number */
|
||||
|
||||
|
@ -59,7 +53,7 @@
|
|||
#define GTP_UPDATE_PDP_RSP 19 /* Update PDP Context Response */
|
||||
#define GTP_DELETE_PDP_REQ 20 /* Delete PDP Context Request */
|
||||
#define GTP_DELETE_PDP_RSP 21 /* Delete PDP Context Response */
|
||||
/* 22-25 For future use. *//* In version GTP 1 anonomous PDP context */
|
||||
/* 22-25 For future use. *//* In version GTP 1 anonomous PDP context */
|
||||
#define GTP_ERROR 26 /* Error Indication */
|
||||
#define GTP_PDU_NOT_REQ 27 /* PDU Notification Request */
|
||||
#define GTP_PDU_NOT_RSP 28 /* PDU Notification Response */
|
||||
|
@ -105,19 +99,21 @@ static inline const char *gtp_type_name(uint8_t val)
|
|||
#define GTPCAUSE_NO_ID_NEEDED 3 /* No identity needed */
|
||||
#define GTPCAUSE_MS_REFUSES_X 4 /* MS refuses */
|
||||
#define GTPCAUSE_MS_NOT_RESP_X 5 /* MS is not GPRS responding */
|
||||
#define GTPCAUSE_006 6 /* For future use 6-48 */
|
||||
#define GTPCAUSE_049 49 /* Cause values reserved for GPRS charging protocol use (See GTP' in GSM 12.15) 49-63 */
|
||||
#define GTPCAUSE_064 64 /* For future use 64-127 */
|
||||
/* 6-48 For future use */
|
||||
/* 49-63 Cause values reserved for GPRS charging protocol use (See GTP' in GSM 12.15) */
|
||||
/* 64-127 For future use */
|
||||
#define GTPCAUSE_ACC_REQ 128 /* Request accepted */
|
||||
#define GTPCAUSE_129 129 /* For future use 129-176 */
|
||||
#define GTPCAUSE_177 177 /* Cause values reserved for GPRS charging protocol use (See GTP' In GSM 12.15) 177-191 */
|
||||
#define GTPCAUSE_NEW_PDP_NET_PREF 129 /* New PDP type due to network preference */
|
||||
#define GTPCAUSE_NEW_PDP_ADDR_BEAR 130 /* New PDP type due to single address bearer only */
|
||||
/* 131-176 For future use */
|
||||
/* 177-191 Cause values reserved for GPRS charging protocol use (See GTP' In GSM 12.15) */
|
||||
#define GTPCAUSE_NON_EXIST 192 /* Non-existent */
|
||||
#define GTPCAUSE_INVALID_MESSAGE 193 /* Invalid message format */
|
||||
#define GTPCAUSE_IMSI_NOT_KNOWN 194 /* IMSI not known */
|
||||
#define GTPCAUSE_MS_DETACHED 195 /* MS is GPRS detached */
|
||||
#define GTPCAUSE_MS_NOT_RESP 196 /* MS is not GPRS responding */
|
||||
#define GTPCAUSE_MS_REFUSES 197 /* MS refuses */
|
||||
#define GTPCAUSE_198 198 /* For future use */
|
||||
/* 198 For future use */
|
||||
#define GTPCAUSE_NO_RESOURCES 199 /* No resources available */
|
||||
#define GTPCAUSE_NOT_SUPPORTED 200 /* Service not supported */
|
||||
#define GTPCAUSE_MAN_IE_INCORRECT 201 /* Mandatory IE incorrect */
|
||||
|
@ -140,8 +136,15 @@ static inline const char *gtp_type_name(uint8_t val)
|
|||
#define GTPCAUSE_SYN_ERR_FILTER 218 /* Syntactic errors in packet filter(s) */
|
||||
#define GTPCAUSE_MISSING_APN 219 /* Missing or unknown APN */
|
||||
#define GTPCAUSE_UNKNOWN_PDP 220 /* Unknown PDP address or PDP type */
|
||||
#define GTPCAUSE_221 221 /* For Future Use 221-240 */
|
||||
#define GTPCAUSE_241 241 /* Cause Values Reserved For Gprs Charging Protocol Use (See Gtp' In Gsm 12.15) 241-255 */
|
||||
/* 221-240 For future use */
|
||||
/* 241-255 Cause Values Reserved For Gprs Charging Protocol Use (See Gtp' In Gsm 12.15) */
|
||||
|
||||
static inline bool gtp_cause_successful(uint8_t cause)
|
||||
{
|
||||
return cause == GTPCAUSE_ACC_REQ ||
|
||||
cause == GTPCAUSE_NEW_PDP_NET_PREF ||
|
||||
cause == GTPCAUSE_NEW_PDP_ADDR_BEAR;
|
||||
}
|
||||
|
||||
struct ul66_t;
|
||||
struct ul16_t;
|
||||
|
@ -232,105 +235,13 @@ union gtp_packet {
|
|||
struct gtp1_packet_long gtp1l;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* ***********************************************************
|
||||
* Information storage for each gsn instance
|
||||
*
|
||||
* Normally each instance of the application corresponds to
|
||||
* one instance of a gsn.
|
||||
*
|
||||
* In order to avoid global variables in the application, and
|
||||
* also in order to allow several instances of a gsn in the same
|
||||
* application this struct is provided in order to store all
|
||||
* relevant information related to the gsn.
|
||||
*
|
||||
* Note that this does not include information storage for '
|
||||
* each pdp context. This is stored in another struct.
|
||||
*************************************************************/
|
||||
|
||||
struct gsn_t {
|
||||
/* Parameters related to the network interface */
|
||||
|
||||
int fd0; /* GTP0 file descriptor */
|
||||
int fd1c; /* GTP1 control plane file descriptor */
|
||||
int fd1u; /* GTP0 user plane file descriptor */
|
||||
int mode; /* Mode of operation: GGSN or SGSN */
|
||||
struct in_addr gsnc; /* IP address of this gsn for signalling */
|
||||
struct in_addr gsnu; /* IP address of this gsn for user traffic */
|
||||
|
||||
/* Parameters related to signalling messages */
|
||||
uint16_t seq_next; /* Next sequence number to use */
|
||||
int seq_first; /* First packet in queue (oldest timeout) */
|
||||
int seq_last; /* Last packet in queue (youngest timeout) */
|
||||
|
||||
unsigned char restart_counter; /* Increment on restart. Stored on disk */
|
||||
char *statedir; /* Disk location for permanent storage */
|
||||
void *priv; /* used by libgtp users to attach their own state) */
|
||||
struct queue_t *queue_req; /* Request queue */
|
||||
struct queue_t *queue_resp; /* Response queue */
|
||||
|
||||
struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
|
||||
struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
|
||||
|
||||
struct osmo_timer_list queue_timer; /* internal queue_{req,resp} timer */
|
||||
|
||||
/* Call back functions */
|
||||
int (*cb_delete_context) (struct pdp_t *);
|
||||
int (*cb_create_context_ind) (struct pdp_t *);
|
||||
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);
|
||||
int (*cb_conf) (int type, int cause, struct pdp_t * pdp, void *cbp);
|
||||
int (*cb_data_ind) (struct pdp_t * pdp, void *pack, unsigned len);
|
||||
int (*cb_recovery) (struct sockaddr_in * peer, uint8_t recovery);
|
||||
int (*cb_recovery2) (struct sockaddr_in * peer, struct pdp_t * pdp, uint8_t recovery);
|
||||
int (*cb_recovery3) (struct gsn_t *gsn, struct sockaddr_in *peer, struct pdp_t *pdp, uint8_t recovery);
|
||||
|
||||
/* Counters */
|
||||
|
||||
uint64_t err_socket; /* Number of socket errors */
|
||||
uint64_t err_readfrom; /* Number of readfrom errors */
|
||||
uint64_t err_sendto; /* Number of sendto errors */
|
||||
uint64_t err_memcpy; /* Number of memcpy */
|
||||
uint64_t err_queuefull; /* Number of times queue was full */
|
||||
uint64_t err_seq; /* Number of seq out of range */
|
||||
uint64_t err_address; /* GSN address conversion failed */
|
||||
uint64_t err_unknownpdp; /* GSN address conversion failed */
|
||||
uint64_t err_unknowntid; /* Application supplied unknown imsi+nsapi */
|
||||
uint64_t err_cause; /* Unexpected cause value received */
|
||||
uint64_t err_outofpdp; /* Out of storage for PDP contexts */
|
||||
|
||||
uint64_t empty; /* Number of empty packets */
|
||||
uint64_t unsup; /* Number of unsupported version 29.60 11.1.1 */
|
||||
uint64_t tooshort; /* Number of too short headers 29.60 11.1.2 */
|
||||
uint64_t unknown; /* Number of unknown messages 29.60 11.1.3 */
|
||||
uint64_t unexpect; /* Number of unexpected messages 29.60 11.1.4 */
|
||||
uint64_t duplicate; /* Number of duplicate or unsolicited replies */
|
||||
uint64_t missing; /* Number of missing information field messages */
|
||||
uint64_t incorrect; /* Number of incorrect information field messages */
|
||||
uint64_t invalid; /* Number of invalid message format messages */
|
||||
};
|
||||
|
||||
/* External API functions */
|
||||
|
||||
extern const char *gtp_version();
|
||||
extern int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
|
||||
int mode);
|
||||
|
||||
extern int gtp_free(struct gsn_t *gsn);
|
||||
|
||||
extern int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
|
||||
uint64_t imsi, uint8_t nsapi) OSMO_DEPRECATED("Use gtp_pdp_newpdp() instead");
|
||||
extern int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp);
|
||||
extern int gtp_freepdp_teardown(struct gsn_t *gsn, struct pdp_t *pdp);
|
||||
|
||||
extern int gtp_create_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
|
||||
void *cbp);
|
||||
|
||||
extern int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
|
||||
int (*cb_create_context_ind) (struct
|
||||
pdp_t *
|
||||
pdp));
|
||||
|
||||
extern int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
|
||||
int cause);
|
||||
|
||||
|
@ -351,107 +262,15 @@ extern int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *p
|
|||
const uint8_t *rim_route_addr, size_t rim_route_addr_len,
|
||||
uint8_t rim_route_addr_discr);
|
||||
|
||||
extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
|
||||
int (*cb_data_ind) (struct pdp_t * pdp,
|
||||
void *pack, unsigned len));
|
||||
|
||||
extern int gtp_fd(struct gsn_t *gsn);
|
||||
extern int gtp_decaps0(struct gsn_t *gsn);
|
||||
extern int gtp_decaps1c(struct gsn_t *gsn);
|
||||
extern int gtp_decaps1u(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");
|
||||
|
||||
extern int gtp_set_cb_delete_context(struct gsn_t *gsn,
|
||||
int (*cb_delete_context) (struct pdp_t *
|
||||
pdp));
|
||||
/*extern int gtp_set_cb_create_context(struct gsn_t *gsn,
|
||||
int (*cb_create_context) (struct pdp_t* pdp)); */
|
||||
|
||||
extern int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer));
|
||||
|
||||
extern int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer));
|
||||
|
||||
extern int gtp_set_cb_ran_info_relay_ind(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer, union gtpie_member **ie));
|
||||
|
||||
extern int gtp_set_cb_conf(struct gsn_t *gsn,
|
||||
int (*cb) (int type, int cause, struct pdp_t * pdp,
|
||||
void *cbp));
|
||||
|
||||
int gtp_set_cb_recovery(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer,
|
||||
uint8_t recovery))
|
||||
OSMO_DEPRECATED("Use gtp_set_cb_recovery2() instead, to obtain pdp ctx originating the recovery");
|
||||
int gtp_set_cb_recovery2(struct gsn_t *gsn,
|
||||
int (*cb) (struct sockaddr_in * peer,
|
||||
struct pdp_t * pdp,
|
||||
uint8_t recovery))
|
||||
OSMO_DEPRECATED("Use gtp_set_cb_recovery3() instead, to obtain gsn handling the recovery");;
|
||||
int gtp_set_cb_recovery3(struct gsn_t *gsn,
|
||||
int (*cb) (struct gsn_t * gsn, struct sockaddr_in * peer,
|
||||
struct pdp_t * pdp,
|
||||
uint8_t recovery));
|
||||
|
||||
void gtp_clear_queues(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 */
|
|
@ -1,10 +1,42 @@
|
|||
noinst_LIBRARIES = libmisc.a
|
||||
|
||||
noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h in46_addr.h netdev.h gtp-kernel.h netns.h util.h icmpv6.h checksum.h
|
||||
noinst_HEADERS = \
|
||||
checksum.h \
|
||||
gnugetopt.h \
|
||||
gtp-kernel.h \
|
||||
icmpv6.h \
|
||||
in46_addr.h \
|
||||
ippool.h \
|
||||
lookup.h \
|
||||
netdev.h \
|
||||
netns.h \
|
||||
syserr.h \
|
||||
tun.h \
|
||||
util.h \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = -O2 -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
|
||||
AM_CFLAGS = \
|
||||
-fno-builtin \
|
||||
-Wall \
|
||||
-DSBINDIR='"$(sbindir)"' \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
libmisc_a_SOURCES = getopt1.c getopt.c ippool.c lookup.c tun.c debug.c in46_addr.c netdev.c netns.c util.c icmpv6.c checksum.c
|
||||
libmisc_a_SOURCES = \
|
||||
checksum.c \
|
||||
debug.c \
|
||||
getopt.c \
|
||||
getopt1.c \
|
||||
icmpv6.c \
|
||||
in46_addr.c \
|
||||
ippool.c \
|
||||
lookup.c \
|
||||
netdev.c \
|
||||
netns.c \
|
||||
tun.c \
|
||||
util.c \
|
||||
$(NULL)
|
||||
|
||||
if ENABLE_GTP_KERNEL
|
||||
AM_CFLAGS += -DGTP_KERNEL $(LIBGTPNL_CFLAGS)
|
||||
|
|
109
lib/gtp-kernel.c
109
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"
|
||||
|
||||
|
@ -104,61 +105,97 @@ void gtp_kernel_stop(const char *devname)
|
|||
|
||||
int gtp_kernel_tunnel_add(struct pdp_t *pdp, const char *devname)
|
||||
{
|
||||
struct in_addr ms, sgsn;
|
||||
int ms_addr_count;
|
||||
struct in46_addr ms[2];
|
||||
struct in46_addr sgsn;
|
||||
struct gtp_tunnel *t;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
pdp_debug(__func__, devname, pdp);
|
||||
|
||||
t = gtp_tunnel_alloc();
|
||||
if (t == NULL)
|
||||
in46a_from_gsna(&pdp->gsnrc, &sgsn);
|
||||
|
||||
ms_addr_count = in46a_from_eua(&pdp->eua, ms);
|
||||
if (ms_addr_count < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(&ms, &pdp->eua.v[2], sizeof(struct in_addr));
|
||||
memcpy(&sgsn, &pdp->gsnrc.v[0], sizeof(struct in_addr));
|
||||
for (int i = 0; i < ms_addr_count; i++) {
|
||||
t = gtp_tunnel_alloc();
|
||||
if (t == NULL)
|
||||
return -1;
|
||||
|
||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||
gtp_tunnel_set_version(t, pdp->version);
|
||||
gtp_tunnel_set_ms_ip4(t, &ms);
|
||||
gtp_tunnel_set_sgsn_ip4(t, &sgsn);
|
||||
if (pdp->version == 0) {
|
||||
gtp_tunnel_set_tid(t, pdp_gettid(pdp->imsi, pdp->nsapi));
|
||||
gtp_tunnel_set_flowid(t, pdp->flru);
|
||||
} else {
|
||||
gtp_tunnel_set_i_tei(t, pdp->teid_own);
|
||||
/* use the TEI advertised by SGSN when sending packets
|
||||
* towards the SGSN */
|
||||
gtp_tunnel_set_o_tei(t, pdp->teid_gn);
|
||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||
gtp_tunnel_set_version(t, pdp->version);
|
||||
|
||||
if (in46a_to_af(&ms[i]) == AF_INET)
|
||||
gtp_tunnel_set_ms_ip4(t, &ms[i].v4);
|
||||
else {
|
||||
/* In IPv6, EUA doesn't contain the actual IP
|
||||
* addr/prefix. Set higher bits to 0 to get the 64 bit
|
||||
* netmask. */
|
||||
memset(((void *)&ms[i].v6) + 8, 0, 8);
|
||||
gtp_tunnel_set_ms_ip6(t, &ms[i].v6);
|
||||
}
|
||||
|
||||
if (in46a_to_af(&sgsn) == AF_INET)
|
||||
gtp_tunnel_set_sgsn_ip4(t, &sgsn.v4);
|
||||
else
|
||||
gtp_tunnel_set_sgsn_ip6(t, &sgsn.v6);
|
||||
|
||||
if (pdp->version == 0) {
|
||||
gtp_tunnel_set_tid(t, pdp_gettid(pdp->imsi, pdp->nsapi));
|
||||
gtp_tunnel_set_flowid(t, pdp->flru);
|
||||
} else {
|
||||
gtp_tunnel_set_i_tei(t, pdp->teid_own);
|
||||
/* use the TEI advertised by SGSN when sending packets
|
||||
* towards the SGSN */
|
||||
gtp_tunnel_set_o_tei(t, pdp->teid_gn);
|
||||
}
|
||||
|
||||
ret = gtp_add_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
|
||||
gtp_tunnel_free(t);
|
||||
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
ret = gtp_add_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
|
||||
gtp_tunnel_free(t);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int gtp_kernel_tunnel_del(struct pdp_t *pdp, const char *devname)
|
||||
{
|
||||
int ms_addr_count;
|
||||
struct in46_addr ms[2];
|
||||
struct gtp_tunnel *t;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
pdp_debug(__func__, devname, pdp);
|
||||
|
||||
t = gtp_tunnel_alloc();
|
||||
if (t == NULL)
|
||||
ms_addr_count = in46a_from_eua(&pdp->eua, ms);
|
||||
if (ms_addr_count < 0)
|
||||
return -1;
|
||||
|
||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||
gtp_tunnel_set_version(t, pdp->version);
|
||||
if (pdp->version == 0) {
|
||||
gtp_tunnel_set_tid(t, pdp_gettid(pdp->imsi, pdp->nsapi));
|
||||
gtp_tunnel_set_flowid(t, pdp->flru);
|
||||
} else {
|
||||
gtp_tunnel_set_i_tei(t, pdp->teid_own);
|
||||
}
|
||||
for (int i = 0; i < ms_addr_count; i++) {
|
||||
t = gtp_tunnel_alloc();
|
||||
if (t == NULL)
|
||||
return -1;
|
||||
|
||||
ret = gtp_del_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
|
||||
gtp_tunnel_free(t);
|
||||
gtp_tunnel_set_ifidx(t, if_nametoindex(devname));
|
||||
gtp_tunnel_set_family(t, in46a_to_af(&ms[i]));
|
||||
gtp_tunnel_set_version(t, pdp->version);
|
||||
if (pdp->version == 0) {
|
||||
gtp_tunnel_set_tid(t, pdp_gettid(pdp->imsi, pdp->nsapi));
|
||||
gtp_tunnel_set_flowid(t, pdp->flru);
|
||||
} else {
|
||||
gtp_tunnel_set_i_tei(t, pdp->teid_own);
|
||||
}
|
||||
|
||||
ret = gtp_del_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
|
||||
gtp_tunnel_free(t);
|
||||
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
18
lib/icmpv6.h
18
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
|
||||
|
||||
|
@ -44,10 +44,9 @@ struct icmpv6_radv_hdr {
|
|||
uint8_t res:6,
|
||||
m:1,
|
||||
o:1;
|
||||
#else
|
||||
uint8_t m:1,
|
||||
o:1,
|
||||
res:6;
|
||||
#elif OSMO_IS_BIG_ENDIAN
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
|
||||
uint8_t o:1, m:1, res:6;
|
||||
#endif
|
||||
uint16_t router_lifetime;
|
||||
uint32_t reachable_time;
|
||||
|
@ -72,10 +71,9 @@ struct icmpv6_opt_prefix {
|
|||
uint8_t res:6,
|
||||
a:1,
|
||||
l:1;
|
||||
#else
|
||||
uint8_t l:1,
|
||||
a:1,
|
||||
res:6;
|
||||
#elif OSMO_IS_BIG_ENDIAN
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
|
||||
uint8_t l:1, a:1, res:6;
|
||||
#endif
|
||||
uint32_t valid_lifetime;
|
||||
uint32_t preferred_lifetime;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
#include "../lib/in46_addr.h"
|
||||
#include "../gtp/pdp.h"
|
||||
#include <osmocom/gtp/pdp.h>
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
|
@ -375,3 +375,10 @@ default_to_dyn_v4:
|
|||
dst->v4.s_addr = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void in46a_from_gsna(const struct ul16_t *in, struct in46_addr *dst)
|
||||
{
|
||||
dst->len = in->l;
|
||||
OSMO_ASSERT(in->l <= sizeof(dst->v6));
|
||||
memcpy(&dst->v6, in->v, in->l);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
@ -39,3 +39,5 @@ static inline bool in46a_is_v6(const struct in46_addr *addr) {
|
|||
static inline bool in46a_is_v4(const struct in46_addr *addr) {
|
||||
return addr->len == sizeof(struct in_addr);
|
||||
}
|
||||
|
||||
void in46a_from_gsna(const struct ul16_t *in, struct in46_addr *dst);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "../gtp/pdp.h"
|
||||
#include <osmocom/gtp/pdp.h>
|
||||
|
||||
#include "ippool.h"
|
||||
#include "in46_addr.h"
|
||||
|
|
|
@ -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}/
|
||||
|
|
|
@ -2,12 +2,22 @@ bin_PROGRAMS = sgsnemu
|
|||
|
||||
AM_LDFLAGS = @EXEC_LDFLAGS@
|
||||
|
||||
AM_CFLAGS = -O2 -D_GNU_SOURCE -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
|
||||
AM_CFLAGS = \
|
||||
-D_GNU_SOURCE \
|
||||
-fno-builtin \
|
||||
-Wall \
|
||||
-DSBINDIR='"$(sbindir)"' \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
sgsnemu_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS)
|
||||
|
||||
if ENABLE_GTP_KERNEL
|
||||
AM_CFLAGS += -DGTP_KERNEL $(LIBGTPNL_CFLAGS)
|
||||
AM_CFLAGS += \
|
||||
-DGTP_KERNEL \
|
||||
$(LIBGTPNL_CFLAGS) \
|
||||
$(NULL)
|
||||
sgsnemu_LDADD += $(LIBGTPNL_LIBS)
|
||||
endif
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
AM_CFLAGS = -Wall -I$(top_srcdir)/include $(LIBOSMOCORE_CFLAGS) -g
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(NULL)
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = \
|
||||
gtpie_test.ok \
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
AM_CFLAGS = -Wall -I$(top_srcdir)/include $(LIBOSMOCORE_CFLAGS) -g
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(NULL)
|
||||
AM_LDFLAGS = -no-install
|
||||
|
||||
EXTRA_DIST = ippool_test.ok \
|
||||
ippool_test.err \
|
||||
|
|
Loading…
Reference in New Issue