mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn.git
synced 2025-11-03 05:33:23 +00:00
Compare commits
30 Commits
keith/icmp
...
whyteks/ic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33680054c3 | ||
|
|
f32c6a9095 | ||
|
|
2eed6ec5ec | ||
|
|
641206ad5e | ||
|
|
bfd3119ae4 | ||
|
|
4b9b19e998 | ||
|
|
00e0559e17 | ||
|
|
0b1d9dbc40 | ||
|
|
5379273ea3 | ||
|
|
ecef920b8f | ||
|
|
eb9267b15e | ||
|
|
1efb2bcd90 | ||
|
|
878593f205 | ||
|
|
1596463985 | ||
|
|
9d82492e49 | ||
|
|
303aeea8a8 | ||
|
|
18898b4a9f | ||
|
|
17cee2056c | ||
|
|
67a3c833af | ||
|
|
b1f641b5b7 | ||
|
|
f01ce65f5b | ||
|
|
be1cf99e9a | ||
|
|
7710080ffd | ||
|
|
798a81d48d | ||
|
|
51930f7b63 | ||
|
|
00ef1b0d6e | ||
|
|
02a82c3c9b | ||
|
|
349cbfcf50 | ||
|
|
51f99ae250 | ||
|
|
12304c0e5a |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -27,7 +27,7 @@ osmo-ggsn-*.tar*
|
||||
# debian
|
||||
debian/osmo-ggsn/
|
||||
debian/*.debhelper
|
||||
debian/libgtp1
|
||||
debian/libgtp*/
|
||||
debian/osmo-ggsn-dbg
|
||||
debian/*.log
|
||||
debian/autoreconf.*
|
||||
@@ -79,5 +79,6 @@ doc/manuals/generated/
|
||||
doc/manuals/osmomsc-usermanual.xml
|
||||
doc/manuals/common
|
||||
doc/manuals/build
|
||||
doc/manuals/vty/ggsn_vty_reference.xml
|
||||
|
||||
contrib/osmo-ggsn.spec
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
# 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
|
||||
osmo-ggsn update osmo-gsm-manuals dependency to > 0.3.0 for vty_cpu_sched.adoc include
|
||||
libgtp ADD gtp_ran_info_relay_req, gtp_set_cb_ran_info_relay_ind
|
||||
|
||||
@@ -9,6 +9,8 @@ AC_CONFIG_AUX_DIR([.])
|
||||
AC_CONFIG_TESTDIR(tests)
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
CFLAGS="$CFLAGS -std=gnu11"
|
||||
|
||||
dnl kernel style compile messages
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
@@ -152,9 +154,9 @@ adl_FUNC_GETOPT_LONG
|
||||
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.5.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.5.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.5.0)
|
||||
|
||||
AC_ARG_ENABLE(sanitize,
|
||||
[AS_HELP_STRING(
|
||||
|
||||
@@ -38,7 +38,6 @@ export PATH="$inst/bin:$PATH"
|
||||
# Additional configure options and depends
|
||||
CONFIG=""
|
||||
if [ "$WITH_MANUALS" = "1" ]; then
|
||||
osmo-build-dep.sh osmo-gsm-manuals
|
||||
CONFIG="--enable-manuals"
|
||||
fi
|
||||
|
||||
|
||||
@@ -29,11 +29,10 @@ BuildRequires: pkgconfig >= 0.20
|
||||
%if 0%{?suse_version}
|
||||
BuildRequires: systemd-rpm-macros
|
||||
%endif
|
||||
BuildRequires: pkgconfig(libgtpnl) >= 1.0.0
|
||||
BuildRequires: pkgconfig(libmnl) >= 1.0.3
|
||||
BuildRequires: pkgconfig(libosmocore) >= 1.1.0
|
||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.1.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.1.0
|
||||
BuildRequires: pkgconfig(libgtpnl) >= 1.2.0
|
||||
BuildRequires: pkgconfig(libosmocore) >= 1.5.0
|
||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.5.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.5.0
|
||||
Obsoletes: openggsn
|
||||
%{?systemd_requires}
|
||||
|
||||
@@ -69,6 +68,7 @@ applications that want to make use of libgtp.
|
||||
echo "%{version}" >.tarball-version
|
||||
autoreconf -fi
|
||||
%configure \
|
||||
--enable-gtp-linux \
|
||||
--disable-static \
|
||||
--docdir="%{_docdir}/%{name}" \
|
||||
--with-systemdsystemunitdir=%{_unitdir} \
|
||||
@@ -108,7 +108,9 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
|
||||
%{_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
|
||||
|
||||
|
||||
44
debian/changelog
vendored
44
debian/changelog
vendored
@@ -1,3 +1,47 @@
|
||||
osmo-ggsn (1.7.1) unstable; urgency=medium
|
||||
|
||||
[ Harald Welte ]
|
||||
* main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
|
||||
* manuals: generate vty reference xml at build time
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 23 Feb 2021 17:31:24 +0100
|
||||
|
||||
osmo-ggsn (1.7.0) unstable; urgency=medium
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* debian/control: change maintainer to the Osmocom team / mailing list
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* configure.ac: Fix trailing whitespace
|
||||
* doc: Update VTY reference xml file
|
||||
* Support setting rt-prio and cpu-affinity mask through VTY
|
||||
* contrib/jenkins: Enable parallel make in make distcheck
|
||||
* ggsn: generate coredump and exit upon SIGABRT received
|
||||
* tests: Explicitly drop category from log
|
||||
* tests: Replace deprecated API log_set_print_filename
|
||||
|
||||
[ Keith ]
|
||||
* Fix vty PDP lookups by IMSI
|
||||
* Prevent Crash in show pdp-context from vty
|
||||
* Minor: remove code duplication
|
||||
* Use imsi_str2gtp() in sgsnemu
|
||||
* sgsnemu: relax check on length of IMSI cmdline arg.
|
||||
* GTP: Replace recently introduced imsi_str2gtp()
|
||||
|
||||
[ Harald Welte ]
|
||||
* Use OSMO_FD_* instead of deprecated BSC_FD_*
|
||||
* gtp-kernel: Remove duplicate #include section
|
||||
* gtp-kernel: don't #include libmnl headers
|
||||
|
||||
[ Oliver Smith ]
|
||||
* contrib/jenkins: don't build osmo-gsm-manuals
|
||||
* configure.ac: set -std=gnu11
|
||||
* apn_start: avoid segfault if missing tun-device
|
||||
* .gitignore: ignore debian/libgtp*
|
||||
* deb/rpm: build with --enable-gtp-linux
|
||||
|
||||
-- Pau Espin Pedrol <pespin@espeweb.net> Tue, 23 Feb 2021 13:34:39 +0100
|
||||
|
||||
osmo-ggsn (1.6.0) unstable; urgency=medium
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
|
||||
5
debian/control
vendored
5
debian/control
vendored
@@ -7,8 +7,9 @@ Build-Depends: debhelper (>= 9),
|
||||
pkg-config,
|
||||
libdpkg-perl, git,
|
||||
dh-autoreconf,
|
||||
libosmocore-dev (>= 1.4.0),
|
||||
osmo-gsm-manuals-dev
|
||||
libosmocore-dev (>= 1.5.0),
|
||||
osmo-gsm-manuals-dev,
|
||||
libgtpnl-dev (>= 1.2.0)
|
||||
Standards-Version: 3.9.6
|
||||
Vcs-Browser: http://git.osmocom.org/osmo-ggsn/
|
||||
Vcs-Git: git://git.osmocom.org/osmo-ggsn
|
||||
|
||||
1
debian/osmo-ggsn.examples
vendored
1
debian/osmo-ggsn.examples
vendored
@@ -1,2 +1,3 @@
|
||||
doc/examples/osmo-ggsn.cfg
|
||||
doc/examples/osmo-ggsn-kernel-gtp.cfg
|
||||
doc/examples/sgsnemu.conf
|
||||
|
||||
5
debian/rules
vendored
5
debian/rules
vendored
@@ -19,7 +19,10 @@ override_dh_strip:
|
||||
dh_strip -plibgtp6 --dbg-package=libgtp-dbg
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- --with-systemdsystemunitdir=/lib/systemd/system --enable-manuals
|
||||
dh_auto_configure -- \
|
||||
--enable-gtp-linux \
|
||||
--with-systemdsystemunitdir=/lib/systemd/system \
|
||||
--enable-manuals
|
||||
|
||||
# Don't create .pdf.gz files (barely saves space and they can't be opened directly by most pdf readers)
|
||||
override_dh_compress:
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
OSMOCONF_FILES = \
|
||||
osmo-ggsn.cfg \
|
||||
$(NULL)
|
||||
|
||||
osmoconfdir = $(sysconfdir)/osmocom
|
||||
osmoconf_DATA = osmo-ggsn.cfg
|
||||
osmoconf_DATA = $(OSMOCONF_FILES)
|
||||
|
||||
EXTRA_DIST = osmo-ggsn.cfg
|
||||
EXTRA_DIST = $(OSMOCONF_FILES)
|
||||
|
||||
CFG_FILES = find $(srcdir) -name '*.cfg*' | sed -e 's,^$(srcdir),,'
|
||||
CFG_FILES = find $(srcdir) -name '*.cfg' -o -name '*.conf' | sed -e 's,^$(srcdir),,'
|
||||
|
||||
dist-hook:
|
||||
for f in $$($(CFG_FILES)); do \
|
||||
|
||||
51
doc/examples/osmo-ggsn-kernel-gtp.cfg
Normal file
51
doc/examples/osmo-ggsn-kernel-gtp.cfg
Normal file
@@ -0,0 +1,51 @@
|
||||
!
|
||||
! OpenGGSN (0.94.1-adac) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging filter all 1
|
||||
logging color 1
|
||||
logging print category 0
|
||||
logging timestamp 0
|
||||
logging level ip info
|
||||
logging level tun info
|
||||
logging level ggsn info
|
||||
logging level sgsn notice
|
||||
logging level icmp6 notice
|
||||
logging level lglobal notice
|
||||
logging level llapd notice
|
||||
logging level linp notice
|
||||
logging level lmux notice
|
||||
logging level lmi notice
|
||||
logging level lmib notice
|
||||
logging level lsms notice
|
||||
logging level lctrl notice
|
||||
logging level lgtp info
|
||||
logging level lstats notice
|
||||
logging level lgsup notice
|
||||
logging level loap notice
|
||||
logging level lss7 notice
|
||||
logging level lsccp notice
|
||||
logging level lsua notice
|
||||
logging level lm3ua notice
|
||||
logging level lmgcp notice
|
||||
!
|
||||
stats interval 5
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
ggsn ggsn0
|
||||
gtp state-dir /tmp
|
||||
gtp bind-ip 127.0.0.2
|
||||
apn internet
|
||||
gtpu-mode kernel-gtp
|
||||
tun-device tun4
|
||||
type-support v4
|
||||
ip prefix dynamic 172.16.222.0/24
|
||||
ip dns 0 8.8.8.8
|
||||
ip dns 1 8.8.4.4
|
||||
ip ifconfig 172.16.222.0/24
|
||||
no shutdown
|
||||
default-apn internet
|
||||
no shutdown ggsn
|
||||
@@ -11,6 +11,12 @@ if BUILD_MANUALS
|
||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
|
||||
|
||||
VTY_REFERENCE = osmoggsn-vty-reference.xml
|
||||
|
||||
BUILT_REFERENCE_XML = $(builddir)/vty/ggsn_vty_reference.xml
|
||||
$(builddir)/vty/ggsn_vty_reference.xml: $(top_builddir)/ggsn/osmo-ggsn
|
||||
mkdir -p $(builddir)/vty
|
||||
$(top_builddir)/ggsn/osmo-ggsn --vty-ref-xml > $@
|
||||
|
||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
|
||||
|
||||
OSMO_REPOSITORY=osmo-ggsn
|
||||
|
||||
@@ -80,3 +80,47 @@ possible to pick differing ports on the same IP address), like:
|
||||
ggsn ggsn0
|
||||
gtp bind-ip 127.0.0.2
|
||||
----
|
||||
|
||||
=== GTP-U kernel module
|
||||
|
||||
WARNING: As of writing, the kernel module does not support IPv6.
|
||||
|
||||
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
|
||||
userspace in OsmoGGSN. The kernel module is included in Linux 4.7.0 and higher.
|
||||
Notably the Debian GNU/Linux distribution has it enabled by default.
|
||||
|
||||
In order to use this feature, make sure that your Linux kernel was configured
|
||||
to support it (`CONFIG_GTP=m` or `=y`). Furthermore, `osmo-ggsn` must have been
|
||||
built with `./configure` argument `--enable-gtp-linux` (which requires libgtpnl
|
||||
to be installed).
|
||||
|
||||
Load the kernel module with:
|
||||
|
||||
----
|
||||
$ sudo modprobe gtp
|
||||
----
|
||||
|
||||
Then start OsmoGGSN with a configuration file that uses `gtpu-mode kernel-gtp`.
|
||||
|
||||
A full example configuration is in `osmo-ggsn-kernel-gtp.cfg`.
|
||||
|
||||
----
|
||||
$ sudo osmo-ggsn -c /usr/share/doc/osmo-ggsn/examples/osmo-ggsn-kernel-gtp.cfg
|
||||
----
|
||||
|
||||
.Example: APN with kernel-gtp
|
||||
----
|
||||
ggsn ggsn0
|
||||
gtp state-dir /tmp
|
||||
gtp bind-ip 127.0.0.2
|
||||
apn internet
|
||||
gtpu-mode kernel-gtp
|
||||
tun-device tun4
|
||||
type-support v4
|
||||
ip prefix dynamic 172.16.222.0/24
|
||||
ip dns 0 8.8.8.8
|
||||
ip dns 1 8.8.4.4
|
||||
ip ifconfig 172.16.222.0/24
|
||||
no shutdown
|
||||
----
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
123
ggsn/ggsn.c
123
ggsn/ggsn.c
@@ -40,6 +40,7 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/ip6.h>
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
@@ -467,9 +468,13 @@ int create_context_ind(struct pdp_t *pdp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: we manually force all context requests to dynamic here! */
|
||||
if (pdp->eua.l > 2)
|
||||
pdp->eua.l = 2;
|
||||
/* FIXME: implement context request for static IP addresses! */
|
||||
if (pdp->eua.l > 2) {
|
||||
LOGPPDP(LOGL_ERROR, pdp, "Static IP addresses not supported: %s\n",
|
||||
osmo_hexdump(pdp->eua.v, pdp->eua.l));
|
||||
gtp_create_context_resp(gsn, pdp, GTPCAUSE_NOT_SUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(pdp->qos_neg0, pdp->qos_req0, sizeof(pdp->qos_req0));
|
||||
|
||||
@@ -580,6 +585,72 @@ err_wrong_af:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t inet_checksum(void *data, int len) {
|
||||
int nleft = len;
|
||||
int sum = 0;
|
||||
unsigned short *w = data;
|
||||
unsigned short answer = 0;
|
||||
|
||||
while (nleft > 1)
|
||||
{
|
||||
sum += *w++;
|
||||
nleft -= 2;
|
||||
}
|
||||
|
||||
if (nleft == 1)
|
||||
{
|
||||
*(unsigned char *)(&answer) = *(unsigned char *)w;
|
||||
sum += answer;
|
||||
}
|
||||
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
answer = ~sum;
|
||||
|
||||
return (answer);
|
||||
}
|
||||
|
||||
|
||||
/* Generate and send an ICMP HOST UNREACHABLE Packet */
|
||||
static void ipv4_host_unreach(struct tun_t *tun, void *pack, unsigned len) {
|
||||
|
||||
char send_buf[sizeof(struct ip) + sizeof(struct icmp) + len];
|
||||
/* What are these 20 bytes on the end of pack? */
|
||||
len = len - 20;
|
||||
struct iphdr *iph = (struct iphdr *)pack;
|
||||
|
||||
memset(send_buf, 0, sizeof(send_buf));
|
||||
|
||||
struct ip *ip = (struct ip *)send_buf;
|
||||
struct icmp *icmp = (struct icmp *)(ip + 1);
|
||||
|
||||
ip->ip_v = 4;
|
||||
ip->ip_hl = 5;
|
||||
ip->ip_tos = 0;
|
||||
ip->ip_len = htons(sizeof(send_buf));
|
||||
ip->ip_id = rand();
|
||||
ip->ip_off = 0;
|
||||
ip->ip_ttl = 64;
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_p = IPPROTO_ICMP;
|
||||
ip->ip_src.s_addr = iph->daddr;
|
||||
//inet_pton(AF_INET, "10.20.0.4", &(ip->ip_src));
|
||||
ip->ip_dst.s_addr = iph->saddr;
|
||||
|
||||
ip->ip_sum = inet_checksum(ip, sizeof(send_buf));
|
||||
|
||||
icmp->icmp_type = ICMP_DEST_UNREACH;
|
||||
icmp->icmp_code = ICMP_HOST_UNREACH;
|
||||
icmp->icmp_id = 0;
|
||||
icmp->icmp_seq = 0;
|
||||
icmp->icmp_cksum = 0;
|
||||
|
||||
memcpy(send_buf + sizeof(ip) + sizeof(icmp) + 12, pack, len);
|
||||
icmp->icmp_cksum = inet_checksum(icmp, sizeof(icmp) + 12 + len);
|
||||
tun_encaps(tun, send_buf, sizeof(send_buf));
|
||||
|
||||
}
|
||||
|
||||
/* Internet-originated IP packet, needs to be sent via GTP towards MS */
|
||||
static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
|
||||
{
|
||||
@@ -589,7 +660,7 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
|
||||
struct iphdr *iph = (struct iphdr *)pack;
|
||||
struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
|
||||
struct ippool_t *pool;
|
||||
char straddr[INET6_ADDRSTRLEN];
|
||||
char straddr[2][INET6_ADDRSTRLEN];
|
||||
uint8_t pref_offset;
|
||||
|
||||
switch (iph->version) {
|
||||
@@ -622,17 +693,45 @@ static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
|
||||
return 0;
|
||||
|
||||
if (ippool_getip(pool, &ipm, &dst)) {
|
||||
LOGTUN(LOGL_DEBUG, tun, "Received packet for APN(%s) with no PDP contex! (%s)\n",
|
||||
apn->cfg.name,
|
||||
iph->version == 4 ?
|
||||
inet_ntop(AF_INET, &iph->saddr, straddr, sizeof(straddr)) :
|
||||
inet_ntop(AF_INET6, &ip6h->ip6_src, straddr, sizeof(straddr)));
|
||||
LOGTUN(LOGL_DEBUG, tun, "APN(%s) Rx DL data packet for IP address outside "
|
||||
"pool of managed addresses: %s <- %s\n",
|
||||
apn->cfg.name,
|
||||
iph->version == 4 ?
|
||||
inet_ntop(AF_INET, &iph->daddr, straddr[0], sizeof(straddr[0])) :
|
||||
inet_ntop(AF_INET6, &ip6h->ip6_dst, straddr[0], sizeof(straddr[0])),
|
||||
iph->version == 4 ?
|
||||
inet_ntop(AF_INET, &iph->saddr, straddr[1], sizeof(straddr[1])) :
|
||||
inet_ntop(AF_INET6, &ip6h->ip6_src, straddr[1], sizeof(straddr[1])));
|
||||
return 0;
|
||||
}
|
||||
LOGTUN(LOGL_DEBUG, tun, "Received packet for APN(%s)\n", apn->cfg.name);
|
||||
|
||||
if (ipm->peer) /* Check if a peer protocol is defined */
|
||||
gtp_data_req(apn->ggsn->gsn, (struct pdp_t *)ipm->peer, pack, len);
|
||||
if (ipm->peer) { /* Check if a peer protocol is defined */
|
||||
struct pdp_t *pdp = (struct pdp_t *)ipm->peer;
|
||||
LOGTUN(LOGL_DEBUG, tun, "APN(%s) Rx DL data packet for PDP(%s:%u): %s <- %s\n",
|
||||
apn->cfg.name,
|
||||
imsi_gtp2str(&(pdp)->imsi), (pdp)->nsapi,
|
||||
iph->version == 4 ?
|
||||
inet_ntop(AF_INET, &iph->daddr, straddr[0], sizeof(straddr[0])) :
|
||||
inet_ntop(AF_INET6, &ip6h->ip6_dst, straddr[0], sizeof(straddr[0])),
|
||||
iph->version == 4 ?
|
||||
inet_ntop(AF_INET, &iph->saddr, straddr[1], sizeof(straddr[1])) :
|
||||
inet_ntop(AF_INET6, &ip6h->ip6_src, straddr[1], sizeof(straddr[1])));
|
||||
gtp_data_req(apn->ggsn->gsn, pdp, pack, len);
|
||||
} else {
|
||||
LOGTUN(LOGL_DEBUG, tun, "APN(%s) Rx DL data packet for IP address with no "
|
||||
"associated PDP Ctx: %s <- %s\n",
|
||||
apn->cfg.name,
|
||||
iph->version == 4 ?
|
||||
inet_ntop(AF_INET, &iph->daddr, straddr[0], sizeof(straddr[0])) :
|
||||
inet_ntop(AF_INET6, &ip6h->ip6_dst, straddr[0], sizeof(straddr[0])),
|
||||
iph->version == 4 ?
|
||||
inet_ntop(AF_INET, &iph->saddr, straddr[1], sizeof(straddr[1])) :
|
||||
inet_ntop(AF_INET6, &ip6h->ip6_src, straddr[1], sizeof(straddr[1])));
|
||||
if (iph->version != 4)
|
||||
return 0;
|
||||
LOGTUN(LOGL_DEBUG, tun, "No PDP Context for Destination Address, send host unreach.\n");
|
||||
ipv4_host_unreach(tun, pack, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,17 @@ static void signal_handler(int s)
|
||||
end = 1;
|
||||
break;
|
||||
case SIGABRT:
|
||||
/* in case of abort, we want to obtain a talloc report and
|
||||
* then run default SIGABRT handler, who will generate coredump
|
||||
* and abort the process. abort() should do this for us after we
|
||||
* return, but program wouldn't exit if an external SIGABRT is
|
||||
* received.
|
||||
*/
|
||||
talloc_report(tall_vty_ctx, stderr);
|
||||
talloc_report_full(tall_ggsn_ctx, stderr);
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
raise(SIGABRT);
|
||||
break;
|
||||
case SIGUSR1:
|
||||
talloc_report(tall_vty_ctx, stderr);
|
||||
talloc_report_full(tall_ggsn_ctx, stderr);
|
||||
@@ -96,17 +107,49 @@ static void print_help()
|
||||
" -c --config-file filename The config file to use\n"
|
||||
" -V --version Print the version of OsmoGGSN\n"
|
||||
);
|
||||
|
||||
printf("\nVTY reference generation:\n");
|
||||
printf(" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n");
|
||||
printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n");
|
||||
}
|
||||
|
||||
static void handle_long_options(const char *prog_name, const int long_option)
|
||||
{
|
||||
static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
|
||||
|
||||
switch (long_option) {
|
||||
case 1:
|
||||
vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
|
||||
if (vty_ref_mode < 0) {
|
||||
fprintf(stderr, "%s: Unknown VTY reference generation "
|
||||
"mode '%s'\n", prog_name, optarg);
|
||||
exit(2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n",
|
||||
get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
|
||||
get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
|
||||
vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode);
|
||||
exit(0);
|
||||
default:
|
||||
fprintf(stderr, "%s: error parsing cmdline options\n", prog_name);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_options(int argc, char **argv)
|
||||
{
|
||||
while (1) {
|
||||
int option_index = 0, c;
|
||||
static int long_option = 0;
|
||||
static struct option long_options[] = {
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "daemonize", 0, 0, 'D' },
|
||||
{ "config-file", 1, 0, 'c' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ "vty-ref-mode", 1, &long_option, 1 },
|
||||
{ "vty-ref-xml", 0, &long_option, 2 },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -115,6 +158,9 @@ static void handle_options(int argc, char **argv)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 0:
|
||||
handle_long_options(argv[0], long_option);
|
||||
break;
|
||||
case 'h':
|
||||
print_usage();
|
||||
print_help();
|
||||
|
||||
@@ -533,9 +533,11 @@ DEFUN(cfg_apn_ip_prefix, cfg_apn_ip_prefix_cmd,
|
||||
struct in46_prefix *pfx;
|
||||
|
||||
/* first update our parsed prefix */
|
||||
if (!strcmp(argv[0], "static"))
|
||||
if (!strcmp(argv[0], "static")) {
|
||||
pfx = &apn->v4.cfg.static_prefix;
|
||||
else
|
||||
vty_out(vty, "%% static IP addresses currently not yet supported%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
} else
|
||||
pfx = &apn->v4.cfg.dynamic_prefix;
|
||||
str2prefix(pfx, argv[1]);
|
||||
|
||||
@@ -567,9 +569,11 @@ DEFUN(cfg_apn_ipv6_prefix, cfg_apn_ipv6_prefix_cmd,
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
struct in46_prefix *pfx;
|
||||
|
||||
if (!strcmp(argv[0], "static"))
|
||||
if (!strcmp(argv[0], "static")) {
|
||||
pfx = &apn->v6.cfg.static_prefix;
|
||||
else
|
||||
vty_out(vty, "%% static IP addresses currently not yet supported%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
} else
|
||||
pfx = &apn->v6.cfg.dynamic_prefix;
|
||||
str2prefix(pfx, argv[1]);
|
||||
return CMD_SUCCESS;
|
||||
@@ -699,6 +703,10 @@ DEFUN(cfg_apn_no_shutdown, cfg_apn_no_shutdown_cmd,
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
|
||||
if (apn->cfg.shutdown) {
|
||||
if (!apn->tun.cfg.dev_name) {
|
||||
vty_out(vty, "%% Failed to start APN, tun-device is not configured%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
if (apn_start(apn) < 0) {
|
||||
vty_out(vty, "%% Failed to start APN, check log for details%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# 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=6:0:0
|
||||
LIBVERSION=7:0:1
|
||||
|
||||
lib_LTLIBRARIES = libgtp.la
|
||||
|
||||
|
||||
175
gtp/gtp.c
175
gtp/gtp.c
@@ -196,6 +196,13 @@ int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
|
||||
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))
|
||||
@@ -773,7 +780,7 @@ static int gtp_resp(uint8_t version, struct gsn_t *gsn, struct pdp_t *pdp,
|
||||
|
||||
static int gtp_notification(struct gsn_t *gsn, uint8_t version,
|
||||
union gtp_packet *packet, int len,
|
||||
struct sockaddr_in *peer, int fd, uint16_t seq)
|
||||
const struct sockaddr_in *peer, int fd, uint16_t seq)
|
||||
{
|
||||
|
||||
uint8_t ver = GTPHDR_F_GET_VER(packet->flags);
|
||||
@@ -1200,6 +1207,57 @@ static int gtp_extheader_ind(struct gsn_t *gsn, struct sockaddr_in *peer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle a RAN Information Relay message */
|
||||
static int gtp_ran_info_relay_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer,
|
||||
void *pack, unsigned len)
|
||||
{
|
||||
union gtpie_member *ie[GTPIE_SIZE];
|
||||
|
||||
if (version != 1) {
|
||||
LOGP(DLGTP, LOGL_NOTICE,
|
||||
"RAN Information Relay expected only on GTPCv1: %u\n", version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int hlen = get_hlen(pack);
|
||||
|
||||
/* Decode information elements */
|
||||
if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
|
||||
gsn->invalid++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Invalid message format (AN Information Relay)\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gsn->cb_ran_info_relay_ind)
|
||||
gsn->cb_ran_info_relay_ind(peer, ie);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Send off a RAN Information Relay message */
|
||||
int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *peer,
|
||||
const uint8_t *ran_container, size_t ran_container_len,
|
||||
const uint8_t *rim_route_addr, size_t rim_route_addr_len,
|
||||
uint8_t rim_route_addr_discr)
|
||||
{
|
||||
union gtp_packet packet;
|
||||
|
||||
/* GTP 1 is the highest supported protocol */
|
||||
unsigned int length = get_default_gtp(1, GTP_RAN_INFO_RELAY, &packet);
|
||||
|
||||
gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RAN_T_CONTAIN, ran_container_len,
|
||||
ran_container);
|
||||
if (rim_route_addr) {
|
||||
gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RIM_ROUT_ADDR,
|
||||
rim_route_addr_len, rim_route_addr);
|
||||
gtpie_tlv(&packet, &length, GTP_MAX, GTPIE_RIM_RA_DISCR, 1,
|
||||
&rim_route_addr_discr);
|
||||
}
|
||||
|
||||
return gtp_notification(gsn, 1, &packet, length, peer, gsn->fd1c, 0);
|
||||
}
|
||||
|
||||
/* ***********************************************************
|
||||
* Session management messages
|
||||
* Messages: create, update and delete PDP context
|
||||
@@ -1792,9 +1850,6 @@ int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* Register that we have received a valid teic from GGSN */
|
||||
pdp->teic_confirmed = 1;
|
||||
|
||||
/* Decode information elements */
|
||||
if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
|
||||
gsn->invalid++;
|
||||
@@ -1894,6 +1949,8 @@ int gtp_create_pdp_conf(struct gsn_t *gsn, int version,
|
||||
gsn->cb_conf(type, EOF, pdp, cbp);
|
||||
return EOF;
|
||||
}
|
||||
/* Register that we have received a valid teic from GGSN */
|
||||
pdp->teic_confirmed = 1;
|
||||
}
|
||||
|
||||
if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
|
||||
@@ -2137,8 +2194,9 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
||||
/* Find the context in question */
|
||||
if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||
len, "Unknown PDP context\n");
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: TID=0x%" PRIx64 "\n",
|
||||
get_tid(pack));
|
||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
||||
len, NULL,
|
||||
GTPCAUSE_NON_EXIST);
|
||||
@@ -2162,9 +2220,9 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
||||
/* Find the context in question */
|
||||
if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer,
|
||||
pack, len, "Unknown PDP context: %u\n",
|
||||
get_tei(pack));
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: TEI=0x%" PRIx32 "\n",
|
||||
get_tei(pack));
|
||||
return gtp_update_pdp_resp(gsn, version, peer,
|
||||
fd, pack, len, NULL,
|
||||
GTPCAUSE_NON_EXIST);
|
||||
@@ -2173,8 +2231,9 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
||||
/* Find the context in question */
|
||||
if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi)) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer,
|
||||
pack, len, "Unknown PDP context\n");
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: IMSI=0x%" PRIx64
|
||||
" NSAPI=%" PRIu8 "\n", imsi, nsapi);
|
||||
return gtp_update_pdp_resp(gsn, version, peer,
|
||||
fd, pack, len, NULL,
|
||||
GTPCAUSE_NON_EXIST);
|
||||
@@ -2325,29 +2384,20 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
||||
static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
|
||||
struct sockaddr_in *peer, void *pack, unsigned len)
|
||||
{
|
||||
struct pdp_t *pdp;
|
||||
struct pdp_t *pdp = NULL;
|
||||
union gtpie_member *ie[GTPIE_SIZE];
|
||||
uint8_t cause, recovery;
|
||||
uint8_t cause = EOF;
|
||||
uint8_t recovery;
|
||||
int rc = 0;
|
||||
void *cbp = NULL;
|
||||
uint8_t type = 0;
|
||||
bool trigger_recovery = false;
|
||||
int hlen = get_hlen(pack);
|
||||
|
||||
/* Remove packet from queue */
|
||||
if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp))
|
||||
return EOF;
|
||||
|
||||
/* Find the context in question */
|
||||
if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: %u\n", get_tei(pack));
|
||||
pdp = NULL;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Register that we have received a valid teic from GGSN */
|
||||
pdp->teic_confirmed = 1;
|
||||
|
||||
/* Decode information elements */
|
||||
if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
|
||||
gsn->invalid++;
|
||||
@@ -2356,19 +2406,34 @@ static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Extract recovery (optional) */
|
||||
if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery))
|
||||
trigger_recovery = true;
|
||||
|
||||
/* Extract cause value (mandatory) */
|
||||
if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
|
||||
goto err_missing;
|
||||
}
|
||||
|
||||
/* Extract recovery (optional) */
|
||||
if (!gtpie_gettv1(ie, GTPIE_RECOVERY, 0, &recovery)) {
|
||||
emit_cb_recovery(gsn, peer, pdp, recovery);
|
||||
/* 3GPP TS 29.060 sec 8.2: "Receiving node shall send back to the source
|
||||
* of the message, a response with the appropriate cause value (either
|
||||
* "Non-existent" or "Context not found"). The Tunnel Endpoint
|
||||
* Identifier used in the response message shall be set to all zeroes."
|
||||
* Hence, TEID=0 in this scenario, it makes no sense to infer PDP ctx
|
||||
* from it. User is responsible to infer it from cbp */
|
||||
if (cause != GTPCAUSE_NON_EXIST && cause != GTPCAUSE_CONTEXT_NOT_FOUND) {
|
||||
/* Find the context in question */
|
||||
if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: TEI=0x%" PRIx32 "\n", get_tei(pack));
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check all conditional information elements */
|
||||
/* TODO: This does not handle GGSN-initiated update responses */
|
||||
if (GTPCAUSE_ACC_REQ == cause) {
|
||||
if (cause == GTPCAUSE_ACC_REQ) {
|
||||
if (version == 0) {
|
||||
if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
|
||||
&pdp->qos_neg0,
|
||||
@@ -2393,6 +2458,8 @@ static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
|
||||
if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
|
||||
goto err_missing;
|
||||
}
|
||||
/* Register that we have received a valid teic from GGSN */
|
||||
pdp->teic_confirmed = 1;
|
||||
}
|
||||
|
||||
if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
|
||||
@@ -2418,18 +2485,20 @@ static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
|
||||
}
|
||||
}
|
||||
|
||||
generic_ret:
|
||||
if (trigger_recovery)
|
||||
emit_cb_recovery(gsn, peer, pdp, recovery);
|
||||
if (gsn->cb_conf)
|
||||
gsn->cb_conf(type, cause, pdp, cbp);
|
||||
return 0; /* Succes */
|
||||
return rc; /* Succes */
|
||||
|
||||
err_missing:
|
||||
gsn->missing++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Missing information field\n");
|
||||
err_out:
|
||||
if (gsn->cb_conf)
|
||||
gsn->cb_conf(type, EOF, pdp, cbp);
|
||||
return EOF;
|
||||
rc = EOF;
|
||||
goto generic_ret;
|
||||
}
|
||||
|
||||
/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
|
||||
@@ -2594,7 +2663,7 @@ int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
|
||||
if (gtp_pdp_getgtp1(gsn, &linked_pdp, get_tei(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: %u\n", get_tei(pack));
|
||||
"Unknown PDP context: TEI=0x%" PRIx32 "\n", get_tei(pack));
|
||||
return gtp_delete_pdp_resp(gsn, version, peer, fd, pack, len,
|
||||
NULL, NULL, GTPCAUSE_NON_EXIST,
|
||||
teardown);
|
||||
@@ -2623,7 +2692,7 @@ int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
|
||||
if (gtpie_gettv1(ie, GTPIE_NSAPI, 0, &nsapi)) {
|
||||
gsn->missing++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||
len, "Missing mandatory information field\n");
|
||||
len, "Missing mandatory information field\n");
|
||||
return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
|
||||
len, NULL, NULL,
|
||||
GTPCAUSE_MAN_IE_MISSING,
|
||||
@@ -2633,8 +2702,9 @@ int gtp_delete_pdp_ind(struct gsn_t *gsn, int version,
|
||||
/* Find the context in question */
|
||||
if (gtp_pdp_getgtp1(gsn, &pdp, linked_pdp->secondary_tei[nsapi & 0x0f])) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||
len, "Unknown PDP context\n");
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: Secondary TEI=0x%" PRIx32 "\n",
|
||||
linked_pdp->secondary_tei[nsapi & 0x0f]);
|
||||
return gtp_delete_pdp_resp(gsn, version, peer, fd, pack,
|
||||
len, NULL, NULL,
|
||||
GTPCAUSE_NON_EXIST,
|
||||
@@ -2687,8 +2757,9 @@ int gtp_delete_pdp_conf(struct gsn_t *gsn, int version,
|
||||
if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
|
||||
"Unknown PDP context: %u (expected if gtp_delete_context_req is used or pdp ctx was freed manually before response)\n",
|
||||
get_tei(pack));
|
||||
"Unknown PDP context: TEI=0x%" PRIx32 " (expected if "
|
||||
"gtp_delete_context_req is used or pdp ctx was freed "
|
||||
"manually before response)\n", get_tei(pack));
|
||||
if (gsn->cb_conf)
|
||||
gsn->cb_conf(type, EOF, NULL, cbp);
|
||||
return EOF;
|
||||
@@ -2765,7 +2836,8 @@ static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
|
||||
if (gtp_pdp_tidget(gsn, &pdp, get_tid(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context\n");
|
||||
"Unknown PDP context: TID=0x%" PRIx64 "\n",
|
||||
get_tid(pack));
|
||||
return EOF;
|
||||
}
|
||||
} else if (version == 1) {
|
||||
@@ -2790,7 +2862,9 @@ static int gtp_error_ind_conf(struct gsn_t *gsn, uint8_t version,
|
||||
|
||||
if (gtp_pdp_getgtp1_peer_d(gsn, &pdp, peer, teid_gn)) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: Peer TEID=0x%" PRIx32 "\n",
|
||||
teid_gn);
|
||||
return EOF;
|
||||
}
|
||||
} else {
|
||||
@@ -2821,22 +2895,22 @@ static int gtp_gpdu_ind(struct gsn_t *gsn, uint8_t version,
|
||||
|
||||
switch (version) {
|
||||
case 0:
|
||||
if (gtp_pdp_getgtp0(gsn, &pdp,
|
||||
ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) {
|
||||
if (gtp_pdp_getgtp0(gsn, &pdp, get_tei(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||
len, "Unknown PDP context, GTPv0\n");
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: TEI=0x%" PRIx32 "\n",
|
||||
get_tei(pack));
|
||||
return gtp_error_ind_resp(gsn, version, peer, fd, pack,
|
||||
len);
|
||||
}
|
||||
hlen = GTP0_HEADER_SIZE;
|
||||
break;
|
||||
case 1:
|
||||
if (gtp_pdp_getgtp1(gsn, &pdp,
|
||||
ntoh32(((union gtp_packet *)pack)->gtp1l.h.tei))) {
|
||||
if (gtp_pdp_getgtp1(gsn, &pdp, get_tei(pack))) {
|
||||
gsn->err_unknownpdp++;
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||
len, "Unknown PDP context, GTPv1\n");
|
||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||
"Unknown PDP context: TEI=0x%" PRIx32 "\n",
|
||||
get_tei(pack));
|
||||
return gtp_error_ind_resp(gsn, version, peer, fd, pack,
|
||||
len);
|
||||
}
|
||||
@@ -3186,6 +3260,9 @@ int gtp_decaps1c(struct gsn_t *gsn)
|
||||
case GTP_ERROR:
|
||||
gtp_error_ind_conf(gsn, version, &peer, buffer, status);
|
||||
break;
|
||||
case GTP_RAN_INFO_RELAY:
|
||||
gtp_ran_info_relay_ind(gsn, version, &peer, buffer, status);
|
||||
break;
|
||||
default:
|
||||
gsn->unknown++;
|
||||
GTP_LOGPKG(LOGL_ERROR, &peer, buffer, status,
|
||||
|
||||
11
gtp/gtp.h
11
gtp/gtp.h
@@ -16,6 +16,7 @@
|
||||
#include <osmocom/core/defs.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
|
||||
#include "gtpie.h"
|
||||
#include "pdp.h"
|
||||
|
||||
#define GTP_MODE_GGSN 1
|
||||
@@ -85,6 +86,7 @@
|
||||
#define GTP_FWD_SRNS 58 /* Forward SRNS Context */
|
||||
#define GTP_FWD_RELOC_ACK 59 /* Forward Relocation Complete Acknowledge */
|
||||
#define GTP_FWD_SRNS_ACK 60 /* Forward SRNS Context Acknowledge */
|
||||
#define GTP_RAN_INFO_RELAY 70 /* RAN Information Relay */
|
||||
/* 61-239 For future use. */
|
||||
#define GTP_DATA_TRAN_REQ 240 /* Data Record Transfer Request */
|
||||
#define GTP_DATA_TRAN_RSP 241 /* Data Record Transfer Response */
|
||||
@@ -276,6 +278,7 @@ struct gsn_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);
|
||||
@@ -343,6 +346,11 @@ extern int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp,
|
||||
extern int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp,
|
||||
void *pack, unsigned len);
|
||||
|
||||
extern int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *peer,
|
||||
const uint8_t *ran_container, size_t ran_container_len,
|
||||
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));
|
||||
@@ -366,6 +374,9 @@ extern int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
|
||||
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));
|
||||
|
||||
10
gtp/gtpie.c
10
gtp/gtpie.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
* OsmoGGSN - Gateway GPRS Support Node
|
||||
* Copyright (C) 2002 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.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* gtpie.c: Contains functions to encapsulate and decapsulate GTP
|
||||
* information elements
|
||||
* gtpie.c: Contains functions to encapsulate and decapsulate GTP
|
||||
* information elements
|
||||
*
|
||||
*
|
||||
* Encapsulation
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <libgtpnl/gtp.h>
|
||||
#include <libgtpnl/gtpnl.h>
|
||||
#include <libmnl/libmnl.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@@ -31,10 +30,6 @@
|
||||
#include "../gtp/pdp.h"
|
||||
#include "../gtp/gtp.h"
|
||||
|
||||
#include <libgtpnl/gtp.h>
|
||||
#include <libgtpnl/gtpnl.h>
|
||||
#include <libmnl/libmnl.h>
|
||||
|
||||
#include "gtp-kernel.h"
|
||||
|
||||
static void pdp_debug(const char *prefix, const char *devname, struct pdp_t *pdp)
|
||||
|
||||
@@ -113,7 +113,7 @@ int main(int argc, char **argv)
|
||||
msgb_talloc_ctx_init(tall_ctx, 0);
|
||||
osmo_init_logging2(tall_ctx, &log_info);
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
log_set_print_filename(osmo_stderr_target, 0);
|
||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ int main(int argc, char **argv)
|
||||
msgb_talloc_ctx_init(tall_ctx, 0);
|
||||
osmo_init_logging2(tall_ctx, &log_info);
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
log_set_print_filename(osmo_stderr_target, 0);
|
||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
||||
|
||||
test_queue_empty();
|
||||
test_queue_one();
|
||||
|
||||
@@ -431,7 +431,7 @@ int main(int argc, char **argv)
|
||||
msgb_talloc_ctx_init(tall_ctx, 0);
|
||||
osmo_init_logging2(tall_ctx, &log_info);
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
log_set_print_filename(osmo_stderr_target, 0);
|
||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
|
||||
@@ -131,7 +131,9 @@ int main(int argc, char **argv)
|
||||
msgb_talloc_ctx_init(tall_ctx, 0);
|
||||
osmo_init_logging2(tall_ctx, &log_info);
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
log_set_print_filename(osmo_stderr_target, 0);
|
||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
||||
log_set_print_category(osmo_stderr_target, 0);
|
||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user