Compare commits

...

130 Commits

Author SHA1 Message Date
Oliver Smith
561a9bc77c Bump version: 1.11.0.31-7ae1-dirty → 1.12.0
Change-Id: Idf8b178290cbb14e5199590feb584c82dc076dd0
2024-07-24 16:22:26 +02:00
Vadim Yanitskiy
7ae1177e04 README.md: cosmetic: fix a typo
Change-Id: Ia04c62a682cfeca2b054c8fb1ff9fff2aab2860d
2024-06-05 18:34:07 +07:00
Oliver Smith
57585767dc {contrib,debian}/osmo-ggsn.init: remove
Remove SysV init scripts. These are not really maintained anymore and
this makes it consistent with other Osmocom projects.

Avoids synchronizing with SysV scripts on debian:
  # systemctl enable osmo-ggsn
  Synchronizing state of osmo-ggsn.service with SysV service script with /lib/systemd/systemd-sysv-install.
  Executing: /lib/systemd/systemd-sysv-install enable osmo-ggsn

Change-Id: I11bfb5122344b54970b7f742470cb74b95fa37e0
2024-05-16 09:00:21 +00:00
Oliver Smith
488972b442 Use uniform log format for default config files
Related: OS#6272
Change-Id: I272767e029e95b64f2525d4f19efdfa1f0e29ca2
2024-05-16 09:00:21 +00:00
Oliver Smith
08239ccac3 contrib/systemd: run as osmocom user
Related: OS#4107
Change-Id: I915f2fc12d0bd905d24636aacb2760a6b72a55e3
2024-05-16 09:00:21 +00:00
Oliver Smith
fbc56063c5 doc: set state-dir to /var/lib/osmocom/osmo-ggsn
Prepare to run osmo-ggsn as user with the systemd service. As with other
Osmocom service files, we will set StateDirectory= and WorkingDirectory=
options. This results in osmo-ggsn only being able to write to
/var/lib/osmocom, therefore let's change the state-dir from /tmp to
/var/lib/osmocom/osmo-ggsn to avoid:

  gsn.c:411 fopen(path=/tmp/gsn_restart, mode=w) failed: Error = Permission denied

Having the state in /var/lib/osmocom also makes more sense, because then
it doesn't get deleted on reboot.

Change-Id: I5b51529b4f8bd2462e54f58a1ce2e2d7c76ff46a
2024-05-16 09:00:21 +00:00
Oliver Smith
c1598e0eb4 ggsn/ggsn_vty: create state-dir
Prepare to change the state-dir in the default config in a follow-up
commit. Create the directory if it does not exist.

Change-Id: I91349fb284336a9de6af41475f1b824eb0e021b0
2024-05-16 09:00:21 +00:00
Oliver Smith
519a2e401d gtp/gtp_internal.h: new file
While at it, move internal functions of gtp.h to a separate file too.
Make all functions that are only used inside gtp.c static.

The following APIs are unexpectedly public:
* imsi_gtp2str gets used by pdp.h
* gsna2in_addr, gtp_echo_req gets used by osmo-sgsn

Change-Id: I72c40cbdec33449ca8104fb3cad8df1a9e07dfd7
2024-05-14 11:13:45 +02:00
Oliver Smith
fbef527222 gtp: move conversion functions up
Move the conversion functions above the first user, so we can make
in_addr2gsna static in a follow-up commit and remove the extra
declaration.

Change-Id: I51e6a7c1161320fc54b0e8197ae57e4327976eb1
2024-05-14 11:13:45 +02:00
Oliver Smith
68f5b086ad gtp: remove unused conversion functions
Remove ipv42eua and eua2ipv4, which are in the "internal functions"
section of gtp.h, but are not used anywhere in the code anymore. This is
in preparation of moving the internal functions that are used in
multiple .c files into a separate header file, and to make the other
internal functions static. (Compiler complains about unused static
functions.)

Change-Id: I90e2750f6a6e3e6122e9c562103fda77d7326932
2024-05-14 11:13:41 +02:00
Oliver Smith
3cb3423a59 gtp/gtp.c: move gtp_create_context_resp down
Move gtp_create_context_resp below gtp_create_pdp_resp, which it calls.
In a follow-up commit, we can make gtp_create_pdp_resp static and
remove the additional declaration.

Change-Id: I34efe7592013a8423f4f280758272d81f24b65fa
2024-05-13 15:16:58 +02:00
Oliver Smith
bad5eeba0f gtp/gsn_internal.h: new file
Change-Id: I999462e39411fc4ec7e50bd0212e870006fbc4f1
2024-05-13 15:16:58 +02:00
Oliver Smith
1dd16fa12f libgtp: move includes to osmocom/include/gtp
Move all includes from /usr/include/….h to
/usr/include/osmocom/gtp/….h to be more consistent with other Osmocom
projects, and to not "pollute" the top include directory if we add more
header files.

Also the new directory structure makes more obvious, which headers are
public and which ones aren't.

Adjust libgtp.pc.in so both #include <gtp.h> (legacy)
and #include <osmocom/gtp/gtp.h> can be used.

Related: OS#6373
Change-Id: If7e01c61168819bf7120667344e40c857da5490b
2024-05-13 15:16:58 +02:00
Oliver Smith
3372625ad9 contrib: remove rpm spec file
Related: https://osmocom.org/news/255
Related: OS#6446
Change-Id: I7cfe55fa2fda43da4eaa1e1b8d40b31d1c8aaf30
2024-05-08 14:40:58 +02:00
Harald Welte
1f9cc2674f README.md: Major overhaul
A lot of the existing contents was still from the old openggsn days, and
predated osmo-ggsn.

Change-Id: I6ec92260da0f55e9493a15db2e8178e5436143a0
2024-03-23 16:32:45 +01:00
Harald Welte
4abe361f33 README.md: Add Forum + Issue Tracker sections
Change-Id: I7b03a78178de77ebf733587ed178fd48c019663c
2024-03-23 16:15:42 +01:00
Harald Welte
bb0655d5aa README.md: Improve markdown formatting
Change-Id: I4e5d99384978d22e6ba0310e97e93d87b610a174
2024-03-23 16:11:50 +01:00
Harald Welte
4e6fe42731 Add funding link to github mirror
see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository

Change-Id: I75ba8c4f8635d5a2d36d5bb97566d737e27bcec9
2024-03-23 16:06:28 +01:00
Oliver Smith
19a506b705 Add clear error for kernel not supporting IPv6
Make it clear to the user, that if adding a tunnel fails with kernel GTP
and IPv6: the reason is that the kernel doesn't support IPv6 yet.

Related: OS#6096
Change-Id: I1d3c8cbb51212c91136292347dad9529a5c58a31
2024-03-04 11:15:07 +01:00
Oliver Smith
ea6c02ac1f doc: fix typo ndoe -> node
Change-Id: Ib78b5de45b93a7534163de2cd91211e9be75445d
2024-03-01 08:08:43 +00:00
Oliver Smith
ec357c5377 lib/gtp-kernel.c: check rc of in46a_from_eua
Fixes: b17fe7bf ("kernel-gtp: support IPv6 on inner layer")
Change-Id: I40e4de1517de8871224a45c173208810b42312ff
2024-02-27 16:04:42 +01:00
Oliver Smith
768d6d5be9 lib/gtp-kernel.c: initialize ret with 0
Fix -Werror=maybe-uninitialize found in Pau's build env:

/home/pespin/dev/sysmocom/git/osmo-ggsn/lib/gtp-kernel.c: In function ‘gtp_kernel_tunnel_add’:
/home/pespin/dev/sysmocom/git/osmo-ggsn/lib/gtp-kernel.c:111:13: error: ‘ret’ may be used uninitialized [-Werror=maybe-uninitialize]
  111 |         int ret;
      |             ^~~
/home/pespin/dev/sysmocom/git/osmo-ggsn/lib/gtp-kernel.c: In function ‘gtp_kernel_tunnel_del’:
/home/pespin/dev/sysmocom/git/osmo-ggsn/lib/gtp-kernel.c:167:13: error: ‘ret’ may be used uninitialized [-Werror=maybe-uninitialize]
  167 |         int ret;
      |             ^~~

Fixes: b17fe7bf ("kernel-gtp: support IPv6 on inner layer")
Change-Id: I19067ebe561d4c067b9ace7f5b201e15af6b342e
2024-02-27 15:00:59 +01:00
Oliver Smith
fa91a10498 Cosmetic: {lib,gtp}/Makefile.am: diff friendly
Change-Id: Ib1956794edc6e82cfa6c5419b2609565674d98a4
2024-02-23 13:25:32 +01:00
Oliver Smith
6929391ecf Cosmetic: AM_CFLAGS: make diff friendly
Change-Id: I3303cd8ba8c8b21ff267608833d9fb4833ffc471
2024-02-23 12:08:48 +01:00
Oliver Smith
9baac03927 Cosmetic: Makefile.am: make SUBDIRS diff friendly
Change-Id: I49e1b08e48dc324f313228e8c69679c37aa774f4
2024-02-23 12:08:48 +01:00
Oliver Smith
9bd2711f39 Revert "kernel-gtp: support IPv6 on outer layer"
This reverts commit 0917ce4e22,
as it breaks building osmo-sgsn. This needs to be reworked to be
backwards compatible.

Related: OS#6373
Change-Id: I2c2b2ff0875217e041d94c8e2cef030d2a86c2d8
2024-02-22 16:06:33 +01:00
Oliver Smith
b17fe7bfe9 kernel-gtp: support IPv6 on inner layer
Related: OS#6096
Change-Id: I3df47b6c209f1e2f8254ba139581d6e622c6b35f
2024-02-21 16:22:24 +01:00
Oliver Smith
0917ce4e22 kernel-gtp: support IPv6 on outer layer
Related: OS#1953, OS#6096
Change-Id: I257fff1dcd9d030a7f9ea936b2693a3f13208230
2024-02-21 16:22:21 +01:00
Oliver Smith
2a0d37cb1d gtp_new: deduplicate create_and_bind_socket code
Change-Id: Iff3cfdfb0c08033d869c51499754b3416c71732b
2024-02-21 13:06:04 +01:00
Oliver Smith
f3d541e353 Fix a typo
Change-Id: I508274a1a466651025c488ad897aeed739e4b799
2024-02-21 13:05:56 +01:00
Pau Espin Pedrol
8d976444b8 pco: Improve IPCP spec reference documentation
Change-Id: I1dd4a41bae491c61197e8e307efcfc8c63945a71
2024-01-26 16:12:08 +01:00
Daniel Willmann
77734ac81b libgtp: Remove defines for reserved causes in gtp.h
As discussed in Gerrit change I9c3bf64537ef2223e29f8082861fa32fde26bf68
remove defines that don't serve any purpose. These are defines for
reserved values and changing them later if a newer spec defined them
would break API.

Keep the comments to explain the missing values.

Change-Id: I8db0aa0ade59785443a407b51dea326144406dcf
2023-11-29 16:40:49 +01:00
Oliver Smith
848ec697e2 Bump version: 1.10.2.1-a625 → 1.11.0
Change-Id: I1f116e1cded135f231f22ebc9b817aebf3736fc2
2023-11-28 13:07:17 +00:00
Daniel Willmann
6a2e82542d libgtp: Use gtp_cause_successful() instead of GTPCAUSE_ACC_REQ
In some cases the phone requests a PDP context type that isn't available
no the PGW/GGSN, e.g. phone requests a combined IPv4/v6 context, but
only IPv4 is supported.

In that case the GGSN can send a Create PDP Context Response with cause
"New PDP type due to network preference" or "New PDP type due to single
address bearer only". libgtp should continue handling these cause values
like the "Request Accepted" cause. Use the new gtp_cause_successful()
function for that.

Related: OS#6268
Change-Id: I7dd1e0aa185530e1e2d0402742df833c61a787a7
2023-11-24 09:48:22 +01:00
Daniel Willmann
a625bdd136 gtp: Add net GTP cause values and a function to check for success
According to the spec the upf/pgw can accept a modified pdp context from
the request e.g. if an ipv4/6 context was requested, but only ipv4 is
availiable. Introduce a function that checks all cause values that are
considered successful.

See also: 3GPP TS 29.060 Ch 7.3.2

Related: OS#6268
Change-Id: I9c3bf64537ef2223e29f8082861fa32fde26bf68
2023-11-22 12:36:49 +01:00
Pau Espin Pedrol
08bb5182a4 Bump version: 1.10.1.8-4963-dirty → 1.10.2
Change-Id: I148375902975aba0a374e4507c97f1ff67d687bc
2023-09-12 14:36:11 +02:00
Oliver Smith
4963d1c2ea lib/in46_addr: add in46a_from_gsna
Prepare to use it in gtp-kernel.c in a future patch.

Related: OS#6096
Change-Id: I3e76eb7ee89ba338f085c617662d15cffa2a62d5
2023-07-24 15:06:03 +02:00
Oliver Smith
37daa5d003 doc: running: update kernel-gtp limitations
Related: OS#6096
Change-Id: Ie4f1452ecefbe0db0e4093caa8177f1c87bd3950
2023-07-21 12:59:41 +02:00
Oliver Smith
c4c4d90b85 README: update documentation section
Change-Id: I3320dc5eb3d183a18c2bd2fe3139f729978ea2a1
2023-07-21 11:19:14 +02:00
Oliver Smith
59f1539ece systemd: depend on networking-online.target
Related: SYS#6400
Change-Id: I29e547242b2ed1cfc4750c7d7e5f8636c2e8f3dc
2023-05-26 14:10:45 +02:00
Oliver Smith
eff88c08e7 debian: set compat level to 10
Related: OS#5958
Change-Id: I4b2988fffba12cc84ff0834bb9ef0f3d9de2bcda
2023-04-25 16:48:22 +02:00
Oliver Smith
92ac7249f9 doc/manuals/chapters/configuration: fix typo
Change-Id: I0e9d2c77200c7c8b49aec669bc39ca91d5d4cf1f
2023-04-11 17:18:34 +02:00
Vadim Yanitskiy
5cf6b75dc9 tests: use -no-install libtool flag to avoid ./lt-* scripts
This option should be used for any executables which are used only
for testing, or for generating other files and are consequently never
installed.  By specifying this option, we are telling Libtool that
the executable it links will only ever be executed from where it is
built in the build tree.  Libtool is usually able to considerably
speed up the link process for such executables.

Change-Id: I2ca675e93dc5b34bb08d3b841adc115e93558137
2023-03-11 04:36:59 +07:00
Vadim Yanitskiy
4aa2e417c9 Do not hard-code -g and -O2 in CFLAGS
Let the user decide on the optimization level and debugging info.

Change-Id: I4b0b523b7dac4d67413bda37b546964262e5ea0d
2023-03-09 17:17:03 +07:00
Vadim Yanitskiy
f14c056310 Bump version: 1.10.0.4-bf69 → 1.10.1
Change-Id: Ibde9f259bccce29638d35efbd597669f5584e295
2023-02-27 22:35:47 +07:00
Vadim Yanitskiy
bf69ddbfef gtp: use OSMO_ASSERT() in gtp_new()
When using built-in static_assert() [1], gcc v12.2.1 fails:

In file included from gsn.c:27:
gsn.c: In function 'gtp_new':
gsn.c:444:54: error: expression in static assertion is not constant
  444 |         osmo_static_assert(gtp_T_defs[0].default_val != 0, first_default_val_not_zero);
      |                                                      ^

The reason is likely that gtp_T_defs[] is not const, so it cannot
be assert()ed statically.  With the current osmo_static_assert()
implementation, this assert does nothing.  One can change the
gtp_T_defs[0].default_val to 0 and the code will still compile.

Change-Id: Ia8af1736b63d501661046fe70befe5bbabc1045a
Related: [1] libosmocore.git I5ca34bc14c05e8c38c721d7df33feb1c6c41c76e
2023-02-27 17:07:26 +07:00
Vadim Yanitskiy
70a4e2e6f8 gtp/gsn.c: fix 'No newline at end of file'
git complains if it's missing, vim adds it automatically.

Change-Id: I3b4808a76da89e65b934d818e7ca280bc0651483
2023-02-27 17:07:26 +07:00
Vadim Yanitskiy
99afe979ef lib/icmpv6.h: fix struct icmpv6_{radv_hdr,opt_prefix}
Fix wrong field order in the big-endian variants.

Change-Id: Ifaa63bb5496e056805bd13b964c8b430fb11c24c
2023-02-27 17:07:05 +07:00
Oliver Smith
35066fb0b0 debian/libgtp6.shlibs: new file
List the most recent library version where new symbols where added, so
debian properly upgrades libgtp6 when upgrading osmo-sgsn from the
version that is currently in Debian to a version from the Osmocom
repositories.

Closes: OS#5318
Change-Id: Ida5dae4655c0acaeb377bc9d556a2ac333bca10a
2023-02-08 18:11:54 +01:00
Pau Espin Pedrol
55fe62f634 Bump version: 1.9.0.10-4fac-dirty → 1.10.0
Change-Id: I553fb72c577181c32005093eaf4fa986ae0e6ca8
2023-02-07 14:29:49 +01:00
Pau Espin Pedrol
4fac842826 Fix typos in comments and VTY descriptions
Change-Id: I359425152dc18d29c57047f1b10942480b7a61e5
2023-01-17 14:17:18 +01:00
arehbein
97f60e3dca osmo-ggsn: Transition to use of 'telnet_init_default'
Related: OS#5809
Change-Id: I51b7c175192759e26d1791723540841e72879b02
2022-12-23 11:13:31 +00:00
Max
a727e6ed38 ctrl: take both address and port from vty config
Change-Id: Ib31d67591657e308eebd1e6b7e23f79e6a3656e9
2022-12-17 21:14:57 +03:00
Pau Espin Pedrol
3a55b89777 gtp: Introduce VTY configurable GTP timer X3
This timer controls the amount of time a resp message transmitted by the
local gsn is to be stored in the resp queue. This is used in order to
detect duplicate requests received, since GTP states the exact same
response should be answered if a duplicate request is received.

Prior to this patch, this timer was hardcoded to 60 seconds.
This patch actually should be set, in general, to a value
equal than (T3-RESPONSE * N3-REQUESTS) values configured at
the peer, since that is the maximum period during which the local gsn
expects to receive req retransmissions from the peer.
Hence, this value must be user configurable to adapt it to the peers
connected to the GSN.

The 60 seconds hardcoded value is therefore changed to default to our
local (T3-RESPONSE * N3-REQUESTS), since the most common scenario for
osmo-ggsn/osmo-sgsn is to run it against a peer osmo-sgsn/osmo-ggsn,
which will have the same values by default.
This way we avoid by default caching response messages for way too long,
potentially filling the queue.

Related: OS#5485
Change-Id: Ia15c1cfd201d7c43e9a1d6ceb6725ddf392d2c65
2022-11-04 11:21:25 +01:00
Pau Espin Pedrol
9f1f747d8e ggsn: Introduce tdef and make it configurable over VTY
Related: OS#5485
Change-Id: I10bc8e2e197c0e8753b23b684b5ae41025672bf7
2022-11-02 20:33:39 +01:00
Pau Espin Pedrol
b9036af7ca Use rate_ctr for gsn_t available_counters
This way they can be inspected with regular osmocom means.

Change-Id: I529305b4f824600c6e733a3c0d2c2c6673f99faf
2022-11-02 18:41:38 +01:00
Pau Espin Pedrol
724ecc6680 Split gsn_t related APIs out of gtp.{c,h}
This way we split the gsn_t object API/logic from the protocol (message
handling) code.

Change-Id: I47cebb51bf08b9fcf7f115fc8dbea5f3493d4388
2022-11-02 18:41:34 +01:00
Pau Espin Pedrol
0d3bd3435f cosmetic: gtp: Fix typo in comment
Change-Id: I54b80bba3126cb3ae534938e253721961d4e08c4
2022-11-02 13:22:17 +01:00
Max
3ed252b58e Ignore .deb build byproducts
Change-Id: Iec63ef5ea0acfc5e6621054926be15ae4754d65d
2022-08-30 19:24:48 +07:00
Max
ac802e63d7 Set working directory in systemd service file
By default systemd will execute service with root directory (or home directory for user instance) which might result in
attempts to create files in unexpected place. Let's set it to 'osmocom' subdir of state directory (/var/lib for system
instance) instead.

Related: OS#4821
Change-Id: Idffc115c21cac77f6f43356333de538ba549fc6a
2022-08-30 19:24:48 +07:00
Pau Espin Pedrol
bc583d9763 Bump version: 1.8.0.13-ade4-dirty → 1.9.0
Change-Id: Id61cbe354437233fc6baf187ea90284da6a6944b
2022-06-28 17:48:22 +02:00
Harald Welte
ade4dc191b update git URLs (git -> https; gitea)
Change-Id: I9d59b62493bcdcb1bdbfbfd0525bae2988359f27
2022-06-18 12:04:24 +02:00
Vadim Yanitskiy
cd05da79e7 tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS'
When using 'check_PROGRAMS', autoconf/automake generates smarter
Makefiles, so that the test programs are not being compiled during
the normal 'make all', but only during 'make check'.

Change-Id: Ia8b8dade0056c51d2dd1d814a89d1de064597344
2022-04-13 19:55:33 +03:00
Pau Espin Pedrol
5545bcea5d pco.h: Fix typo in reference to spec
Change-Id: Ic428892161123b62d25a7619128ef7325bf85500
2022-03-24 12:51:17 +01:00
Pau Espin Pedrol
c97286f839 gtp: Fix typo in comment
Change-Id: I0e38e0966081d8b37c3f816f5330b4f52f81b7fa
2022-03-07 16:22:53 +01:00
Pau Espin Pedrol
f471800168 gtp: Log retrans queue register&free entries
Change-Id: I4e12376652fc7a6a96fbdcb579dbe916c1473012
2022-03-07 16:22:53 +01:00
Pau Espin Pedrol
bdf0697a5a gtp: Specify retrans queue name & seqnum in log lines
Change-Id: I4f193d7a482ace33afd8526b5f50d2d03467d5fa
2022-03-07 12:55:07 +01:00
Pau Espin Pedrol
674a912fb5 gtp: Small log improvements in gtp_create_pdp_ind()
Drop unneeded log line, rewrite line to better fit code path.

Change-Id: Id254e04d539cc055fee8c16fb66cd897b041557e
2022-03-07 12:44:15 +01:00
Pau Espin Pedrol
1bf3b3d0f9 gtp: Log detection of rx duplicate
Change-Id: I8bc9143db6743ad4fae2fe6d6fe0417648e9eec9
2022-03-07 12:20:13 +01:00
Pau Espin Pedrol
fb9303c610 gtp: Use switch statement in gtp_create_pdp_ind()
Double if had to be changed to if-else anyway, so let's simply use a
switch statement.

Change-Id: I91e8722947e58776742521d89abef8ae7584cb25
2022-03-07 11:34:30 +01:00
Pau Espin Pedrol
0585769741 libgtp: Define retransmit QUEUE_SIZE relative to PDP_MAX (increase)
QUEUE_SIZE holds the number of pending transmitted messages
which can be handled concurrently.
Current value was 1024, same as PDP contexts (PDP_MAX). However, that
seems to be a quite low amount, which can be filled under certain
conditions, for instance if recovery procedure is triggered on the GSN
which is running full (around PDP_MAX pdp contexts created).
In this scenario, the GSN would need to send around PDP_MAX concurrent
messages (DeletePDPContextReq), which means the queue would very likely
end up being full.
Hence, let's define QUEUE_SIZE based on PDP_MAX, and set it to twice the
size to make sure it won't be filled in extreme conditions.

Change-Id: I6034b0fab2b2e5962314c2fca2f893246ce5cf4f
2022-03-01 12:39:08 +01:00
Pau Espin Pedrol
9b288b788e libgtp: Fix ggsn crash if pdp alloc array is full (PDP_MAX)
osmo-ggsn crashes when concurrent pdp context num 1024 is created, due to
the gsn->pdpa array (of size PDP_MAX, 1024) being full.
The crash happens because return code of gtp_pdp_newpdp was not checked,
and hence a pointer "pdp" pointing to a temporary not-fully-allocated
object was being passed to gsn->cb_create_context_ind() callback.

Let's avoid crashing and instead reject the PDP context.

Related: OS#5469
Change-Id: I0d94ffad97eb4fef477d981bf285bf99740592a3
2022-03-01 12:38:58 +01:00
Pau Espin Pedrol
134ac7e7c8 vty: Fix cmd 'no echo-interval' doing nothing
It was incorrectly implemented and in practice was a NOOP.

Change-Id: I5e03c4965d05871d3f2e56675da6e75af0ec18c2
2022-02-25 17:25:00 +01:00
Pau Espin Pedrol
46f04343a5 tests: in46a_test: Make coverity happy when calling in46a_from_eua
Coverity warns around that test code:
"Overrunning struct type in46_addr of 20 bytes by passing it to a
function which accesses it at byte offset 39."

That's basically because in64a_from_eua expects to be passed a 2 element
array to be filled. The second element, though, is only accessed in the
case where an IPv4v6 EUA is passed, so in the cases where the test
explicitly passes an IPv4 or IPv6 EUA it's not really an issue, hence
coverity throwing a false positive here.
Let's anyway rewrite the code to pass a 2 element array for completeness,
since it doesn't hurt and makes coverity happy.

Related: Coverity CID#249006
Change-Id: Idfc9104f48eeee6e7f11ebc5c17d4b0e4b2fe9e2
2022-02-09 09:41:46 +01:00
Pau Espin Pedrol
a3ca2d185b Bump version: 1.7.1.20-8cbd-dirty → 1.8.0
Change-Id: I21502c6e0b804237fe9bd8f5579dbabd519d6d51
2021-11-16 13:49:16 +01:00
Pau Espin Pedrol
8cbdd21867 gtp_echo_responder: report invalid chars present in node-feautres cmdline arg as error
from "man strtoul":
"""
If endptr is not NULL, strtoul() stores the address of the first invalid character in *endptr.
In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.
"""

Fixes: ae81195418
Change-Id: I89d26a575ef81ee17483db035924354588d9d094
2021-10-08 17:28:16 +02:00
Pau Espin Pedrol
ae81195418 Introduce program gtp-echo-responder
This is a small standalone program (under MIT license, hence cannot make
use of libosmocore) whose only purpose is to answer GTPC (v1 and v2)
Echo Request messages with Echo Reply ones, with information provided
from the command line.

A small python script companion is provided to easily test the program.

Related: SYS#5598
Change-Id: Ibdd6d8f6920571db0c60cf8b3b25d541b15ad3f1
2021-10-04 14:06:51 +02:00
Pau Espin Pedrol
6ee5fa939a cosmetic: configure.ac: Fix tabulation in line
Change-Id: I5cfc90ace5f9cc9c3fe4dde7aeccbdf1909da007
2021-09-23 13:35:13 +02:00
Pau Espin Pedrol
b6a0e3fd2e ggsn: Fix heap-use-after-free during Recovery without associated PDP
Related: OS#4641
Change-Id: Ib4dca2e30e723a196084b0fa0040fbceca835359
2021-06-10 19:41:00 +02:00
Pau Espin Pedrol
bd2b55679e ggsn: Log tun fd write errors
Change-Id: I5f681b5edcc4cf525629d2078ae0c0ffd7ebb72d
2021-06-01 12:00:21 +02:00
Pau Espin Pedrol
f32c6a9095 gtp: Support tx/rx RAN Information Relay message
See 3GPP TS 29.060 sec 7.5.14.1 RAN Information Relay.

Related: SYS#5314
Change-Id: Iea3eb032ccd4aed5187baca7f7719349d76039d4
2021-05-06 18:57:12 +02:00
Pau Espin Pedrol
2eed6ec5ec gtp: constify pointer arg
Change-Id: Ib5b5a8b64247202a2538c2ff8f8601981ccda822
2021-05-05 17:51:34 +02:00
Pau Espin Pedrol
641206ad5e cosmetic: gtpie.c: Fix trailing whitespace
Change-Id: I552e3b5f694e1b49fe5e21fa4023e4a24ffc2784
2021-05-03 17:24:30 +02:00
Pau Espin Pedrol
bfd3119ae4 gtp: Improve logging of failing pdp ctx resolution from TEI/TID
Change-Id: I4f2084ec7e3a830e0224dd998ff0fe6654cc23bd
2021-04-22 16:24:55 +02:00
Pau Espin Pedrol
4b9b19e998 ggsn: Improve logging on incoming DL data packets
Change-Id: I3617c8f68d8f18617871c070e28cc6ae5c6a925b
2021-04-22 16:24:55 +02:00
Pau Espin Pedrol
00e0559e17 gtp: Rework parsing logic of UpdatePdpCtxResponse
The previous order of parsing lead to non-optimal information gathering
when pushing events to upper layers.

This patch rearranges parsing of packet data to always gather as much
info as possible for the benefit of the upper layer. This way it can
gather information such as the cause, which is important in the case of
"Non-existent", since user should then drop the context.

First we want to parse the recovery state, but delay cb to upper layers
until we tried to gather the pdp ctx (meaning all except that pdp ctx
should be freed).
Second, we want to parse the cause, in order to know if there's an
associated pdp ctx we can gather from TEID.
Third, once we know if we should expect a meaningul TEID, parse it.

Related: SYS#5435
Change-Id: Idd10b494e8fbac8703c49ecd8f9bbe4246e51c57
2021-04-22 16:24:48 +02:00
Pau Espin Pedrol
0b1d9dbc40 gtp: Update teic_confirmed only on resp success
Change-Id: I54c54cbb51bfa5d1520855f448fa27511037b396
2021-04-21 19:45:23 +02:00
Harald Welte
5379273ea3 vty: Inform user that static IP addresses are not supported
Currently, osmo-ggsn doesn't implement PDP contexts with static IP
addresses.  The code for specifying ranges that can be used for
static IPs was always present even from OpenGGSN days, but we never
really treated them.  Let's not raise the impression we do by
warning accordingly if the user configures them.

Change-Id: I7787dae037c46c0c5052aa6dd000be330984f144
Related: OS#5097
2021-03-27 19:03:30 +01:00
Harald Welte
ecef920b8f ggsn: Reject PDP CTX ACT for static IP addresses
We don't implement handling of static IP addresses for now,
let's properly reject those rather than allocating a dynamic address
anyway.

Change-Id: Iac8868438655fe4e5e07d167d7dbd6273dbb7678
Related: OS#5097
2021-03-27 19:00:34 +01:00
Harald Welte
eb9267b15e Don't install sgsnemu.conf to /etc/osmocom/
This is an auxiliary example config file, which should not be installed
to /etc/ and hence not be in OSMOCONF_FILES

This fixes the following rpm packaging error:
[  149s] error: Installed (but unpackaged) file(s) found:
[  149s]    /etc/osmocom/sgsnemu.conf

Change-Id: Id31f6542590405531ff61a9434041c15e779865b
Fixes: Icd6f3efcf5a9ef50237a3d0a76d4cce55051f447
2021-03-03 08:10:56 +01:00
Harald Welte
1efb2bcd90 Don't install osmo-ggsn-kernel-gtp.cfg to /etc/osmocom/
This is an auxiliary example config file, which should not be installed
to /etc/ and hence not be in OSMOCONF_FILES

This fixes the following rpm packaging error:
[  149s] error: Installed (but unpackaged) file(s) found:
[  149s]    /etc/osmocom/osmo-ggsn-kernel-gtp.cfg

Change-Id: If118ed26491a1edda83eda7f95479e165ca4c150
Fixes: I6fbe8a8e55bad41532e9aed3cf71ebebffdcee52
2021-03-03 08:10:23 +01:00
Oliver Smith
878593f205 gitignore: add ggsn_vty_reference.xml
Change-Id: I39bd36e4bde457b7c7a62ca6aa6d5dadea4051fc
2021-03-02 09:03:20 +01:00
Oliver Smith
1596463985 doc/manuals: describe GTP-U kernel module
Related: OS#3209
Change-Id: Ib45cbfe03077960f216a83cf500ab3203d02cb3b
2021-03-02 09:03:09 +01:00
Oliver Smith
9d82492e49 doc/examples/osmo-ggsn-kernel-gtp.cfg: new file
Add a copy of osmo-ggsn.cfg, with gtpu-mode set to kernel-gtp and apn
inet6 and inet46 removed (as the kernel module only supports ipv4).

Related: OS#3209
Change-Id: I6fbe8a8e55bad41532e9aed3cf71ebebffdcee52
2021-03-01 15:37:39 +01:00
Oliver Smith
303aeea8a8 doc/examples/Makefile.am: add sgsnemu.conf
Related: OS#3209
Change-Id: Icd6f3efcf5a9ef50237a3d0a76d4cce55051f447
2021-03-01 15:03:10 +01:00
Pau Espin Pedrol
18898b4a9f Bump version: 1.7.0.2-17ce → 1.7.1
Change-Id: Ideca49e0762eb20799375a33a04469673dfeb168
2021-02-23 17:31:24 +01:00
Harald Welte
17cee2056c manuals: generate vty reference xml at build time
Remove ggsn_vty_reference from the source tree.

In manuals/Makefile.am use the new BUILT_REFERENCE_XML feature recently added
to osmo-gsm-manuals, and add a build target to generate the XML using the new
osmo-ggsn --vty-ref-xml cmdline switch.

Change-Id: I772293cc78a6c95e07565a7048c1c8dadf87d2fc
Depends: I613d692328050a036d05b49a436ab495fc2087ba
Related: OS#5041
2021-02-23 17:08:14 +01:00
Harald Welte
67a3c833af main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
Change-Id: I966715ab2a430497bbccf26c50aef72d0901997f
Depends: Ie2022a7f9e167e5ceacf15350c037dd43768ff40
Related: OS#5041
2021-02-23 17:08:06 +01:00
Pau Espin Pedrol
b1f641b5b7 Bump version: 1.6.0.22-f01c-dirty → 1.7.0
Change-Id: I05d9bee0791cec5aebbeb1602be6697ecc2e2b74
2021-02-23 13:34:40 +01:00
Harald Welte
f01ce65f5b gtp-kernel: don't #include libmnl headers
* we don't check for libmnl via pkg-config in configure.ac
* we don't add libmnl include path to CFLAGS

As a result, we cannot #include related files.

libmnl is completely encapsulated by libgtpnl.  It even
includes a forward-declaration of 'struct mnl_socket'.

Change-Id: I0af869cc3c8e30b69d73a4985c56ef7743565e95
2021-02-20 11:28:59 +01:00
Harald Welte
be1cf99e9a gtp-kernel: Remove duplicate #include section
This was probably a wrong patch merge at some point.

Change-Id: I54191aca8fd55de84d86591035fe9785d379205f
2021-02-20 11:05:53 +01:00
Oliver Smith
7710080ffd deb/rpm: build with --enable-gtp-linux
Allow optional use of the GTP kernel module.

Related: OS#3208
Change-Id: Ic001ec6c5ec9887706a5b27f2a48cd61942ab4ee
2021-02-19 18:28:04 +01:00
Oliver Smith
798a81d48d .gitignore: ignore debian/libgtp*
Change-Id: I41fa611917defeab13f01a59dcc3f95961f10bda
2021-02-19 18:25:58 +01:00
Pau Espin Pedrol
51930f7b63 tests: Replace deprecated API log_set_print_filename
Change-Id: I35eb879d82e1030ea8be56ce9039277c021bb6fa
2021-02-19 13:23:00 +01:00
Pau Espin Pedrol
00ef1b0d6e tests: Explicitly drop category from log
Let's disable category here since we don't care about its formatting here.

In any case, every test relying on logging output validation should
always explicitly state the config to avoid issues in the future if
default values change.

Change-Id: Icce09882ef3ed07328679594ff84902383d16c72
Related: OS#5034
2021-02-19 13:22:28 +01:00
Oliver Smith
02a82c3c9b apn_start: avoid segfault if missing tun-device
Check if tun-device is defined and give the user a hint that it is
missing instead of segfaulting with gtpu-mode kernel-gtp:
  20210205141701206 DGGSN <0002> ggsn.c:186 APN(internet): Starting
  20210205141701206 DGGSN <0002> ggsn.c:204 APN(internet): Opening Kernel GTP device (null)
  Segmentation fault

With gtpu-mode tun it didn't segfault, but still tried to open the NULL
device:
  20210205141557598 DGGSN <0002> ggsn.c:186 APN(internet): Starting
  20210205141557599 DGGSN <0002> ggsn.c:189 APN(internet): Opening TUN device (null)
  20210205141557599 DTUN <0001> tun.c:195 errno=1/Operation not permitted ioctl() failed

Related: OS#3208
Change-Id: I9f71af65cc0eed71728c04b774e5c08352947913
2021-02-05 16:37:02 +01:00
Oliver Smith
349cbfcf50 configure.ac: set -std=gnu11
Change-Id: I7fed7d43242f804e6d2b005277c5b2b1bd197aa8
2021-01-28 09:28:56 +00:00
Oliver Smith
51f99ae250 contrib/jenkins: don't build osmo-gsm-manuals
Related: OS#4912
Change-Id: Ie77a81d3bd7cdb739fa082d9e1b5ddeba433a9db
2021-01-13 13:05:20 +01:00
Pau Espin Pedrol
12304c0e5a ggsn: generate coredump and exit upon SIGABRT received
Previous code relied on abort() switching sigaction to SIG_FDL +
retriggering SIGABRT in case the signal handler returns, which would
then generate the coredump + terminate the process.
However, if a SIGABRT is received from somewhere else (kill -SIGABRT),
then the process would print the talloc report and continue running,
which is not desired.

Change-Id: I7acfdfe5020320d853cba98b5add7479f8aaaf39
Fixes: OS#4865
2020-11-25 18:49:16 +01:00
Harald Welte
1719abb409 Use OSMO_FD_* instead of deprecated BSC_FD_*
Change-Id: Ib660cbbeafd8f4077c693d53127ecd1c15455455
2020-10-18 22:38:20 +02:00
Pau Espin Pedrol
3ddf4c6933 contrib/jenkins: Enable parallel make in make distcheck
Change-Id: Id7d4e6682be1d4f77979e896089b42f35548ca98
Related: OS#4421
2020-10-12 19:32:31 +02:00
Keith
fb2a7298e0 GTP: Replace recently introduced imsi_str2gtp()
Replace with the version from osmo-sgsn, renamed so
as not to collide with that version.

Change-Id: I910d5339a823332277ce7b5854d5c943ed69ea81
2020-10-12 15:47:26 +02:00
Keith
568ac5ee8e sgsnemu: relax check on length of IMSI cmdline arg.
Change-Id: I0374ff8773ae528c916fbee5f3f1efd89a5d2a08
2020-10-12 13:17:49 +02:00
Keith
23c832bb4b Use imsi_str2gtp() in sgsnemu
Change-Id: I94168c84dd613cfe51715e247b0d8b57308017d0
2020-10-12 13:11:26 +02:00
Keith
4831851ca3 Minor: remove code duplication
Change-Id: Id18ebcd3b3c20ce28e383edf9354e9f8516e1e81
2020-10-12 13:11:26 +02:00
Keith
080dcfaabe Prevent Crash in show pdp-context from vty
Fix test for return value from gtp_pdp_getimsi() so
we do not call show_one_pdp() with an uninitialised pdp_t

Change-Id: Ic40429939b185f97c020dd3904e054fe860b91e8
2020-10-12 13:11:25 +02:00
Keith
cbc07bdd82 Fix vty PDP lookups by IMSI
The PDP context is searched on the hash which is generated
on context creation from the IMSI in gtp format. - A hash
created from "human-readable" IMSI does not match.
Check user input for length then convert the IMSI to gtp format
before continuing.

Change-Id: Icd2e2bc6068c06fbf5d5fe905ebcda8954f33f04
2020-10-12 13:11:19 +02:00
Pau Espin Pedrol
aedae4c971 Support setting rt-prio and cpu-affinity mask through VTY
Change-Id: Ic8d38a5f64c661ce650004c68d73bd77149caef4
Depends: libosmocore.git Change-Id If76a4bd2cc7b3c7adf5d84790a944d78be70e10a
Depends: osmo-gsm-masnuals.git Change-Id Icd75769ef630c3fa985fc5e2154d5521689cdd3c
Related: SYS#4986
2020-08-18 12:52:56 +02:00
Pau Espin Pedrol
b36eb9d12f doc: Update VTY reference xml file
Change-Id: I2e8bebb67e63000c6f571a23baec04a68fc2974e
2020-08-18 12:47:39 +02:00
Pau Espin Pedrol
8df01fad14 configure.ac: Fix trailing whitespace
Change-Id: Ia7b0ff11e58375842be15823d6b5dcaafc0f1f82
2020-08-18 12:47:26 +02:00
Vadim Yanitskiy
c8020b959d debian/control: change maintainer to the Osmocom team / mailing list
Change-Id: Ia93dd2bf84ebb2c4d11917021888d4c6a5085d50
2020-08-13 15:00:43 +00:00
Harald Welte
2154607fb0 Bump version: 1.5.0.37-d08a → 1.6.0
Change-Id: I2248595ca11f4d808d38a9e25e7c3d3b64134427
2020-08-13 12:26:20 +02:00
Pau Espin Pedrol
d08a15b343 gtp: queue_test: Fix printf gcc warn under ARM
queue_test.c:39:3: warning: format '%ld' expects argument of type
'long int', but argument 9 has type 'unsigned int' [-Wformat=]

Change-Id: Ie9530cdd191386ca3f6c336684f81c4582c4d962
2020-07-07 16:03:37 +02:00
Harald Welte
4e37fb356a example config: use RFC1918 addresses for GGSN pools
It's 172.16, not 176.16.

Change-Id: I2d83ee747e8987f10c4960d42f3c3f2a723e3f4c
2020-05-23 11:07:34 +02:00
Oliver Smith
6a8a389c47 Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
Change-Id: Ie9cc3da87dea413408c82b721875e89735a47fcf
2020-05-22 13:39:41 +02:00
Oliver Smith
569e46cbf9 contrib: integrate RPM spec
Remove OpenSUSE bug report link, set version to @VERSION@, make it build
with CentOS 8 etc.

Related: OS#4550
Change-Id: Iba04d5c7b9beee80baca83063f9cb2cd533a0003
2020-05-19 15:25:36 +02:00
Oliver Smith
91d9410157 contrib: import RPM spec
Copy the RPM spec file from:
https://build.opensuse.org/project/show/home:mnhauke:osmocom:nightly

Related: OS#4550
Change-Id: I50a93d2cde429974b059bafd38befa9a189c0e8a
2020-05-15 13:52:17 +02:00
Oliver Smith
065ddb6416 osmo-ggsn.spec.in: remove
Remove old osmo-ggsn.spec.in file from 2017 in favor of the one imported
from mnhauke, which is currently used in openSUSE nightly builds (will
be added in a follow-up commit).

Related: OS#4550
Change-Id: I24794564f0d4d85d3955ab08f4e4c3c05f53a0cd
2020-05-15 13:52:02 +02:00
Philipp Maier
53244a2132 debug: use LOGL_NOTICE instead of LOGL_DEBUG
In debug.c the log category DICMP6 uses LOGL_DEBUG as default. This is
way to verbose, lets use LOGL_NOTICE instead.

Change-Id: I4c6a9165114d1240e7e2cfa98d30d571a3f4e9d2
Related: OS#2577
2020-05-12 11:32:06 +00:00
Dmitri Kalashnik
db98f309a9 sgsnemu: use real tun device name after the device is up.
The device name option could be empty, using it without checking
would crash sgsnemu. Using the real device is better anyway.

Change-Id: Ic3934281bfc2e433323e4ab72cf5be2cbd1c962a
2020-04-28 13:14:52 +04:00
78 changed files with 9988 additions and 3733 deletions

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
open_collective: osmocom

10
.gitignore vendored
View File

@@ -16,7 +16,6 @@ install-sh
libtool
ltmain.sh
missing
osmo-ggsn.spec
stamp-h1
INSTALL
m4/
@@ -28,7 +27,7 @@ osmo-ggsn-*.tar*
# debian
debian/osmo-ggsn/
debian/*.debhelper
debian/libgtp1
debian/libgtp*/
debian/osmo-ggsn-dbg
debian/*.log
debian/autoreconf.*
@@ -80,3 +79,10 @@ 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
/debian/gtp-echo-responder-dbg/
/debian/gtp-echo-responder/
/debian/osmo-ggsn-doc/
/utils/gtp-echo-responder

View File

@@ -1,5 +1,15 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = lib gtp ggsn sgsnemu doc contrib tests
SUBDIRS = \
include \
lib \
gtp \
ggsn \
sgsnemu \
doc \
contrib \
utils \
tests \
$(NULL)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libgtp.pc
@@ -10,7 +20,14 @@ $(top_srcdir)/.version:
dist-hook:
echo $(VERSION) > $(distdir)/.tarball-version
EXTRA_DIST = git-version-gen .version README.md README.FreeBSD README.MacOSX
EXTRA_DIST = \
.version \
README.FreeBSD \
README.MacOSX \
README.md \
debian \
git-version-gen \
$(NULL)
AM_DISTCHECK_CONFIGURE_FLAGS = \
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)

169
README.md
View File

@@ -5,57 +5,71 @@ 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
--------------
You can clone from the official osmo-ggsn.git repository using
git clone git://git.osmocom.org/osmo-ggsn.git
git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn
There is a cgit interface at http://git.osmocom.org/osmo-ggsn/
There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn>
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
We use 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
```

View File

@@ -1,9 +1,9 @@
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
# according to https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
# In short:
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
# LIBVERSION=c:r:a
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0.
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
#library what description / commit summary line

View File

@@ -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])])
@@ -19,7 +21,7 @@ AC_PROG_AWK
AC_PROG_CPP
LT_INIT
dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang
dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang
AS_CASE(["$LD"],[*clang*],
[AS_CASE(["${host_os}"],
[*linux*],[archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'])])
@@ -69,7 +71,7 @@ AC_ARG_ENABLE([gtp-linux],
[enable_gtp_linux="$enableval"], [enable_gtp_linux="no"])
AS_IF([test "x$enable_gtp_linux" = "xyes"], [
PKG_CHECK_MODULES([LIBGTPNL], [libgtpnl >= 1.2.0])
PKG_CHECK_MODULES([LIBGTPNL], [libgtpnl >= 1.3.0])
])
AM_CONDITIONAL([ENABLE_GTP_KERNEL], [test "$enable_gtp_linux" = "yes"])
@@ -152,9 +154,9 @@ adl_FUNC_GETOPT_LONG
AM_INIT_AUTOMAKE([foreign])
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.10.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.10.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.10.0)
AC_ARG_ENABLE(sanitize,
[AS_HELP_STRING(
@@ -255,15 +257,18 @@ AC_CONFIG_FILES([Makefile
lib/Makefile
intl/Makefile
po/Makefile
utils/Makefile
sgsnemu/Makefile
doc/manuals/Makefile
doc/manuals/Makefile
contrib/Makefile
contrib/systemd/Makefile
tests/Makefile
tests/lib/Makefile
tests/gtp/Makefile
libgtp.pc
osmo-ggsn.spec])
include/Makefile
include/osmocom/Makefile
include/osmocom/gtp/Makefile
libgtp.pc])
AC_OUTPUT
echo "

View File

@@ -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
@@ -54,11 +53,11 @@ cd "$base"
autoreconf --install --force
./configure --enable-sanitize --enable-werror $GTP $CONFIG
$MAKE $PARALLEL_MAKE
DISTCHECK_CONFIGURE_FLAGS="$CONFIG" $MAKE distcheck
DISTCHECK_CONFIGURE_FLAGS="$CONFIG" $MAKE $PARALLEL_MAKE distcheck
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
make -C "$base/doc/manuals" publish
fi
$MAKE maintainer-clean
$MAKE $PARALLEL_MAKE maintainer-clean
osmo-clean-workspace.sh

View File

@@ -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

View File

@@ -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

254
debian/changelog vendored
View File

@@ -1,3 +1,257 @@
osmo-ggsn (1.12.0) unstable; urgency=medium
[ Daniel Willmann ]
* libgtp: Remove defines for reserved causes in gtp.h
[ Pau Espin Pedrol ]
* pco: Improve IPCP spec reference documentation
[ Oliver Smith ]
* Fix a typo
* gtp_new: deduplicate create_and_bind_socket code
* kernel-gtp: support IPv6 on outer layer
* kernel-gtp: support IPv6 on inner layer
* Revert "kernel-gtp: support IPv6 on outer layer"
* Cosmetic: Makefile.am: make SUBDIRS diff friendly
* Cosmetic: AM_CFLAGS: make diff friendly
* Cosmetic: {lib,gtp}/Makefile.am: diff friendly
* lib/gtp-kernel.c: initialize ret with 0
* lib/gtp-kernel.c: check rc of in46a_from_eua
* doc: fix typo ndoe -> node
* Add clear error for kernel not supporting IPv6
* contrib: remove rpm spec file
* libgtp: move includes to osmocom/include/gtp
* gtp/gsn_internal.h: new file
* gtp/gtp.c: move gtp_create_context_resp down
* gtp: remove unused conversion functions
* gtp: move conversion functions up
* gtp/gtp_internal.h: new file
* ggsn/ggsn_vty: create state-dir
* doc: set state-dir to /var/lib/osmocom/osmo-ggsn
* contrib/systemd: run as osmocom user
* Use uniform log format for default config files
* {contrib,debian}/osmo-ggsn.init: remove
[ Harald Welte ]
* Add funding link to github mirror
* README.md: Improve markdown formatting
* README.md: Add Forum + Issue Tracker sections
* README.md: Major overhaul
[ Vadim Yanitskiy ]
* README.md: cosmetic: fix a typo
-- Oliver Smith <osmith@sysmocom.de> Wed, 24 Jul 2024 15:13:31 +0200
osmo-ggsn (1.11.0) unstable; urgency=medium
[ Daniel Willmann ]
* 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 ]
* tests: in46a_test: Make coverity happy when calling in46a_from_eua
* vty: Fix cmd 'no echo-interval' doing nothing
* libgtp: Fix ggsn crash if pdp alloc array is full (PDP_MAX)
* libgtp: Define retransmit QUEUE_SIZE relative to PDP_MAX (increase)
* gtp: Use switch statement in gtp_create_pdp_ind()
* gtp: Log detection of rx duplicate
* gtp: Small log improvements in gtp_create_pdp_ind()
* gtp: Specify retrans queue name & seqnum in log lines
* gtp: Log retrans queue register&free entries
* gtp: Fix typo in comment
* pco.h: Fix typo in reference to spec
[ Vadim Yanitskiy ]
* tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS'
[ Harald Welte ]
* update git URLs (git -> https; gitea)
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 28 Jun 2022 17:48:22 +0200
osmo-ggsn (1.8.0) unstable; urgency=medium
[ Oliver Smith ]
* doc/examples/Makefile.am: add sgsnemu.conf
* doc/examples/osmo-ggsn-kernel-gtp.cfg: new file
* doc/manuals: describe GTP-U kernel module
* gitignore: add ggsn_vty_reference.xml
[ Harald Welte ]
* Don't install osmo-ggsn-kernel-gtp.cfg to /etc/osmocom/
* Don't install sgsnemu.conf to /etc/osmocom/
* ggsn: Reject PDP CTX ACT for static IP addresses
* vty: Inform user that static IP addresses are not supported
[ Pau Espin Pedrol ]
* gtp: Update teic_confirmed only on resp success
* gtp: Rework parsing logic of UpdatePdpCtxResponse
* ggsn: Improve logging on incoming DL data packets
* gtp: Improve logging of failing pdp ctx resolution from TEI/TID
* cosmetic: gtpie.c: Fix trailing whitespace
* gtp: constify pointer arg
* gtp: Support tx/rx RAN Information Relay message
* ggsn: Log tun fd write errors
* ggsn: Fix heap-use-after-free during Recovery without associated PDP
* cosmetic: configure.ac: Fix tabulation in line
* Introduce program gtp-echo-responder
* gtp_echo_responder: report invalid chars present in node-feautres cmdline arg as error
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 16 Nov 2021 13:49:16 +0100
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 ]
* cosmetic: Fix comment typo
* netns: Improve error checking
* sgsnemu: cmdline: Drop unused function cmdline_parser_params_create()
* sgsnemu: Pass array of in64_addr to in46a_from_eua()
* sgsnemu: Rename sgsnemu's libgtp cb_conf
* sgsnemu: Set its default loglevel category to INFO
* Move icmpv6 and checksum files from ggsn/ dir to lib/
* netdev_addaddr6: Use prefixlen arg
* sgsnemu: Avoid adding extra autogenerated local link ipv6 addr to tun iface
* sgsnemu: Fix ping transmitted statistics output
* cosmetic: icmpv6.c: fix typo in comment
* icmpv6.c: Mark internal function as static
* sgsnemu: Get rid of duplicated options.destaddr
* sgsnemu: Get rid of duplicated options.net
* sgsnemu: tun_addaddr: Don't set local addr as dstaddr
* icmpv6.c: Move code generating ipv6 hdr to its own function
* Rename netdev_*route to end in route4
* sgsnemu: Fix build/run against linux < 4.11 (no sysctl addr_gen_mode support)
* sgsnemu: Handle IPv6 SLAAC in tun iface manually
* sgsnemu: Implement ping on IPv6 APNs
* sgsnemu: Fix assumption ipv6 Interface-Identifier of public addr == announced Prefix
* gtp: queue_test: Fix printf gcc warn under ARM
[ Andreas Schultz ]
* add Linux network namespace support for TUN device
[ Vadim Yanitskiy ]
* lib/netns: fix open_ns(): return fd from open()
[ Philipp Maier ]
* doc: do not use random ip address for dns in default conf
* doc: use 127.0.0.2 instead of 127.0.0.6 as bind ip.
* debug: use LOGL_NOTICE instead of LOGL_DEBUG
[ Eric ]
* configure.ac: fix libtool issue with clang and sanitizer
[ Harald Welte ]
* lib/netns.c: Add comments to the code, including doxygen API docs
* lib/netns: OSMO_ASSERT() if user doesn't call init_netns()
* lib/netns: Fix up error paths
* example config: use RFC1918 addresses for GGSN pools
[ Dmitri Kalashnik ]
* sgsnemu: use real tun device name after the device is up.
[ Oliver Smith ]
* osmo-ggsn.spec.in: remove
* contrib: import RPM spec
* contrib: integrate RPM spec
* Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
-- Harald Welte <laforge@osmocom.org> Thu, 13 Aug 2020 12:26:20 +0200
osmo-ggsn (1.5.0) unstable; urgency=medium
[ Jan Engelhardt ]

2
debian/compat vendored
View File

@@ -1 +1 @@
9
10

36
debian/control vendored
View File

@@ -1,17 +1,18 @@
Source: osmo-ggsn
Maintainer: Harald Welte <laforge@gnumonks.org>
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.1.0),
osmo-gsm-manuals-dev
libosmocore-dev (>= 1.10.0),
osmo-gsm-manuals-dev (>= 1.6.0),
libgtpnl-dev (>= 1.3.0)
Standards-Version: 3.9.6
Vcs-Browser: http://git.osmocom.org/osmo-ggsn/
Vcs-Git: git://git.osmocom.org/osmo-ggsn
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn
Homepage: https://projects.osmocom.org/projects/openggsn
Package: osmo-ggsn
@@ -23,7 +24,7 @@ Description: Osmocom Gateway GPRS Support Node (GGSN)
operators as the interface between the Internet and the rest of the
mobile network infrastructure.
Package: libgtp6
Package: libgtp10
Architecture: any
Multi-Arch: same
Section: libs
@@ -37,12 +38,18 @@ Description: library implementing the GTP protocol between SGSN and GGSN
This library is part of OsmoGGSN and implements the GTP protocol between
SGSN (Serving GPRS support node) and GGSN.
Package: gtp-echo-responder
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends}
Description: Small program answering GTP ECHO Request with GTP ECHO Response
Package: libgtp-dev
Architecture: any
Multi-Arch: same
Section: libdevel
Depends: ${misc:Depends},
libgtp6 (= ${binary:Version})
libgtp10 (= ${binary:Version})
Description: Development files for libgtp
OsmoGGSN is a Gateway GPRS Support Node (GGSN). It is used by mobile
operators as the interface between the Internet and the rest of the
@@ -55,18 +62,27 @@ Package: osmo-ggsn-dbg
Section: debug
Architecture: any
Priority: extra
Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp6 (= ${binary:Version}), osmo-ggsn (= ${binary:Version})
Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp10 (= ${binary:Version}), osmo-ggsn (= ${binary:Version})
Multi-Arch: same
Description: Debug symbols for OsmoGGSN
OsmoGGSN is a Gateway GPRS Support Node (GGSN). It is used by mobile
operators as the interface between the Internet and the rest of the
mobile network infrastructure.
Package: gtp-echo-responder-dbg
Section: debug
Architecture: any
Priority: extra
Depends: ${shlibs:Depends}, ${misc:Depends}, gtp-echo-responder (= ${binary:Version})
Multi-Arch: same
Description: Debug symbols for gtp-echo-responder
Small program answering GTP ECHO Request with GTP ECHO Response.
Package: libgtp-dbg
Section: debug
Architecture: any
Priority: extra
Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp6 (= ${binary:Version})
Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp10 (= ${binary:Version})
Multi-Arch: same
Description: Debug symbols for OsmoGGSN
OsmoGGSN is a Gateway GPRS Support Node (GGSN). It is used by mobile

5
debian/copyright vendored
View File

@@ -16,6 +16,11 @@ Files: lib/getopt.c
Copyright: 1987-2001 Free Software Foundation, Inc.
License: LGPL-2.1+
Files: utils/gtp_echo_responder.c
utils/gtp_echo_responder_test.py
Copyright: 2021 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
License: MIT
Files: debian/*
Copyright: 2010-2017 Harald Welte <laforge@gnumonks.org>
2016 Ruben Undheim <ruben.undheim@gmail.com>

1
debian/gtp-echo-responder.install vendored Normal file
View File

@@ -0,0 +1 @@
/usr/bin/gtp-echo-responder

2
debian/libgtp6.shlibs vendored Normal file
View File

@@ -0,0 +1,2 @@
# Most recent version of the package that added new symbols (OS#5318)
libgtp 6 libgtp6 (>= 1.8.0)

View File

@@ -1,2 +1,3 @@
doc/examples/osmo-ggsn.cfg
doc/examples/osmo-ggsn-kernel-gtp.cfg
doc/examples/sgsnemu.conf

163
debian/osmo-ggsn.init vendored
View File

@@ -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
:

39
debian/postinst vendored Executable file
View File

@@ -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#

7
debian/rules vendored
View File

@@ -16,10 +16,13 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all
override_dh_strip:
dh_strip -posmo-ggsn --dbg-package=osmo-ggsn-dbg
dh_strip -plibgtp6 --dbg-package=libgtp-dbg
dh_strip -plibgtp10 --dbg-package=libgtp-dbg
override_dh_auto_configure:
dh_auto_configure -- --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:

View File

@@ -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 \

View File

@@ -0,0 +1,53 @@
!
! OpenGGSN (0.94.1-adac) configuration saved from vty
!!
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
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 /var/lib/osmocom/osmo-ggsn
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

View File

@@ -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,16 +38,16 @@ 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
tun-device tun4
type-support v4
ip prefix dynamic 176.16.222.0/24
ip prefix dynamic 172.16.222.0/24
ip dns 0 8.8.8.8
ip dns 1 8.8.4.4
ip ifconfig 176.16.222.0/24
ip ifconfig 172.16.222.0/24
no shutdown
apn inet6
gtpu-mode tun
@@ -60,10 +62,10 @@ ggsn ggsn0
gtpu-mode tun
tun-device tun46
type-support v4v6
ip prefix dynamic 176.16.46.0/24
ip prefix dynamic 172.16.46.0/24
ip dns 0 8.8.8.8
ip dns 1 8.8.4.4
ip ifconfig 176.16.46.0/24
ip ifconfig 172.16.46.0/24
ipv6 prefix dynamic 2001:780:44:2100:0:0:0:0/56
ipv6 dns 0 2001:4860:4860::8888
ipv6 dns 1 2001:4860:4860::8844

View File

@@ -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

View File

@@ -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

View File

@@ -80,3 +80,52 @@ 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, 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
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
----

View File

@@ -20,6 +20,8 @@ include::{srcdir}/chapters/configuration.adoc[]
include::./common/chapters/control_if.adoc[]
include::./common/chapters/vty_cpu_sched.adoc[]
include::./common/chapters/port_numbers.adoc[]
include::./common/chapters/bibliography.adoc[]

File diff suppressed because it is too large Load Diff

View File

@@ -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)

View File

@@ -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,8 +195,8 @@ int apn_start(struct apn_ctx *apn)
}
LOGPAPN(LOGL_INFO, apn, "Opened TUN device %s\n", apn->tun.tun->devname);
/* Register with libosmcoore */
osmo_fd_setup(&apn->tun.fd, apn->tun.tun->fd, BSC_FD_READ, ggsn_tun_fd_cb, apn, 0);
/* 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);
/* Set TUN library callback */
@@ -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
@@ -467,9 +464,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));
@@ -532,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;
}
@@ -589,7 +591,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 +624,41 @@ 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])));
}
return 0;
}
@@ -704,7 +730,7 @@ static int ggsn_tun_fd_cb(struct osmo_fd *fd, unsigned int what)
{
struct apn_ctx *apn = fd->data;
OSMO_ASSERT(what & BSC_FD_READ);
OSMO_ASSERT(what & OSMO_FD_READ);
return tun_decaps(apn->tun.tun);
}
@@ -715,7 +741,7 @@ static int ggsn_gtp_fd_cb(struct osmo_fd *fd, unsigned int what)
struct ggsn_ctx *ggsn = fd->data;
int rc;
OSMO_ASSERT(what & BSC_FD_READ);
OSMO_ASSERT(what & OSMO_FD_READ);
switch (fd->priv_nr) {
case 0:
@@ -809,15 +835,15 @@ int ggsn_start(struct ggsn_ctx *ggsn)
ggsn->gsn->gsnu = ggsn->cfg.gtpu_addr.v4;
/* Register File Descriptors */
osmo_fd_setup(&ggsn->gtp_fd0, ggsn->gsn->fd0, BSC_FD_READ, ggsn_gtp_fd_cb, ggsn, 0);
osmo_fd_setup(&ggsn->gtp_fd0, ggsn->gsn->fd0, OSMO_FD_READ, ggsn_gtp_fd_cb, ggsn, 0);
rc = osmo_fd_register(&ggsn->gtp_fd0);
OSMO_ASSERT(rc == 0);
osmo_fd_setup(&ggsn->gtp_fd1c, ggsn->gsn->fd1c, BSC_FD_READ, ggsn_gtp_fd_cb, ggsn, 1);
osmo_fd_setup(&ggsn->gtp_fd1c, ggsn->gsn->fd1c, OSMO_FD_READ, ggsn_gtp_fd_cb, ggsn, 1);
rc = osmo_fd_register(&ggsn->gtp_fd1c);
OSMO_ASSERT(rc == 0);
osmo_fd_setup(&ggsn->gtp_fd1u, ggsn->gsn->fd1u, BSC_FD_READ, ggsn_gtp_fd_cb, ggsn, 2);
osmo_fd_setup(&ggsn->gtp_fd1u, ggsn->gsn->fd1u, OSMO_FD_READ, ggsn_gtp_fd_cb, ggsn, 2);
rc = osmo_fd_register(&ggsn->gtp_fd1u);
OSMO_ASSERT(rc == 0);

View File

@@ -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);
@@ -167,6 +169,3 @@ void ggsn_close_one_pdp(struct pdp_t *pdp);
LOGP(DGGSN, level, "GGSN(%s): " fmt, (ggsn)->cfg.name, ## args)
#define LOGPPDP(level, pdp, fmt, args...) LOGPDPX(DGGSN, level, pdp, fmt, ## args)
#define LOGTUN(level, tun, fmt, args...) \
LOGP(DTUN, level, "TUN(%s): " fmt, (tun)->devname, ## args)

View File

@@ -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>
@@ -45,6 +46,7 @@
#include <osmocom/vty/ports.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/misc.h>
#include <osmocom/vty/cpu_sched_vty.h>
#include "ggsn.h"
@@ -59,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)
{
@@ -70,6 +77,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);
@@ -95,17 +113,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 }
};
@@ -114,6 +164,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();
@@ -158,6 +211,7 @@ int main(int argc, char **argv)
osmo_stats_vty_add_cmds();
ggsn_vty_init();
ctrl_vty_init(tall_ggsn_ctx);
osmo_cpu_sched_vty_init(tall_ggsn_ctx);
handle_options(argc, argv);
@@ -169,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);

View File

@@ -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;
@@ -389,10 +398,9 @@ DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
NO_STR "Send an echo request to this static GGSN every interval.\n")
{
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
int prev_interval = ggsn->cfg.echo_interval;
struct sgsn_peer *sgsn;
if (prev_interval == ggsn->cfg.echo_interval)
if (ggsn->cfg.echo_interval == 0)
return CMD_SUCCESS;
ggsn->cfg.echo_interval = 0;
@@ -533,9 +541,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 +577,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;
@@ -677,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;
@@ -694,11 +706,15 @@ 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;
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;
@@ -788,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)
@@ -805,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);
}
@@ -894,11 +908,16 @@ DEFUN(show_pdpctx_imsi, show_pdpctx_imsi_cmd,
return CMD_WARNING;
}
imsi = strtoull(argv[1], NULL, 10);
if (strlen(argv[1]) < 6 || strlen(argv[1]) > 15) {
vty_out(vty, "%% Invalid IMSI '%s'%s", argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
imsi = gtp_imsi_str2gtp(argv[1]);
if (argc > 2) {
nsapi = atoi(argv[2]);
if (gtp_pdp_getimsi(ggsn->gsn, &pdp, imsi, nsapi)) {
if (!gtp_pdp_getimsi(ggsn->gsn, &pdp, imsi, nsapi)) {
show_one_pdp(vty, pdp);
num_found++;
}
@@ -1101,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);

View File

@@ -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)
{

View File

@@ -2,9 +2,9 @@
#include <stdint.h>
#include "../gtp/pdp.h"
#include <osmocom/gtp/pdp.h>
/* 3GPP TS 24.008 10.6.5.3 */
/* 3GPP TS 24.008 10.5.6.3 */
enum pco_protocols {
PCO_P_LCP = 0xC021,
PCO_P_PAP = 0xC023,
@@ -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 {

View File

@@ -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)
{
@@ -116,6 +116,7 @@ static unsigned int sgsn_peer_drop_all_pdp_except(struct sgsn_peer *sgsn, struct
{
unsigned int num = 0;
char buf[INET_ADDRSTRLEN];
unsigned int count = llist_count(&sgsn->pdp_list);
inet_ntop(AF_INET, &sgsn->addr, buf, sizeof(buf));
@@ -125,10 +126,17 @@ static unsigned int sgsn_peer_drop_all_pdp_except(struct sgsn_peer *sgsn, struct
continue;
ggsn_close_one_pdp(pdp->lib);
num++;
if (num == count) {
/* Note: if except is NULL, all pdp contexts are freed and sgsn
* is most probably already freed at this point.
* As a result, last access to sgsn->pdp_list before exiting
* loop would access already freed memory. Avoid it by exiting
* the loop without the last check, and make sure sgsn is not
* accessed after this loop. */
break;
}
}
/* Note: if except is NULL, all pdp contexts are freed and sgsn is
already freed at this point */
LOGP(DGGSN, LOGL_INFO, "SGSN(%s) Dropped %u PDP contexts\n", buf, num);
return num;

View File

@@ -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;

View File

@@ -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=6:0:0
LIBVERSION=10:0:0
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)

578
gtp/gsn.c Normal file
View File

@@ -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;
}

3
gtp/gsn_internal.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
void gtp_queue_timer_start(struct gsn_t *gsn);

1109
gtp/gtp.c

File diff suppressed because it is too large Load Diff

3
gtp/gtp_internal.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
uint64_t gtp_imsi_str2gtp(const char *str);

View File

@@ -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
@@ -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

View File

@@ -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"
@@ -338,9 +340,7 @@ int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi)
int gtp_pdp_getimsi(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi)
{
return gtp_pdp_tidget(gsn, pdp,
(imsi & 0x0fffffffffffffffull) +
((uint64_t) nsapi << 60));
return gtp_pdp_tidget(gsn, pdp, pdp_gettid(imsi, nsapi));
}

View File

@@ -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 */

View File

@@ -19,11 +19,11 @@
#include <osmocom/core/linuxlist.h>
#include "gtp.h"
#include <osmocom/gtp/gtp.h>
#define QUEUE_DEBUG 0 /* Print debug information */
#define QUEUE_SIZE 1024 /* Size of retransmission queue */
#define QUEUE_SIZE (PDP_MAX*2) /* Size of retransmission queue */
#define QUEUE_HASH_SIZE 65536 /* Size of hash table (2^16) */
struct qmsg_t { /* Holder for queued packets */

3
include/Makefile.am Normal file
View File

@@ -0,0 +1,3 @@
SUBDIRS = \
osmocom \
$(NULL)

View File

@@ -0,0 +1,3 @@
SUBDIRS = \
gtp \
$(NULL)

View File

@@ -0,0 +1,8 @@
libgtp_HEADERS = \
gsn.h \
gtp.h \
gtpie.h \
pdp.h \
$(NULL)
libgtpdir = $(includedir)/osmocom/gtp

178
include/osmocom/gtp/gsn.h Normal file
View File

@@ -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 */

View File

@@ -13,13 +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
@@ -31,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 */
@@ -58,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 */
@@ -85,6 +80,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 */
@@ -103,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 */
@@ -138,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;
@@ -230,104 +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_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);
@@ -343,103 +257,20 @@ 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_set_cb_data_ind(struct gsn_t *gsn,
int (*cb_data_ind) (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_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_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);
#endif /* !_GTP_H */

View File

@@ -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)

View File

@@ -29,7 +29,7 @@ static const struct log_info_cat default_categories[] = {
[DICMP6] = {
.name = "DICMP6",
.description = "ICMPv6",
.enabled = 1, .loglevel = LOGL_DEBUG,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
};

View File

@@ -18,22 +18,18 @@
#include <libgtpnl/gtp.h>
#include <libgtpnl/gtpnl.h>
#include <libmnl/libmnl.h>
#include <errno.h>
#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 <libgtpnl/gtp.h>
#include <libgtpnl/gtpnl.h>
#include <libmnl/libmnl.h>
#include "gtp-kernel.h"
@@ -109,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;
}

View File

@@ -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"

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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.

View File

@@ -318,7 +318,14 @@ int tun_decaps(struct tun_t *this)
int tun_encaps(struct tun_t *tun, void *pack, unsigned len)
{
return write(tun->fd, pack, len);
int rc;
rc = write(tun->fd, pack, len);
if (rc < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "TUN(%s): write() failed", tun->devname);
} else if (rc < len) {
LOGTUN(LOGL_ERROR, tun, "short write() %d < %u\n", rc, len);
}
return rc;
}
int tun_runscript(struct tun_t *tun, char *script)

View File

@@ -59,4 +59,7 @@ extern int tun_runscript(struct tun_t *tun, char *script);
int tun_ip_local_get(const struct tun_t *tun, struct in46_prefix *prefix_list,
size_t prefix_size, int flags);
#define LOGTUN(level, tun, fmt, args...) \
LOGP(DTUN, level, "TUN(%s): " fmt, (tun)->devname, ## args)
#endif /* !_TUN_H */

View File

@@ -9,7 +9,7 @@
*
*/
#include "../gtp/pdp.h"
#include <osmocom/gtp/pdp.h>
#include "ippool.h"
#include "in46_addr.h"

View File

@@ -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}/

View File

@@ -1,90 +0,0 @@
Summary: Osmocom Gateway GPRS Support Node (GGSN)
Name: @PACKAGE@
Version: @VERSION@
Release: 1
URL: https://osmocom.org/projects/openggsn
Source0: http://prdownloads.sourceforge.net/ggsn/%{name}-%{version}.tar.gz
License: GPL
Group: System Environment/Daemons
BuildRoot: %{_tmppath}/%{name}-root
%description
OsmoGGSN is a Gateway GPRS Support Node (GGSN). It is used by mobile
operators as the interface between the Internet and the rest of the
mobile network infrastructure. The project also provides an SGSN
emulator suitable for GPRS core network testing.
%prep
%setup -q
%build
./configure --prefix=/usr --enable-static-exec
make
%install
make install prefix=$RPM_BUILD_ROOT/usr
strip $RPM_BUILD_ROOT/usr/bin/osmo-ggsn
strip $RPM_BUILD_ROOT/usr/bin/sgsnemu
#Copy osmo-ggsn init script in place
mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
install -m755 examples/osmo-ggsn.init \
$RPM_BUILD_ROOT/etc/rc.d/init.d/osmo-ggsn
#Copy osmo-ggsn.conf in place
install -m755 examples/osmo-ggsn.cfg \
$RPM_BUILD_ROOT/etc/osmo-ggsn.cfg
#Copy gsn_restart file in place
mkdir -p $RPM_BUILD_ROOT/var/lib/osmo-ggsn
echo "0" > $RPM_BUILD_ROOT/var/lib/osmo-ggsn/gsn_restart
#Clean up unwanted library files
rm -rf $RPM_BUILD_ROOT/usr/include/*
rm -rf $RPM_BUILD_ROOT/usr/lib/*
%clean
rm -rf $RPM_BUILD_ROOT
make clean
%post
/sbin/chkconfig --add osmo-ggsn
%files
%defattr(-,root,root)
/usr/bin/osmo-ggsn
/usr/bin/sgsnemu
/etc/rc.d/init.d/osmo-ggsn
%dir /var/lib/osmo-ggsn
/var/lib/osmo-ggsn/gsn_restart
%doc AUTHORS COPYING INSTALL NEWS README.md
%doc examples/osmo-ggsn.conf
%doc examples/sgsnemu.conf
%doc examples/osmo-ggsn.init
%doc examples/firewall
%doc /usr/man/man8/osmo-ggsn.8.gz
%doc /usr/man/man8/sgsnemu.8.gz
%config /etc/osmo-ggsn.cfg
#/usr/lib/libgtp.a
#/usr/lib/libgtp.la
#/usr/lib/libgtp.so
#/usr/lib/libgtp.so.0
#/usr/lib/libgtp.so.0.0.0
%changelog
* Mon Jun 30 2017 <laforge@gnumonks.org>
- Update to OsmoGGSN
* Mon Jun 30 2003 <jj@openggsn.org>
- Initial build.

View File

@@ -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

View File

@@ -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 */
@@ -492,27 +494,12 @@ static int process_options(int argc, char **argv)
}
/* imsi */
if (strlen(args_info.imsi_arg) != 15) {
if (strlen(args_info.imsi_arg) < 6 || strlen(args_info.imsi_arg) > 15) {
printf("Invalid IMSI\n");
return -1;
}
options.imsi = 0xf000000000000000ull;
options.imsi |= ((uint64_t) (args_info.imsi_arg[0] - 48));
options.imsi |= ((uint64_t) (args_info.imsi_arg[1] - 48)) << 4;
options.imsi |= ((uint64_t) (args_info.imsi_arg[2] - 48)) << 8;
options.imsi |= ((uint64_t) (args_info.imsi_arg[3] - 48)) << 12;
options.imsi |= ((uint64_t) (args_info.imsi_arg[4] - 48)) << 16;
options.imsi |= ((uint64_t) (args_info.imsi_arg[5] - 48)) << 20;
options.imsi |= ((uint64_t) (args_info.imsi_arg[6] - 48)) << 24;
options.imsi |= ((uint64_t) (args_info.imsi_arg[7] - 48)) << 28;
options.imsi |= ((uint64_t) (args_info.imsi_arg[8] - 48)) << 32;
options.imsi |= ((uint64_t) (args_info.imsi_arg[9] - 48)) << 36;
options.imsi |= ((uint64_t) (args_info.imsi_arg[10] - 48)) << 40;
options.imsi |= ((uint64_t) (args_info.imsi_arg[11] - 48)) << 44;
options.imsi |= ((uint64_t) (args_info.imsi_arg[12] - 48)) << 48;
options.imsi |= ((uint64_t) (args_info.imsi_arg[13] - 48)) << 52;
options.imsi |= ((uint64_t) (args_info.imsi_arg[14] - 48)) << 56;
options.imsi = gtp_imsi_str2gtp(args_info.imsi_arg);
printf("IMSI is: %s (%#08llx)\n",
args_info.imsi_arg, options.imsi);
@@ -1928,11 +1915,11 @@ int main(int argc, char **argv)
we don't need it. Don't exit on error since this sysctl is
only available starting with linux 4.11. */
snprintf(buf, sizeof(buf), "%u", IN6_ADDR_GEN_MODE_NONE);
if (proc_ipv6_conf_write(options.tun_dev_name, "addr_gen_mode", buf) < 0) {
if (proc_ipv6_conf_write(tun->devname, "addr_gen_mode", buf) < 0) {
SYS_ERR(DSGSN, LOGL_ERROR, errno,
"Failed to disable addr_gen_mode on %s, an extra link-local "
"ip address will appear on the tun device.\n",
options.tun_dev_name);
tun->devname);
}
#endif
@@ -1940,9 +1927,9 @@ int main(int argc, char **argv)
if (tun->fd > maxfd)
maxfd = tun->fd;
if (proc_ipv6_conf_write(options.tun_dev_name, "accept_ra", "0") < 0) {
if (proc_ipv6_conf_write(tun->devname, "accept_ra", "0") < 0) {
SYS_ERR(DSGSN, LOGL_ERROR, 0,
"Failed to disable IPv6 SLAAC on %s\n", options.tun_dev_name);
"Failed to disable IPv6 SLAAC on %s\n", tun->devname);
exit(1);
}
}

View File

@@ -1,11 +1,16 @@
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 \
queue_test.ok \
$(NULL)
noinst_PROGRAMS = \
check_PROGRAMS = \
gtpie_test \
queue_test \
$(NULL)

View File

@@ -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];
@@ -113,7 +114,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));

View File

@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include <arpa/inet.h>
#include <osmocom/core/utils.h>
@@ -27,7 +28,7 @@ static void queue_print(struct queue_t *queue, char* str)
OSMO_ASSERT(memcmp(&qmsg_zero, &queue->qmsga[n], sizeof(qmsg_zero)) == 0);
continue;
}
printf("%d\t%d\t%d\t%d\t%d\t%d\t%u\t%ld\n",
printf("%d\t%d\t%d\t%d\t%d\t%d\t%u\t%" PRIuPTR "\n",
n,
queue->qmsga[n].seq,
queue->qmsga[n].next,
@@ -35,7 +36,7 @@ static void queue_print(struct queue_t *queue, char* str)
(int)queue->qmsga[n].timeout,
queue->qmsga[n].retrans,
queue->qmsga[n].type,
((uintptr_t)queue->qmsga[n].cbp & 0xFFFFFFFF)
(uintptr_t)queue->qmsga[n].cbp
);
}
printf("======================================================\n");
@@ -222,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();

File diff suppressed because it is too large Load Diff

View File

@@ -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 \
@@ -7,7 +12,7 @@ EXTRA_DIST = ippool_test.ok \
in46a_test.ok \
in46a_v6_test.ok
noinst_PROGRAMS = ippool_test in46a_test
check_PROGRAMS = ippool_test in46a_test
ippool_test_SOURCES = \
ippool_test.c \

View File

@@ -146,7 +146,7 @@ static void test_in46a_to_eua(void)
static void test_in46a_from_eua(void)
{
struct in46_addr ia;
struct in46_addr ia[2];
struct ul66_t eua;
const uint8_t v4_unspec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v4 };
const uint8_t v4_spec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v4, 1,2,3,4 };
@@ -155,35 +155,35 @@ static void test_in46a_from_eua(void)
printf("Testing in46a_from_eua() with IPv4 addresses\n");
/* default: v4 unspec */
OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 1);
OSMO_ASSERT(ia.len == 4);
OSMO_ASSERT(ia.v4.s_addr == 0);
OSMO_ASSERT(in46a_from_eua(&eua, ia) == 1);
OSMO_ASSERT(ia[0].len == 4);
OSMO_ASSERT(ia[0].v4.s_addr == 0);
/* invalid */
eua.v[0] = 0x23;
eua.v[1] = PDP_EUA_TYPE_v4;
eua.l = 6;
OSMO_ASSERT(in46a_from_eua(&eua, &ia) < 0);
OSMO_ASSERT(in46a_from_eua(&eua, ia) < 0);
/* invalid */
eua.v[0] = PDP_EUA_ORG_IETF;
eua.v[1] = 0x23;
eua.l = 6;
OSMO_ASSERT(in46a_from_eua(&eua, &ia) < 0);
OSMO_ASSERT(in46a_from_eua(&eua, ia) < 0);
/* unspecified V4 */
memcpy(eua.v, v4_unspec, sizeof(v4_unspec));
eua.l = sizeof(v4_unspec);
OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 1);
OSMO_ASSERT(ia.len == 4);
OSMO_ASSERT(ia.v4.s_addr == 0);
OSMO_ASSERT(in46a_from_eua(&eua, ia) == 1);
OSMO_ASSERT(ia[0].len == 4);
OSMO_ASSERT(ia[0].v4.s_addr == 0);
/* specified V4 */
memcpy(eua.v, v4_spec, sizeof(v4_spec));
eua.l = sizeof(v4_spec);
OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 1);
OSMO_ASSERT(ia.len == 4);
OSMO_ASSERT(ia.v4.s_addr == htonl(0x01020304));
OSMO_ASSERT(in46a_from_eua(&eua, ia) == 1);
OSMO_ASSERT(ia[0].len == 4);
OSMO_ASSERT(ia[0].v4.s_addr == htonl(0x01020304));
}
static void test_in46a_netmasklen(void)
@@ -318,7 +318,7 @@ static void test_in46a_to_eua_v4v6() {
static void test_in46a_from_eua_v6(void)
{
struct in46_addr ia;
struct in46_addr ia[2];
struct ul66_t eua;
const uint8_t v6_unspec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v6 };
const uint8_t v6_spec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v6,
@@ -331,16 +331,16 @@ static void test_in46a_from_eua_v6(void)
/* unspecified V6 */
memcpy(eua.v, v6_unspec, sizeof(v6_unspec));
eua.l = sizeof(v6_unspec);
OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 1);
OSMO_ASSERT(ia.len == 16);
OSMO_ASSERT(IN6_IS_ADDR_UNSPECIFIED(&ia.v6));
OSMO_ASSERT(in46a_from_eua(&eua, ia) == 1);
OSMO_ASSERT(ia[0].len == 16);
OSMO_ASSERT(IN6_IS_ADDR_UNSPECIFIED(&ia[0].v6));
/* specified V6 */
memcpy(eua.v, v6_spec, sizeof(v6_spec));
eua.l = sizeof(v6_spec);
OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 1);
OSMO_ASSERT(ia.len == 16);
OSMO_ASSERT(!memcmp(&ia.v6, v6_spec+2, ia.len));
OSMO_ASSERT(in46a_from_eua(&eua, ia) == 1);
OSMO_ASSERT(ia[0].len == 16);
OSMO_ASSERT(!memcmp(&ia[0].v6, v6_spec+2, ia[0].len));
}
static void test_in46a_from_eua_v4v6(void) {
@@ -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));

View File

@@ -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));

3
utils/Makefile.am Normal file
View File

@@ -0,0 +1,3 @@
bin_PROGRAMS = gtp-echo-responder
gtp_echo_responder_SOURCES = gtp_echo_responder.c

470
utils/gtp_echo_responder.c Normal file
View File

@@ -0,0 +1,470 @@
/*
* MIT License
*
* Copyright (c) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau Espin Pedrol <pespin@sysmocom.de>
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* For more info see:
* 3GPP TS 29.060 (GTPv1 and GTPv0)
* 3GPP TS 29.274 (GTPv2C)
*/
#include "../config.h"
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/socket.h>
#define GTP1C_PORT 2123
#define GTP_MSGTYPE_ECHO_REQ 1
#define GTP_MSGTYPE_ECHO_RSP 2
#define GTP1C_IE_RECOVERY 14
#define GTP2C_IE_RECOVERY 3
#define GTP2C_IE_NODE_FEATURES 152
struct gtp1_hdr {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint8_t pn:1, s:1, e:1, spare:1, pt:1, version:3;
#else
uint8_t version:3, pt:1, spare:1, e:1, s:1, pn:1;
#endif
uint8_t type;
uint16_t length;
uint32_t tei;
uint16_t seq;
uint8_t npdu;
uint8_t next;
} __attribute__((packed));
struct gtp2_hdr {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint8_t reserved:3, t:1, p:1, version:3;
#else
uint8_t version:3, p:1, t:1, reserved:1;
#endif
uint8_t type;
uint16_t length;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint32_t reserved2:8, seq:24;
#else
uint8_t seq:24, reserved2:1;
#endif
} __attribute__((packed));
struct gtp_echo_resp_state {
struct {
char laddr[INET6_ADDRSTRLEN];
uint8_t recovery_ctr;
uint8_t node_features;
} cfg;
struct sockaddr_storage laddr_gtpc;
int fd_gtpc;
};
struct gtp_echo_resp_state *g_st;
static void print_usage(void)
{
printf("Usage: gtp-echo-responder [-h] [-V] [-l listen_addr]\n");
}
static void print_help(void)
{
printf(" Some useful help...\n"
" -h --help This help text\n"
" -V --version Print the version of gtp-echo-responder\n"
" -l --listen-addr Listend address for GTPCv1 and GTPCv2\n"
" -R --recovery-counter GTP Recovery Counter to transmit in GTP Echo Response message\n"
" -n --node-features GTPCv2 Node Features bitmask to transmit in GTP Echo Response message\n"
);
}
static void print_version(void)
{
printf("gtp-echo-responder version %s\n", PACKAGE_VERSION);
}
static uint8_t parse_node_features_mask(const char *arg)
{
unsigned long res;
char *end;
errno = 0;
res = strtoul(arg, &end, 0);
if ((errno == ERANGE && res == ULONG_MAX) || (errno && !res) ||
arg == end || *end != '\0') {
fprintf(stderr, "Failed parsing Node Features bitmask: '%s'\n", arg);
exit(1);
}
if (res > 0xff) {
fprintf(stderr, "Failed parsing Node Features bitmask: '%s' > 0xFF\n", arg);
exit(1);
}
return (uint8_t)res;
}
static void handle_options(int argc, char **argv)
{
while (1) {
int option_index = 0, c;
static struct option long_options[] = {
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
{ "listen-addr", 1, 0, 'l'},
{ "recovery-counter", 1, 0, 'R'},
{ "node-features", 1, 0, 'N'},
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "hVl:R:N:", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_usage();
print_help();
exit(0);
case 'V':
print_version();
exit(0);
break;
case 'l':
strncpy(&g_st->cfg.laddr[0], optarg, sizeof(g_st->cfg.laddr));
g_st->cfg.laddr[sizeof(g_st->cfg.laddr) - 1] = '\0';
break;
case 'R':
g_st->cfg.recovery_ctr = (uint8_t)atoi(optarg);
break;
case 'N':
g_st->cfg.node_features = parse_node_features_mask(optarg);
break;
}
}
}
static int init_socket(void)
{
struct in_addr addr;
struct in6_addr addr6;
struct sockaddr_in *saddr;
struct sockaddr_in6 *saddr6;
int family;
if (inet_pton(AF_INET6, g_st->cfg.laddr, &addr6) == 1) {
family = AF_INET6;
saddr6 = (struct sockaddr_in6 *)&g_st->laddr_gtpc;
saddr6->sin6_family = family;
saddr6->sin6_port = htons(GTP1C_PORT);
memcpy(&saddr6->sin6_addr, &addr6, sizeof(addr6));
} else if (inet_pton(AF_INET, g_st->cfg.laddr, &addr) == 1) {
family = AF_INET;
saddr = (struct sockaddr_in *)&g_st->laddr_gtpc;
saddr->sin_family = family;
saddr->sin_port = htons(GTP1C_PORT);
memcpy(&saddr->sin_addr, &addr, sizeof(addr));
} else {
fprintf(stderr, "Failed parsing address %s\n", g_st->cfg.laddr);
return -1;
}
if ((g_st->fd_gtpc = socket(family, SOCK_DGRAM, 0)) < 0) {
fprintf(stderr, "socket() failed: %s\n", strerror(errno));
return -2;
}
if (bind(g_st->fd_gtpc, (struct sockaddr *)&g_st->laddr_gtpc, sizeof(g_st->laddr_gtpc)) < 0) {
fprintf(stderr, "bind() failed: %s\n", strerror(errno));
return -3;
}
return 0;
}
static const char *sockaddr2str(const struct sockaddr *saddr)
{
static char _rem_addr_str[INET6_ADDRSTRLEN];
struct sockaddr_in *saddr4;
struct sockaddr_in6 *saddr6;
switch (saddr->sa_family) {
case AF_INET6:
saddr6 = (struct sockaddr_in6 *)saddr;
if (!inet_ntop(saddr6->sin6_family, &saddr6->sin6_addr, _rem_addr_str, sizeof(_rem_addr_str)))
strcpy(_rem_addr_str, "unknown");
return _rem_addr_str;
case AF_INET:
saddr4 = (struct sockaddr_in *)saddr;
if (!inet_ntop(saddr4->sin_family, &saddr4->sin_addr, _rem_addr_str, sizeof(_rem_addr_str)))
strcpy(_rem_addr_str, "unknown");
return _rem_addr_str;
default:
strcpy(_rem_addr_str, "unknown-family");
return _rem_addr_str;
}
}
static int write_cb(int fd, const uint8_t *buf, size_t buf_len, const struct sockaddr *rem_saddr)
{
ssize_t rc;
rc = sendto(fd, buf, buf_len, 0, rem_saddr, sizeof(struct sockaddr_storage));
if (rc < 0) {
fprintf(stderr, "sendto() failed: %s\n", strerror(errno));
return -1;
}
if (rc != buf_len) {
fprintf(stderr, "sendto() short write: %zd vs exp %zu\n", rc, buf_len);
return -1;
}
return 0;
}
static int gen_gtpc1_echo_rsp(uint8_t *buf, struct gtp1_hdr *echo_req)
{
int offset = 0;
struct gtp1_hdr *echo_rsp = (struct gtp1_hdr *)buf;
unsigned exp_hdr_len = (echo_req->s || echo_req->pn || echo_req->e) ? 12 : 8;
memcpy(echo_rsp, echo_req, exp_hdr_len);
echo_rsp->type = GTP_MSGTYPE_ECHO_RSP;
offset = exp_hdr_len;
buf[offset++] = GTP1C_IE_RECOVERY;
buf[offset++] = g_st->cfg.recovery_ctr;
/* Update Length */
echo_rsp->length = htons(offset - 8);
return offset;
}
static int gen_gtpc2_echo_rsp(uint8_t *buf, struct gtp2_hdr *echo_req)
{
int offset = 0;
struct gtp1_hdr *echo_rsp = (struct gtp1_hdr *)buf;
unsigned exp_hdr_len = 8;
memcpy(echo_rsp, echo_req, exp_hdr_len);
echo_rsp->type = GTP_MSGTYPE_ECHO_RSP;
offset = exp_hdr_len;
/* 3GPP TS 29.274 sec 8.5 Recovery (Restart Counter) */
buf[offset++] = GTP2C_IE_RECOVERY;
buf[offset++] = 0; /* IE Length (high) */
buf[offset++] = 1; /* IE Length (low) */
buf[offset++] = 0; /* Spare=0 | Instance=0 (Table 7.1.1-1) */
buf[offset++] = g_st->cfg.recovery_ctr;
/* 3GPP TS 29.274 sec 8.83 Node Features */
if (g_st->cfg.node_features > 0) {
buf[offset++] = GTP2C_IE_NODE_FEATURES;
buf[offset++] = 0; /* IE Length (high) */
buf[offset++] = 1; /* IE Length (low) */
buf[offset++] = 0; /* Spare=0 | Instance=0 (Table 7.1.1-1) */
buf[offset++] = g_st->cfg.node_features;
}
/* Update Length */
echo_rsp->length = htons(offset - 4);
return offset;
}
static int rx_gtpc1_echo_req(struct gtp1_hdr *echo_req, unsigned buf_len, const struct sockaddr *rem_saddr)
{
int rc;
const size_t tx_buf_len = buf_len + 128; /* Leave some extra room */
uint8_t *tx_buf = alloca(tx_buf_len);
printf("Rx GTPCv1_ECHO_REQ from %s, Tx GTPCv1_ECHO_RSP\n", sockaddr2str(rem_saddr));
memset(tx_buf, 0, tx_buf_len);
rc = gen_gtpc1_echo_rsp(tx_buf, echo_req);
return write_cb(g_st->fd_gtpc, tx_buf, rc, rem_saddr);
}
static int rx_gtpc1(struct gtp1_hdr *hdr, unsigned buf_len, const struct sockaddr *rem_saddr)
{
unsigned exp_hdr_len = (hdr->s || hdr->pn || hdr->e) ? 12 : 8;
unsigned pdu_len;
if (buf_len < exp_hdr_len) {
fprintf(stderr, "GTPCv1 packet size smaller than header! %u < exp %u\n", buf_len, exp_hdr_len);
return -1;
}
pdu_len = ntohs(hdr->length);
if (buf_len < 8 + pdu_len) {
fprintf(stderr, "GTPCv1 packet size smaller than announced! %u < exp %u\n", buf_len, 8 + pdu_len);
return -1;
}
if (hdr->pt != 1) {
fprintf(stderr, "GTPCv1 Protocol Type GTP' not supported!\n");
return -1;
}
switch (hdr->type) {
case GTP_MSGTYPE_ECHO_REQ:
return rx_gtpc1_echo_req(hdr, buf_len, rem_saddr);
default:
fprintf(stderr, "Silently ignoring unexpected packet of type %u\n", hdr->type);
return 0;
}
}
static int rx_gtpc2_echo_req(struct gtp2_hdr *echo_req, unsigned buf_len, const struct sockaddr *rem_saddr)
{
int rc;
const size_t tx_buf_len = buf_len + 128; /* Leave some extra room */
uint8_t *tx_buf = alloca(tx_buf_len);
if (echo_req->t) {
fprintf(stderr, "GTPCv2 ECHO message should contain T=0!\n");
return -1;
}
printf("Rx GTPCv2_ECHO_REQ from %s, Tx GTPCv2_ECHO_RSP\n", sockaddr2str(rem_saddr));
memset(tx_buf, 0, tx_buf_len);
rc = gen_gtpc2_echo_rsp(tx_buf, echo_req);
return write_cb(g_st->fd_gtpc, tx_buf, rc, rem_saddr);
}
static int rx_gtpc2(struct gtp2_hdr *hdr, unsigned buf_len, const struct sockaddr *rem_saddr)
{
unsigned exp_hdr_len = hdr->t ? 12 : 8;
unsigned pdu_len;
if (hdr->p) {
fprintf(stderr, "GTPCv2 piggybacked message not supported!\n");
return -1;
}
if (buf_len < exp_hdr_len) {
fprintf(stderr, "GTPCv2 packet size smaller than header! %u < exp %u\n", buf_len, exp_hdr_len);
return -1;
}
pdu_len = ntohs(hdr->length);
/* 3GPP TS 29.274 sec 5.5.1: "Octets 3 to 4 represent the Message Length
* field. This field shall indicate the length of the message in octets
* excluding the mandatory part of the GTP-C header (the first 4
* octets). The TEID (if present) and the Sequence Number shall be
* included in the length count" */
if (buf_len < 4 + pdu_len) {
fprintf(stderr, "GTPCv2 packet size smaller than announced! %u < exp %u\n", buf_len, 4 + pdu_len);
return -1;
}
switch (hdr->type) {
case GTP_MSGTYPE_ECHO_REQ:
return rx_gtpc2_echo_req(hdr, buf_len, rem_saddr);
default:
fprintf(stderr, "Silently ignoring unexpected packet of type %u\n", hdr->type);
return 0;
}
}
static int read_cb(int fd)
{
ssize_t sz;
uint8_t buf[4096];
struct sockaddr_storage rem_saddr;
socklen_t rem_saddr_len = sizeof(rem_saddr);
struct gtp1_hdr *hdr1;
if ((sz = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&rem_saddr, &rem_saddr_len)) < 0) {
fprintf(stderr, "recvfrom() failed: %s\n", strerror(errno));
return -1;
}
if (sz == 0) {
fprintf(stderr, "recvfrom() read zero bytes!\n");
return -1;
}
hdr1 = (struct gtp1_hdr *)&buf[0];
switch (hdr1->version) {
case 1:
return rx_gtpc1(hdr1, sz, (const struct sockaddr *)&rem_saddr);
case 2:
return rx_gtpc2((struct gtp2_hdr *)&buf[0], sz, (const struct sockaddr *)&rem_saddr);
default:
fprintf(stderr, "Rx GTPv%u: not supported (flags=0x%x)\n", hdr1->version, buf[0]);
return -1;
}
}
static int loop(void)
{
int rc;
fd_set rfds;
int nfds;
while (true) {
FD_ZERO(&rfds);
FD_SET(g_st->fd_gtpc, &rfds);
nfds = g_st->fd_gtpc + 1;
rc = select(nfds, &rfds, NULL, NULL, NULL);
if (rc == 0)
continue;
if (rc < 0) {
fprintf(stderr, "select() failed: %s\n", strerror(errno));
return -1;
}
if (FD_ISSET(g_st->fd_gtpc, &rfds))
read_cb(g_st->fd_gtpc);
}
}
int main(int argc, char **argv)
{
g_st = calloc(1, sizeof(struct gtp_echo_resp_state));
strcpy(g_st->cfg.laddr, "::");
handle_options(argc, argv);
printf("Listening on: %s\n", g_st->cfg.laddr);
if (init_socket() < 0)
exit(1);
printf("Socket bound successfully, listening for requests...\n");
if (loop() < 0)
exit(1);
return 0;
}

111
utils/gtp_echo_responder_test.py Executable file
View File

@@ -0,0 +1,111 @@
#!/usr/bin/env python3
# MIT License
#
# Copyright (c) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
# Author: Pau Espin Pedrol <pespin@sysmocom.de>
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice (including the next
# paragraph) shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import socket
import argparse
import struct
from ipaddress import ip_address, IPv4Address
GTP1C_PORT = 2123
BUF_SIZE = 4096
GTP_HDRv1_FLAG_PN = (1<<0)
GTP_HDRv1_FLAG_S = (1<<1)
GTP_HDRv1_FLAG_E = (1<<2)
GTP_HDRv1_PT_GTP = (1<<4)
GTP_HDRv1_VER_GTP1 = (1<<5)
GTP_HDRv2_FLAG_T = (1<<3)
GTP_HDRv2_FLAG_P = (1<<4)
GTP_HDRv2_VER_GTP2 = (2<<5)
def gen_gtpc_v1_hdr(flags, type, length, tei, seq=0, npdu=0, next=0):
spare = 0
if (flags & (GTP_HDRv1_FLAG_PN|GTP_HDRv1_FLAG_S|GTP_HDRv1_FLAG_E)):
#long format
length += 4
d = struct.pack('!BBHIHBB', flags, type, length, tei, seq, npdu, next)
else:
#short format
d = struct.pack('!BBHI', flags, type, length, tei)
return d
def gen_gtpc_v2_hdr(flags, type, length, tei=0, seq=0):
spare = 0
if (flags & (GTP_HDRv2_FLAG_T)):
#long format, with TEI
length += 4 + 4
d = struct.pack('!BBHIHBB', flags, type, length, tei, seq >> 8, seq & 0xff, spare)
else:
#short format
length += 4
d = struct.pack('!BBHHBB', flags, type, length, seq >> 8, seq & 0xff, spare)
return d
def gen_gtpc_v1_echo_req(tei=0, append_flags=0, seq=0, npdu=0, next=0):
return gen_gtpc_v1_hdr(GTP_HDRv1_VER_GTP1 | GTP_HDRv1_PT_GTP | append_flags, 1, 0, tei, seq, npdu, next)
def gen_gtpc_v2_echo_req(append_flags=0, seq=0, recovery=0, node_features=-1):
length = 0
payload = b''
if (recovery > 0):
recovery_ie = struct.pack('!BHBB', 3, 1, 0, recovery)
payload += recovery_ie
length += len(recovery_ie)
if (node_features > 0):
node_features_ie = struct.pack('!BHBB', 152, 1, 0, node_features)
payload += node_features_ie
length += len(node_features_ie)
return gen_gtpc_v2_hdr(GTP_HDRv2_VER_GTP2 | append_flags, 1, length, 0, seq) + payload
def tx_rx(sk, rem_addr, tx_buf, exp_rx = True):
print('Tx ECHO_REQ to %r: %r' % (repr(rem_addr), repr(tx_buf)))
sk.sendto(tx_buf, rem_addr)
if exp_rx:
rx_buf = sk.recvfrom(BUF_SIZE)
msg = "Message from Server {}".format(rx_buf)
print(msg)
if __name__ == '__main__':
p = argparse.ArgumentParser(description='Tester for gtp-echo-recorder.')
p.add_argument('-l', '--local-address', default='127.0.0.2', help="Local GTP address")
p.add_argument('-r', '--remote-address', default='127.0.0.1', help="Remote GTP address")
args = p.parse_args()
print('Binding socket on %r...' % repr((args.local_address, GTP1C_PORT)))
family = socket.AF_INET if type(ip_address(args.local_address)) is IPv4Address else socket.AF_INET6
sk = socket.socket(family=family, type=socket.SOCK_DGRAM)
sk.bind((args.local_address, GTP1C_PORT));
rem_addr = (args.remote_address, GTP1C_PORT)
tx_rx(sk, rem_addr, gen_gtpc_v1_echo_req())
tx_rx(sk, rem_addr, gen_gtpc_v1_echo_req(1, GTP_HDRv1_FLAG_S, seq=67))
tx_rx(sk, rem_addr, gen_gtpc_v2_echo_req(0, seq=300, recovery=-1, node_features=-1))
tx_rx(sk, rem_addr, gen_gtpc_v2_echo_req(0, seq=20, recovery=99, node_features=-1))
tx_rx(sk, rem_addr, gen_gtpc_v2_echo_req(0, seq=20, recovery=100, node_features=0xbb))