Compare commits

...

487 Commits

Author SHA1 Message Date
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
Pau Espin Pedrol
04715d284f sgsnemu: Fix assumption ipv6 Interface-Identifier of public addr == announced Prefix
Until now, sgsnemu was able to identify pdp contexts of incoming packets
in the tun based on the assumption that the Interface-Identifier part of
public IPv6 addresses in incoming packets was equal to the announced
prefix path during Create Pdp Context Response (see changes in cb_tun_ind()).
This assumption works fine with osmo-ggsn due to implementation details but
breaks on other spec-conformant GGSNs.

In order to fix it, a new placeholder struct pdp_peer_sgsnemu_ctx is
introduced which will be assigned to each pdp_t "peer[0]" user-defined
pointer. This way, each pdp_t ctx upgrades from having only 1 iphash_t
item to 3 (hence being able to match against 3 different ip addresses).
This way, in IPv6 we can match against 2 different IP addresses set on
the tun iface:
* link-local: "fe80::IfId", where IfId is the Interface-Identifier
  received during Pdp Context Resp and which can be used to communicate
  with the nearest router (the GGSN).
* global: The global IPv6 addr set after SLAAC procedure, containing a
  the prefix announced by CreatePdpContextResp/RouterAdvertisement and
  an Interface-Identifier chosen by sgsnemu itself (currently ::ff).

This change is also a step forward towards supporting IPv4v6 APNs in sgsnemu.

Related: OS#4434
Change-Id: I0d36145250185e4cce699fdaedfe96bd969f5fa1
2020-04-21 16:40:39 +02:00
Pau Espin Pedrol
962146085c sgsnemu: Implement ping on IPv6 APNs
Related: OS#4434
Change-Id: If9ca7c37a1a397bbc3f8912d67bccdabc4968e0c
2020-04-21 16:40:39 +02:00
Pau Espin Pedrol
e2b0961f18 sgsnemu: Handle IPv6 SLAAC in tun iface manually
Disable IPv6 automatic SLAAC by linux kernel and handle it manually.
This allows us gaining control on local address acquisition and set
addresses and routing properly. It will also allow us to run in ping
mode without a tun iface.

Related: OS#4434

Change-Id: Iae59cf6ffb181357e10b3080a5c751bd454f4a1f
2020-04-21 14:39:42 +00:00
Pau Espin Pedrol
ff2ebee03b sgsnemu: Fix build/run against linux < 4.11 (no sysctl addr_gen_mode support)
On older systems (like debian 8), the enum is not present in the header
file and build will fail (as saw in osmocom's OBS instance).
Furthermore, the sysctl to change the value was added at a later point
in time, which means compiling can go fine but running may fail due to
the sysctl not being available.

This is a fix-up to Change-Id I1d51f3ca91edbb3b788939982ab63264182ec2ce

Change-Id: I208970d5b16ea7148444d414b0a6f68c8d9a086c
2020-04-19 08:29:35 +00:00
Pau Espin Pedrol
2a1cedd2dc Rename netdev_*route to end in route4
Functions for IPv6 will be added soon afterwards. Also take the chance
to check for address length in sgsnemu and only apply the route if the
address matches.

Change-Id: Ic6c1b3c11c56f047e6e8c6f1040257fd62afea0f
2020-04-15 16:40:10 +02:00
Pau Espin Pedrol
c43e887e9e icmpv6.c: Move code generating ipv6 hdr to its own function
It will be re-used in next commits.

Change-Id: I3c108efad6461cd4e82ef435290005174bc8b30e
2020-04-15 16:40:10 +02:00
Pau Espin Pedrol
e5d71639e5 sgsnemu: tun_addaddr: Don't set local addr as dstaddr
That should be used for point-to-point destination address.

Change-Id: Iead7e9c7570ba6a9de3089a164997b1db81dc59a
2020-04-15 16:40:10 +02:00
Pau Espin Pedrol
a1b3deefda sgsnemu: Get rid of duplicated options.net
It's not really set by any cmdline arg, and it always contains same
content as options.netaddr.

Change-Id: Id3cdca0975bdd2893b4b83944c5ebf29b2994622
2020-04-15 16:40:10 +02:00
Pau Espin Pedrol
964f08a919 sgsnemu: Get rid of duplicated options.destaddr
It's not really set by any cmdline arg, and it always contains same
content as options.netaddr.

Change-Id: I5a4e3c4b5ae43a89a7d0af62fb396311dcb6ebae
2020-04-15 16:40:10 +02:00
Pau Espin Pedrol
ee1529e5ac icmpv6.c: Mark internal function as static
Change-Id: Ib38907c3a05c1651faa86ef57381ee22643e0d53
2020-04-15 16:40:10 +02:00
Pau Espin Pedrol
29e7bd0510 cosmetic: icmpv6.c: fix typo in comment
Change-Id: I2217dfb0b0a1e6e029ac817902e80c771ed219c3
2020-04-15 16:39:51 +02:00
Pau Espin Pedrol
cdcaeda81c sgsnemu: Fix ping transmitted statistics output
Change-Id: I6e23e024ee30d6049c6b8b614c50d062d80a5260
2020-04-15 16:39:28 +02:00
Pau Espin Pedrol
98f8126b98 sgsnemu: Avoid adding extra autogenerated local link ipv6 addr to tun iface
It's not needed because a link-local address will be added as a result
of Create Pdp Context Response. Morevoer, it fools sgsnemu ip addr
verifications since it gets used on some scenarios by applications.

Change-Id: I1d51f3ca91edbb3b788939982ab63264182ec2ce
2020-04-15 15:10:42 +02:00
Philipp Maier
a1503b902c doc: use 127.0.0.2 instead of 127.0.0.6 as bind ip.
The example config for osmo-sgsn suggests to use 127.0.0.6 as bind ip.
(the ip-address where the SGSN tries to connect) Lets use 127.0.0.2
instead to match the default config of osmo-sgsn.

Change-Id: I513ab64896dee47fd92dbc5ef495fe1c6e734ec3
2020-04-14 17:16:58 +00:00
Harald Welte
8398bccb0b lib/netns: Fix up error paths
The error handling in the code was doing exactly what one would not
expect.  If we switch to a netns and then encounter an error, we
obviously have to switch back to the original netns before returning.

Likewise, if we temporarily change the signal mask, we need to switch
back to the original one before returning.

Change-Id: I9ff5ae7bffc5bd7629dae0af1b72cfea548f9039
2020-04-14 17:15:52 +00:00
Pau Espin Pedrol
5552872733 netdev_addaddr6: Use prefixlen arg
The parameter was simply unused until this change was made. An Ipv6 can
have a prefix length between 48 and 64 bits.

Change-Id: I4b1512d5a4d7bbc2516221ea6808565eac0eb18f
2020-04-14 17:15:35 +00:00
Harald Welte
61b010c25a lib/netns: OSMO_ASSERT() if user doesn't call init_netns()
It is vital that init_netns() is called first in order to initialize
default_nsfd.

Change-Id: Ic16646fa7d60c578056b17351c5fe2090a81dff0
2020-04-14 13:19:35 +00:00
Harald Welte
20d9d154c5 lib/netns.c: Add comments to the code, including doxygen API docs
Change-Id: I0b20e4870bf62df0a459a621a64a4e2795340ceb
2020-04-14 13:19:04 +00:00
Pau Espin Pedrol
1c8ae66654 Move icmpv6 and checksum files from ggsn/ dir to lib/
They will be required by sgsnemu to implement ICMPv6 Router
Soliciations.

Change-Id: Ie878604f0fc0169cc98a1e9eee64b14d76be2c45
2020-04-14 13:18:21 +00:00
Pau Espin Pedrol
fcdaf31aa8 sgsnemu: Set its default loglevel category to INFO
sgsnemu is a testing program and doesn't have a VTY iface to configure
its log levels, so let's simply enable INFO as a default.

Change-Id: I2a577f547b57fb0ab7b83de5c12da088697f3904
2020-04-14 13:18:21 +00:00
Pau Espin Pedrol
9366f4c034 sgsnemu: Rename sgsnemu's libgtp cb_conf
It makes it easier to understand where the function is called.

Change-Id: Ibf32b416c3247d1415aa9c1a88755076dcd606f4
2020-04-14 13:18:21 +00:00
Pau Espin Pedrol
28c6a32677 sgsnemu: Pass array of in64_addr to in46a_from_eua()
Let's avoid buffer-overflow writing into out-of-bounds memory in the
event the GGSN sends us 2 EUAs in Create PDP Context Respose. It should
theoretically happen since we don't yet support ipv4v6 APNs in sgsnemu,
but who knows.

Change-Id: I8becd90ce1f0e8bb6e21438c04da4a9cab845492
2020-04-14 13:18:21 +00:00
Eric
107c813eee configure.ac: fix libtool issue with clang and sanitizer
As pointed out at https://github.com/libexpat/libexpat/issues/312
libtool does not play nice with clang sanitizer builds at all.
For those builds LD shoud be set to clang too (and LDFLAGS needs the
sanitizer flags as well), because the clang compiler driver knows how
linking to the sanitizer libs works, but then at a later stage libtool
fails to actually produce the shared libraries and the build fails. This
is fixed by this patch.

Addtionally LD_LIBRARY_PATH has no effect on conftest runs during
configure time, so the rpath needs to be set to the asan library path to
ensure the configure run does not fail due to a missing asan library,
i.e.:

SANS='-fsanitize=memory -fsanitize-recover=all -shared-libsan'
export CC=clang-10
ASANPATH=$(dirname `$CC -print-file-name=libclang_rt.asan-x86_64.so`)
export LDFLAGS="-Wl,-rpath,$ASANPATH $SANS $LDFLAGS"

Change-Id: Icc09c9d09bfa01264ddf867356d068e50d97c5a0
2020-04-14 13:07:47 +00:00
Pau Espin Pedrol
90d1732be1 sgsnemu: cmdline: Drop unused function cmdline_parser_params_create()
Change-Id: I7d5d69f104d24aafd4aa0b7289bb8b3fa1d77ed4
2020-04-08 19:00:19 +02:00
Philipp Maier
1c3505b885 doc: do not use random ip address for dns in default conf
The default configuration has a random ip-address as first DNS server.
This might cause unnedessary trouble for people who try osmo-ggsn the
first time. Lets have some public DNS here, just to be sure.

Change-Id: I5876a806185bb3aea356fb6996d1925b8d0d1758
2020-03-25 13:01:45 +01:00
Vadim Yanitskiy
20539f0271 lib/netns: fix open_ns(): return fd from open()
Looks like a bug introduced by I9b9c8fd6eeaaa7d190b8e2a34ca82088904c7708.

Change-Id: I38caf5541ca90638ed10714adfbb08120e5397b9
Fixes: CID#208656
2020-03-03 15:40:26 +07:00
Pau Espin Pedrol
ad6eaa2881 netns: Improve error checking
Change-Id: I9b9c8fd6eeaaa7d190b8e2a34ca82088904c7708
2020-03-02 09:41:43 +01:00
Andreas Schultz
b629240a35 add Linux network namespace support for TUN device
Change-Id: Idd0ad8fa9c8e7ba0aeec1b52947598d4d297b620
2020-02-26 11:16:06 +01:00
Pau Espin Pedrol
b283c32027 cosmetic: Fix comment typo
Change-Id: I8240b388ffb8c1806bf0d34a9e59146b403a13be
2020-02-25 14:13:09 +01:00
Pau Espin Pedrol
e71e0f2af8 Bump version: 1.4.0.32-bd8f-dirty → 1.5.0
Change-Id: I84bbe9eff37e14985b812b49e53eb6d62fff14a5
2020-01-02 20:39:39 +01:00
Vadim Yanitskiy
bd8f028bff contrib/systemd: add systemd-networkd examples from manuals
Change-Id: I265637f39dd16dd43992f33149e512e34ed83252
2019-12-06 00:47:26 +07:00
Vadim Yanitskiy
a55454d58e manuals/configuration.adoc: fix IPv4 address mismatch in <<ggsn_no_root>>
Change-Id: Ide9465a01857dbe5ec7f5bc1d09468153865156f
2019-12-06 00:21:13 +07:00
Vadim Yanitskiy
f1be1df0d3 manuals/configuration.adoc: fix Network Address without prefix length
"An address '192.168.7.1' is specified without prefix length. The behavior
of parsing addresses without prefix length will be changed in the future
release. Please specify prefix length explicitly."

Change-Id: I51777c6344191182fb87bae6f0048ce422802541
2019-12-06 00:20:21 +07:00
Harald Welte
c22205bec8 manual: Fix copy+paste error
Change-Id: Ib6a97d8c93203e1f896ab1bd3d200d2223f9fc48
2019-12-01 14:24:19 +01:00
Harald Welte
fdf3358959 sgsnemu: Fix null-pointer format string argument
Modern gcc-9.2.1 actually fails like this with --enable-werror active:

In file included from sgsnemu.c:52:
In function ‘process_options’,
    inlined from ‘main’ at sgsnemu.c:1557:6:
../lib/syserr.h:31:3: error: ‘%s’ directive argument is null [-Werror=format-overflow=]
   31 |   logp2(sub, pri, __FILE__, __LINE__, 0,   \
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   32 |    fmt "\n", ##args);    \
      |    ~~~~~~~~~~~~~~~~~
sgsnemu.c:435:3: note: in expansion of macro ‘SYS_ERR’
  435 |   SYS_ERR(DSGSN, LOGL_ERROR, 0,
      |   ^~~~~~~
sgsnemu.c: In function ‘main’:
sgsnemu.c:436:42: note: format string is defined here
  436 |    "Listening address must be specified: %s!",
      |                                          ^~

It is correct: We are dereferencing args_info.listen_addr in a
branch which explicitly checks if that is NULL beforehand :/

Change-Id: I417f447f821d396aa92049e0a791121240f1cf44
2019-12-01 09:26:49 +01:00
Pau Espin Pedrol
1bf41e4f36 ggsn, sgsnemu: Drop use of no-op deprecated gtp_retrans* APIs
Related: OS#4178
Change-Id: I295b89ee493d230c2550d461fca9602c589d38b5
2019-09-05 09:59:52 +00:00
Pau Espin Pedrol
c94837c6a4 gtp: Manage queue timers internally
Currently each user (application) of libgtp needs to manage its own
timers in order to call gtp_retrans_timeout() and gtp_retrans() and
maintain retransmit and duplicate queues working correctly. This adds
unnecesary complexity to applications since nowadays, as a libosmocore
user, libgtp can handle this internally in an easy way.
Furthermore, keeping the timers internal to the library allows for
easier extension of features as well as re-implementation of related
code in the future.
Last but not least, it was detected that existing known applications
(osmo-sgsn, osmo-ggsn, sgsnemu) are not using correctly the API, since
they should be updating their timers through gtp_retrans_timeout()
everytime a message is enqueued/transmitted, otherwise they may fire
gtp_retrans() for retransmition too late in some cases.

Related: OS#4178
Change-Id: Ife7cfd66d6356f413263fe5bda9e43091f5c9e98
2019-09-05 09:59:52 +00:00
Vadim Yanitskiy
68c5a74557 gtp/gtp.c: cosmetic: use get_tid() where we need TID
Change-Id: I39e92f25ed51665c8a615826ed52f35024bdd54b
2019-09-02 09:03:43 +00:00
Vadim Yanitskiy
bdf2cf9038 gtp_error_ind_conf(): fix: guard against an unknown GTP version
This change fixes the following compiler warnings (found by Clang):

  gtp.c:2747:13: warning: variable 'pdp' is used uninitialized
			  whenever 'if' condition is false
			  [-Wsometimes-uninitialized]
		 } else if (version == 1) {

  gtp.c:2781:14: note: uninitialized use occurs here
  		 OSMO_ASSERT(pdp);
			     ^^^

Shall not happen in general, but let's make Clang happy.

Change-Id: Id471b22afd4c45435589a4edda0a804e66be3a7a
2019-09-02 09:03:43 +00:00
Vadim Yanitskiy
00a6171b8d gtp_update_pdp_ind(): fix NULL-pointer dereference
As stated in the comment above, we need to use the tunnel identifier
to find a GTP context, and derive both IMSI and NSAPI from that TID,
when speaking GTP version 0.

This change fixes the following warnings (found with Clang):

  gtp.c:2115:22: warning: variable 'pdp' is uninitialized
			  when used here [-Wuninitialized]
		 pdp_set_imsi_nsapi(pdp, tid);
				    ^^^

  gtp.c:2118:34: warning: variable 'imsi' is uninitialized
			  when used here [-Wuninitialized]
		 if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi))
						^^^^

  gtp.c:2118:40: warning: variable 'nsapi' is uninitialized
			  when used here [-Wuninitialized]
		 if (gtp_pdp_getimsi(gsn, &pdp, imsi, nsapi))
						      ^^^^^

Change-Id: I8f1c8d0ba2e8189d97fe1bb5c872680e5ad1cd7a
2019-09-02 09:03:43 +00:00
Pau Espin Pedrol
26e300fda0 ggsn: rx DeletePdpReq confirmation: Improve documentation and use gtp_freepdp()
Update documentation since nowadays there are more paths calling
ggsn_close_one_pdp() (because we now close pdp contexts during sgsn
timeouts).

Switch pdp_freepdp() to gtp_freepdp() since in the event we ended up
there in the future we want to go through normal delete_ctx_cb  to free
related application data structures.

Change-Id: I7d9ae9a27390498ba387797aac6651e32fa44f29
2019-08-29 14:07:04 +02:00
Pau Espin Pedrol
4e605b32d4 cosmetic: gtp: Improve documentation of gtp_delete_context_req2()
Change-Id: I1f85c7cc7684e146fca4f17914927d45410dbb84
2019-08-29 14:07:04 +02:00
Pau Espin Pedrol
494d873fe3 cosmetic: gtp: Drop commented out code calling pdp_freepdp()
That code was commented out in 0b076a331e
(year 2003), and indeed it makes no sense to call those in current pdp
lifecycle (they are expected to be freed by the application).

Change-Id: I096d8cb8d749ff9b737d6f3f96b1d423660ece37
2019-08-29 14:07:00 +02:00
Pau Espin Pedrol
b4c98e7397 gtp: Log msg retransmits and timeouts
Change-Id: Ie768ddb45313582b4b5358b97a981080be64fd42
2019-08-28 18:47:58 +02:00
Pau Espin Pedrol
3eb05d2c1a cosmetic: fix formatting in if line
Fixes: eefa30dce8
Fixes: 2d6a69e69a
Change-Id: I9ee5f4142cacf912145693c72a53c0f531bad2c6
2019-08-28 11:34:51 +02:00
Pau Espin Pedrol
f5fbb419ef ggsn: Implement echo req/resp and recovery
This patch is quite big because implementing echo req/resp and recovery
requires having knowledge and managing differentiated state for each GSN
peer attached/connected to osmo-ggsn. This kind of information was not
available in osmo-ggsn nor in libgtp.

So osmo-ggsn is now able to track GSN peers connected to a
ggsn_ctx (associated gsn_t from libgtp) by means of "sgsn_peer" data
structure, and accessible from the ggsn through a list. The instances of
sgsn_peer are currently allocated and destroyed dynamically based on
discovered peer who have at least a pdp context attached to us (we are
not interested in peers without pdp contexts because we don't need to
send echo requests/responses and maintain state in that case).

A new private pointer (pdp_t->priv) data structure struct pdp_priv_t is
added to be able to relate a pdp_t to an sgsn as well as the already
existing pointer to an apn.

An "echo-interval <0-36000>" VTY command is added which allows
configuring time wait between echo requests being sent to each
sgsn_peer. Transmission of echo requests is disabled by default.

Finally, a new "show sgsn" VTY command is introduced, and its output is
also printed during "show ggsn".

Related: OS#4165
Change-Id: Id2c84165dc59dff495106758146a701ca488834f
2019-08-28 11:34:11 +02:00
Pau Espin Pedrol
5d8b226597 libgtp: Introduce cb_recovery3
Since osmo-ggsn can manage several GSN structures simultaneously, it
needs the gsn_t pointer to know the ggsn it should forward the call to.

Related: OS#4165
Change-Id: I33b4fe594d5833993af01cce34737e61e597b320
2019-08-28 11:24:08 +02:00
Pau Espin Pedrol
c602d7cf00 doc: Update vty reference xml file
Change-Id: I49e7db4d0f5c7868b86a4947d8b5739c2068da46
2019-08-28 11:21:23 +02:00
Pau Espin Pedrol
a019631c0b ggsn_vty.c: Improve output of VTY show pdp-context
GTP version and primary/secondary information is printed now for each
pdp context.

Related: OS#4154
Change-Id: If9682fe343e9a1e78175a12538fb80d4bda54802
2019-08-28 11:20:32 +02:00
Pau Espin Pedrol
88ce94c2bd pdp: constify param in pdp_count_secondary()
Change-Id: Ie772f2c54264c8bc91f50d9030479861dd8868b7
2019-08-28 11:14:57 +02:00
Pau Espin Pedrol
310ea1db10 ggsn_vty.c: Avoid printing duplicates for pdp context with v4v6 EUAs
Fixes potential duplicates when calling following VTY cmd:
show pdp-context ggsn NAME
show pdp-context ggsn NAME apn APN

Related: OS#4154
Change-Id: I98db39a710a72a1438d71aabaf4f8227984643e3
2019-08-28 11:14:57 +02:00
Pau Espin Pedrol
012d51ed7d Introduce LOGTUN log helper
Change-Id: I237acdee0be19498804e0d509c610f4e0454ba72
2019-08-28 11:14:57 +02:00
Pau Espin Pedrol
1ef2621d3f gtp-kernel.c: Fix wrong use of in46a_from_eua, print IPv6 euas
in46a_from_eua() API documentation clearly states an array of 2 items
should be passed as pointer, but show_one_pdp() was passing only one,
which would end up in out-of-bounds writes on v4v6 EUAs.

Let's better use ippool to print allocated ip addresses instead of
parsing EUAs we sent some point in the past.

Change-Id: I7e164f40f50de43027bcd4464aa879450d2fb10e
2019-08-28 11:14:57 +02:00
Pau Espin Pedrol
f612ffea82 Move pdp_get_peer_ipv() to lib/util.*
Preparation for next commit, where this function will be needed inside
libmisc (lib/*).

Change-Id: Ibab4f6c09d1e5f0e9cfaea28ae1e7ab5b5c219b5
2019-08-28 11:14:57 +02:00
Pau Espin Pedrol
421f22e8cf ggsn: Split application lifecycle related code into ggsn_main.c
This way we further shrink ggsn.c and leave there GGSN related code.

Change-Id: I9e6a3beac7657f0a8c02d514b54c6f1caa93bba7
2019-08-28 11:14:57 +02:00
Pau Espin Pedrol
03cce86941 ggsn_vty.c: Fix wrong use of in46a_from_eua, print IPv6 euas
in46a_from_eua() API documentation clearly states an array of 2 items
should be passed as pointer, but show_one_pdp() was passing only one,
which would end up in out-of-bounds writes on v4v6 EUAs.

Let's better use ippool to print allocated ip addresses instead of
parsing EUAs we sent some point in the past.

Related OS#4154
Change-Id: Ia34939957bb7856388cb52a741cec0c015a08c70
2019-08-28 11:14:57 +02:00
Pau Espin Pedrol
95cd897c3f in46_addr: Improve in46a_ntop documentation
Change-Id: I27238c330f9b805ac9e734e735d2c7ae158fe524
2019-08-28 11:14:51 +02:00
Pau Espin Pedrol
f7884e880e ggsn: Move PCO handling code into its own file
This way ggsn.c is shrinked in size and get rid of a lot of code there,
which is of no interest unless the reader is interested in that really
specific part.

Change-Id: Ieaa7e71f17c7fd9377c76ef53362eab596d669a6
2019-08-28 11:13:46 +02:00
Pau Espin Pedrol
60ee0dbfa4 Introduce in46a_is_v{4,6}() helpers
It's clearer having size-related checks in one place for a data structure
in46_addr, instead of spread around the code.

Change-Id: Idc94bf0c8c01bb5a30e36d3c284b99f66b972abb
2019-08-28 11:13:32 +02:00
Pau Espin Pedrol
d950134c53 libgtp: announce pdp ctx deletion upon CreatePdpCtx being rejected
The libgtp application  may have already allocated related resources
associated to the pdp context, so we need to signal its deletion in
order to let the application free the resources.

This should fix the duplication of pdp contexts seen in osmo-ggsn when
"show pdp-context" related VTY commands are used.
It was spotted due to some MS requesting a v4v6 context on a
v4-only APN, where first v4 address was allocated, and then upon v6
allocation create_context_ind() called
gtp_create_context_resp(GTPCAUSE_MISSING_APN) but the first address was
not freed. Upon receiving the callback, osmo-ggsn should now free the
related resources.

Related: OS#4154
Change-Id: I6c6215a4ce478afabc78ffaf5ffb0cf829e41226
2019-08-23 14:39:35 +02:00
Pau Espin Pedrol
623c5b36e9 libgtp: Remove packets in tx queue belonging pdp being freed
Doing so should avoid the crash seen in OS#3956, where a message is
received in osmo-sgsn gtp iface after having received a DeleteCtxAccept
message where pdp and associated cbp is freed. As a result, when new
confirmation arrives, it can still be matched against an old request and
be sent to upper layers providing an already freed cbp.

With this patch, since all queued messages belonging to that pdp are
dropped, confirmation won't find a match and be discarded in libgtp.

In order to be able to drop all req messages belonging to a pdp, a new list
is added to pdp_t and qmsg_t are added to that list when inserted into the per-gsn
req transmit queue. This way upon pdp free time it's simply a
matter of iterating over that list to remove all messages.

There's no need to do same for resp queue, and it'd be actually
counter-productive, because it wouldn't be possible to detect and
discard duplicates anymore after pdp ctx has been freed.

Related: OS#3956
Change-Id: Id86d0b241454d3ad49c64c28087fd2710fa2d17a
2019-08-23 14:38:56 +02:00
Jan Engelhardt
aab47afe58 build: switch AC_CANONICAL_TARGET for AC_CANONICAL_HOST
$target/$target_os is never used, so AC_CANONICAL_TARGET is useless.
$host is, so employ AC_CANONICAL_HOST.

Change-Id: I6dc505888b42cfb686043470d3a3548c24cbe1f7
2019-08-15 14:12:00 +02:00
Pau Espin Pedrol
67aebc9d1c Bump version: 1.3.0.50-ea1c-dirty → 1.4.0
Change-Id: I5ca7ada037a9b91c3b747cea6d83654d0b9afed3
2019-08-07 21:28:30 +02:00
Pau Espin Pedrol
ea1cb3fa33 Require libosmocore 1.1.0
Older commit made use of gsm48_decode_bcd_number2(), which is available
in libosmocore 1.1.0 onwards, but forgot to increase configure.ac
requirements.

Fixes: fb62504160
Change-Id: I89b37be55fc4ba22b90e9aab9a5989573df2ae38
2019-08-07 21:27:00 +02:00
Pau Espin Pedrol
0036a60c44 Remove undefined param passed to {logging,osmo_stats}_vty_add_cmds
Since March 15th 2017, libosmocore API logging_vty_add_cmds() had its
parameter removed (c65c5b4ea075ef6cef11fff9442ae0b15c1d6af7). However,
definition in C file doesn't contain "(void)", which means number of
parameters is undefined and thus compiler doesn't complain. Let's remove
parameters from all callers before enforcing "(void)" on it.
API osmo_stats_vty_add_cmds never had a param list but has seem problem
(no "void"), so some users decided to pass a parameter to it.

Change-Id: I0a89586ce683ad060212355b37470c349992ec49
Related: OS#4138
2019-08-05 17:47:55 +00:00
Pau Espin Pedrol
e47932976c sgsnemu: Fix unaligned pointer access during ip/icmp checksum
Catched by gcc 9.1.0:
osmo-ggsn/sgsnemu/sgsnemu.c:1294:2: error: converting a packed struct ip_ping pointer (alignment 1) to a uint16_t {aka short unsigned int} pointer (alignment 2) may result in an unaligned pointer value [-Werror=address-of-packed-member]
 1294 |  p = (uint16_t *) & pack;

Change-Id: I783f104c31234a07f2a13f6dbc577a71b25b36a7
2019-07-29 18:06:20 +02:00
Harald Welte
f1e01517bc sgsnemu: Fix format string argument count
Change-Id: I6bb8c3df53a585913d5e0351ecad2e6ae9f0b886
Closes: CID#178643
2019-07-21 12:36:27 +02:00
Oliver Smith
ad252e70aa contrib/jenkins.sh: run "make maintainer-clean"
Related: OS#3047
Change-Id: I0ad159a3973d28ac79ea7fb433401c72b247c2b0
2019-07-10 12:25:35 +02:00
Pau Espin Pedrol
08ca425bc2 configure.ac: some versions of linux/if.h require including sys/socket.h
Related: OS#3230
Change-Id: Iba869a75745cea01024fa3ce04917c02fa608a13
2019-07-01 12:14:13 +02:00
Pau Espin Pedrol
1eeb113c34 configure.ac: Use prefered AC_CONFIG_HEADERS over AM_CONFIG_HEADER
This macro is preferred by autofoo upstream. It was added around
automake 1.7, and offers backward compatibility with AM_CONFIG_HEADER.

Related: OS#3230
Change-Id: I88707d4895d9c231715d5252d2cfab589b42fe0c
2019-07-01 12:13:56 +02:00
Pau Espin Pedrol
d0ba664fec configure.ac: Use brackets in AC_INIT params
Change applied as a result of running "autoupdate".

Change-Id: I955b535737f0a0cbdf25377609cec8f3d8d3eb45
2019-07-01 12:13:56 +02:00
Pau Espin Pedrol
ec1d8c4004 configure.ac: Replace obosolete macro AC_CANONICAL_SYSTEM
$ autoconf -Wall
configure.ac:11: warning: The macro `AC_CANONICAL_SYSTEM' is obsolete.
configure.ac:11: You should run autoupdate.

autoupdate applied the change present in this commit.

Change-Id: Iee59e6e9a7670867d5bc55ba96f79130bc6982f6
2019-07-01 12:13:56 +02:00
Pau Espin Pedrol
36e12d4db8 ggsn: Use structures instead of raw arrays when parsing ipcp_hdr
We have a structure to handle that data type, so let's use it.

Change-Id: I991e53544b733df7773d66280ffa19a2a5123d97
2019-07-01 12:13:56 +02:00
Pau Espin Pedrol
2404c5b0b7 ggsn: Avoid unaligned mem access reading PCO proto id
Change-Id: I3d80833319869503691a52927892e6ac30744915
2019-07-01 12:13:56 +02:00
Harald Welte
32b76ee1af ggsn: More logging from PCO handling (e.g. in case of malconfiguration)
Change-Id: I38c2c4178ff4fd795f54638adec63166b1c0838e
2019-07-01 12:13:56 +02:00
Harald Welte
7bdc80de00 ggsn: Add minimalistic PAP support
Some modems are configured to use PAP as an additional authentication
mechanism beyond the GSM authentication that's part of GMM.  Let's
handle such PAP authentication requests by simply acknowledging them
all, without actually checking any credentials database.

This is the most sane thing we can do for now, without adding external
requirements / interfaces like radius servers or the like.

Closes: OS#3914
Change-Id: I81875f30f9f1497199253497f84718510747f731
2019-07-01 12:13:51 +02:00
Pau Espin Pedrol
83f5266f43 gtp: queue: Add unit test queue_test
Closes: OS#1740
Change-Id: Id09bc5e23aa7a4b864822bc92cc23a4b60db52c3
2019-06-21 11:57:50 +02:00
Pau Espin Pedrol
e725d87d13 gtp: queue.c: Document queue APIs
Change-Id: I8523a0d0508d7fb870a4a9119aa8eb4c3a4d6f17
2019-06-20 16:47:11 +00:00
Pau Espin Pedrol
8b90bce962 gtp: Add missing headers
Those headers are using types defined in other places (like sockaddr_in)
and don't explicitly include them, which makes future queue_test fail.

Change-Id: I65e12a067d89ef71be3719636b64f4d93ea73cc4
2019-06-20 17:08:13 +02:00
Pau Espin Pedrol
f0829ff34b cosmetic: gtp: queue: remove trailing whitespace
Change-Id: I20c83cd607ae8e1025fdc1a810c0d27bad80b178
2019-06-20 17:08:06 +02:00
Daniel Willmann
e589c6544c manuals: Add script to regenerate vty/counter documentation
Related: OS#1700
Change-Id: I2f51ff19d2a1d7bcfdf569309a79a6e91a848302
2019-06-19 11:33:38 +02:00
Pau Espin Pedrol
d1a2ddfee6 sgsnemu: Replace use of deprecated libgtp API pdp_newpdp with new one
Related: OS#2873
Change-Id: I9742b82c382ae2e63f8aff4c5c32e2450059082b
2019-06-04 17:46:15 +02:00
Pau Espin Pedrol
7b52f00192 ggsn: vty: Require ggsn param in <show pdp-context> cmd
Other similar commands already do it. This way we also get rid of
deprecated APIs, supporting search when more than one GSN is set up.

Related: OS#2873
Change-Id: I8357e20076348c8ded5e9f5b8e7252566b0fbfea
2019-06-04 17:45:36 +02:00
Pau Espin Pedrol
25ab381c0f ggsn_vty_reference.xml: Update from last code changes
Change-Id: I5de2e5223e4532bbbec77b928fbdecb57ef2bca7
2019-06-04 17:45:36 +02:00
Pau Espin Pedrol
9fbcb10568 gtp: Make use of new libgtp APIs with multi-gsn support
Drop use of deprecated APIs everywhere in libgtp and use the new ones instead.

Related: OS#2873
Change-Id: Ibf56a063f01d1f95a2a3271416da6e062e85fdfa
2019-06-04 17:45:06 +02:00
Pau Espin Pedrol
eefa30dce8 gtp: Introduce new pdp APIs (and deprecate old ones) to support multiple GSN
Move static global pdp storage arrays to be per GSN. This way now
several GSN per process are supported without collisions.

* pdp_init() is defined in public API but it's actually only intended
for use (and currently only used) internally in gtp_new(). So let's
document that and re-use it for backward compatibility with now
deprecated API, where only one GSN per process is supported.

* Back pointer to gsn_t (pdp->gsn) moved from gtp.c:gtp_new() to
gtp_pdp_newpdp(), since it makes more sense to have it there. This way
backpointer is always set, even in case were app calls pdp_newpdp() API
directly instead of creating them through gtp.c, like osmo-sgsn does.

* Create new versions of required APIs with a pointer to gsn_t where the
pdp ctx is to be created/found. Some APIs receiving a pointer to a pdp
ctx can be left intact because we have a backpointer to its gsn_t.

* pdp_getpdp() is nowhere used, and makes little sense now that we have
pdpa reachable in gsn->pdpa, so let's deprecate it without adding a
replacement.

* Deprecate gtp.h gtp_newpdp(), since it's nowhere used and useless
(does same as new gtp_pdp_newpdp() and doesn't allow for old_pdp to be
passed as parameter).

Fixes: OS#2873
Change-Id: I653cbdc185165592d985e3efab6e3f1add97877b
2019-06-04 17:42:16 +02:00
Pau Espin Pedrol
5560001af5 ggsn: Fix undefined behaviour shifting beyond sign bit
Fixes following ASan complaint during VTY "show running-config":
osmo-ggsn/ggsn/ggsn_vty.c:657:37: runtime error: left shift of 1 by 31 places cannot be represented in type 'int'

Change-Id: I2b8d163dbc108b0fb5a1e820dc23181835d12869
2019-06-04 08:43:03 +00:00
Pau Espin Pedrol
a469a90d5e cosmetic: gtp.h: Remove trailing whitespaces
Change-Id: I60f8cf5e36bcef767f90b150a488a800445bf744
2019-05-31 16:44:01 +02:00
Pau Espin Pedrol
84515f4b8b pdp: Drop unused code for haship
Nowadays we have one tun device per APN, so we don't need this hash
table because we use the ippool of the APN to find the related PDP ctx
pointer.

Change-Id: Ife3f222daa87f0630ff34ffc3e63f4dad2ad914b
2019-05-31 16:44:01 +02:00
Oliver Smith
1cde2c1691 ggsn: Use gtp_delete_context_req2() everywhere
Replace calls to gtp_delete_context_req() with
gtp_delete_context_req2().

Related: OS#2741
Change-Id: Iecc8c5ac45207e7e20129559c4ac7f3c67dfb36a
2019-05-31 16:44:01 +02:00
Pau Espin Pedrol
93dd798a99 gtp: Re-arrange free pdp ctx code in non-teardown scenario
Code modified actually behaves the same, since gtp_freepdp() also calls
delete cb, and this way it's more consistent with rest of the code base.

Change-Id: I299765816e9d885497110d2e834f7ccdc943052c
2019-05-31 16:42:07 +02:00
Pau Espin Pedrol
8651573632 cosmetic: gtp: Document free pdp ctx in non-teardown scenario
Change-Id: Ia47ac792111fe1e9aa68222b32b5da823642206b
2019-05-31 16:40:39 +02:00
Pau Espin Pedrol
0d0b0592f0 gtp: Refactor code to use gtp_freepdp(_teardown) APIs
* API gtp_freepdp was already there but was not really being used by
anyone currently, so we can change its behaviour to call cb_delete_ctx.
It makes sense to call the cb in there too to be consistent with rest of
APIs.
* Add API gtp_freepdp_teardown, which calls gtp_freepdp on pdp and its
secondary contexts. It will also be used later on by osmo-ggsn.
* Use new APIs in internal code to simplify it.

Change-Id: I9f0b774e9385a7a8d81ec9702f158e2f9a50d571
2019-05-31 16:34:32 +02:00
Pau Espin Pedrol
aad77a0acf gtp_create_pdp_ind: simplify code by reordering and compacting parsing
Move all parsing with same conditions under same blocks to make code
easier to follow and make it more compact.

Change-Id: I52d5a3543ce6cf764bd84303b5a0d8b0643d998d
2019-05-31 16:34:32 +02:00
Pau Espin Pedrol
9ee8d3264b pdp: Introduce new API pdp_count_secondary
Change-Id: Id2d84ad1cdb0f3b500efeda4cc0fbccb24ae0c61
2019-05-31 16:34:32 +02:00
Pau Espin Pedrol
de72d26f49 gtp: Fix typo dublicate->duplicate
Change-Id: Ic572c216e74fa937dfd12f9f3dc03de18b6b123e
2019-05-31 14:25:57 +00:00
Pau Espin Pedrol
ceac078d77 gtp: Take queue_resp into account to schedule retrans timer
Before this patch they were not taken into account, which means some
resp messages could stay more time than required enqueued.

Change-Id: Iebf405b2310a34785f3b363cc2a9f415281f6030
2019-05-31 14:25:57 +00:00
Pau Espin Pedrol
cd87c5f963 ggsn: Start gtp retrans timer during startup
This timer was added in osmo-ggsn.git
dda21ed7d4,
but it was never initially started since it was introducing, and as a
result retransmissions never being triggered.

Also as a consequence, gtp_retrans is never called. That function is
responsible from triggering retransmissions and to free old responses
waiting in the resp queue (to check for duplicates). Since it's never
called, the retransmit resp queue will grow over time.

Fixes: dda21ed7d4
Fixes: OS#3997
Change-Id: Ie4adc52829446539fbbb5e9e0cf75a04f91c7eea
2019-05-31 14:25:57 +00:00
Oliver Smith
154f93da51 debian: create -doc subpackage with pdf manuals
I have verified, that the resulting debian packages build in my own OBS
namespace (see the -doc packages):
https://download.opensuse.org/repositories/home:/osmith42/Debian_9.0/all/
https://build.opensuse.org/project/show/home:osmith42

Depends: Ib7251cca9116151e473798879375cd5eb48ff3ad (osmo-ci)
Related: OS#3899
Change-Id: I5563e023dc3c8b158a79ce0c9e1478e117b0ec37
2019-05-31 14:25:07 +00:00
Pau Espin Pedrol
742a6b55ce gtp: Document spec reasoning drop of Rx DeleteCtxReq
Change-Id: I563fc0b48595d71ebdf56a50f4e9984eee423676
2019-05-30 13:36:56 +02:00
Pau Espin Pedrol
72ab4bc547 ggsn: Drop unused param force in apn_stop()
Change-Id: I920679c7062d480c1cfaa3d89c90a0ed4a2ef58b
2019-05-29 19:09:02 +02:00
Vadim Yanitskiy
fb62504160 osmo-ggsn: properly show subscriber's MSISDN in the VTY
Instead of printing subscriber's MSISDN as a hex-string, let's
attempt to decode it using gsm48_decode_bcd_number2().

Change-Id: I3f3a105dc8d0d582f2b9d8e1ff6c5785369e569b
2019-05-19 02:00:41 +07:00
Vadim Yanitskiy
d7030d268c osmo-ggsn: print requested / actual APN in PDP info
An actual APN can be different from the one that was requested by
user, e.g. when 'default-apn' VTY parameter is used. The one that
was requested is already being stored in the PDP context state.
Let's also store a chosen APN in create_context_ind().

Change-Id: I9cbe195f64e5b83d5158c175aad2e81ba2487850
2019-05-14 08:33:25 +00:00
Vadim Yanitskiy
2e8e57a3de osmo-ggsn: check result of osmo_apn_to_str()
Change-Id: I03d0eb266dca176f342e77a54f0291cc5bd7df43
2019-05-13 22:09:15 +07:00
Vadim Yanitskiy
ca276e01eb osmo-ggsn: add VTY command to show PDP context by IPv4
Change-Id: Iad60de34c562803a1a1fc024287d1a60e071afab
2019-05-13 15:37:02 +07:00
Vadim Yanitskiy
977b339abe osmo-ggsn: fix VTY command for getting PDP contexts by APN
Change-Id: I0a7f4b245c4664afdae83c660358acb1a5f88ce5
2019-05-13 15:36:58 +07:00
Harald Welte
9272d212c3 ggsn.c: Refactor PCO processing during PDP activation
The existing PCO processing is implemented in a rather convoluted
way.  We scan the list of PCO elements several times for different
PCO protocols.  Let's change to a straight-forward model where we
simply do one iteration over the list of PCO elements and generate
responses step by step.

Change-Id: I4a7d09279b6b259e2b95f1f51159b16838b2d94c
2019-04-11 19:41:00 +02:00
Harald Welte
f653c5bc33 ggsn: Fix build_ipcp_pco() in presence of invalid IPCP content
When build_ipcp_pco() iterated over the PCO list, it didn't use
the "outer" pco length as an increment, but used the "inner" IPCP
length.

If an IPCP message with an invalid "inner" length was being processed
(see pcap file attached to OS#3914), the PCO iteration beyond that
broken IPCP would fail, possibly rendering false hits.

Let's make pco_contains_proto() return a pointer to the the pco_element,
so that the caller can use the outer length as an increment.

Change-Id: I8e9cffde092c8c5824abfaeecb742afcf949802c
Related: OS#3914
2019-04-11 19:27:17 +02:00
Harald Welte
549417e675 ggsn: Remove magic numbers from ipcp_contains_option()
Let's remove some magic numbers and use a data structure instead.

Change-Id: I5b1abc6f403f85986407e9e8359924dfcb58031a
2019-04-11 19:27:17 +02:00
Harald Welte
42c9fa4958 ggsn: const-ify input / read-only arguments of PCO related functions
Change-Id: Ia0877988180ded4e3c033d7f1fb6e1c2acd60163
2019-04-11 19:27:17 +02:00
Harald Welte
df404c4296 ggsn: Remove magic numbers from pco_contains_proto()
Let's remove some magic numbers and use a data structure to describe
the PCO element header.

Change-Id: I9871ffced677320aa82438332bfdb951ab129f04
2019-04-11 19:27:17 +02:00
Harald Welte
ffa227307c process_pco() const-ify 'apn' argument
Change-Id: I2a96b0fbe077c7c49342553de0880bfc58318669
2019-04-11 14:59:51 +00:00
Max
3fc9cc97de Don't return error on normal shutdown
Previously we've always returned error code from main() even in case of
regular expected shutdown. Let's not confuse it with actual error
shutdown and return 0 by default.

Change-Id: I7fe0d3e052953d5b87ce65649d88d83476fee3c0
2019-03-14 11:16:55 +01:00
Harald Welte
f5a268a96d Bump version: 1.2.2.44-6da8-dirty → 1.3.0
Change-Id: Ie12af1d57df178a9ab27937ef0b764c98dd96e32
2019-01-20 21:34:23 +01:00
Oliver Smith
6da888c5d0 contrib: fix makedistcheck with disabled systemd
EXTRA_DIST files need to be distributed, no matter if the systemd option
is configured or not.

Change-Id: Ibd348eac3adca88663bd510172efbe4ec0bf3599
2018-12-06 13:43:26 +01:00
Oliver Smith
33c537e5a7 contrib/jenkins.sh: build and publish manuals
Add new environment variables WITH_MANUALS and PUBLISH to control if
the manuals should be built and uploaded. Describe all environment vars
on top of the file.

When WITH_MANUALS is set, install osmo-gsm-manuals like any other
dependency and add --enable-manuals to the configure flags (for "make"
and "make distcheck"). Add the bin subdir of the installed files to
PATH, so osmo-gsm-manuals-check-depends can be used by ./configure.

Related: OS#3385
Change-Id: I43e3b592c593237eb4df2d70c926c031ddb7b20b
2018-12-05 13:16:14 +01:00
Oliver Smith
aa69034c00 Fix DISTCHECK_CONFIGURE_FLAGS override
Set AM_DISTCHECK_CONFIGURE_FLAGS in Makefile.am instead of
DISTCHECK_CONFIGURE_FLAGS. This is the recommended way from the
automake manual, as otherwise the flag can't be changed by the user
anymore.

Related: OS#3718
Change-Id: I810b2b96ea077e8bd5ab01df5137e214a4349628
2018-12-04 15:33:20 +01:00
Oliver Smith
bf47f71785 build manuals moved here from osmo-gsm-manuals.git
Moved to doc/manuals/, with full commit history, in preceding merge commit.
Now incorporate in the build system.

Build with:

$ autoreconf -fi
$ ./configure --enable-manuals
$ make

Shared files from osmo-gsm-manuals.git are found automatically if
- the repository is checked out in ../osmo-gsm-manuals; or
- if it osmo-gsm-manuals was installed with "make install"; or
- OSMO_GSM_MANUALS_DIR is set.

Related: OS#3385
Change-Id: I14533676d5774ee0d0ee5054ba77d7dac32cff43
2018-11-27 18:28:24 +01:00
Neels Hofmeyr
2b7a860ffb Merge history from osmo-gsm-manuals.git
Change-Id: Ic7cebd4e6f2836be80a6186939f98057969207d4
2018-11-27 18:27:58 +01:00
Neels Hofmeyr
932eeec240 ggsn: update vty reference
Change-Id: I8a5c37505c0180d5c04c7792d6d0afdb0dffb282
2018-11-27 18:27:47 +01:00
Harald Welte
6f7aabf6a3 vty-ref: Update URI of docbook 5.0 schema
... to match the /etc/xml/catalog file on debian (no "www" in hostname)

Change-Id: Id9f3579c7f2bc3af13fe30b5268f249b6f59ed0d
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
a491e42129 OsmoGGSN: update vty reference
Add new (generic) logging commands, talloc context print commands.
Add the jitter buffer logging category.

Change-Id: Ifdc735df6221bf6e9b6247912f2958974dcfc4f2
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
1ce111f72b OsmoGGSN: fix VTY additions' node IDs
Change-Id: I8cd5eb64300151d0de8023ed019568cfdc4fe453
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
e010dea56e OsmoGGSN vty: update VTY reference
Apply VTY reference changes from libosmocore: change node IDs from index
numbers to meaningful names from VTY node prompts.

Introduce section with common commands, do not repeat the common commands on
each child node.

Populate section names (so far empty).

Add apn / gpdu VTY reference.

This is generated using the recent libosmocore vty doc patches that conclude in
libosmocore change-id Iedd67750539b676271de0e0e9316d4e6f794406a.

Change-Id: Ia269c4bda0aa0b905abcccc75338f5f808e01727
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
f4530447f6 OsmoGGSN VTY ref: prep: convert newlines to unix
To omit whitespace changes in an upcoming patch that updates the VTY reference
and will use '\n' line breaks, convert line breaks from '\r\n' to '\n' without
any other changes.

Change-Id: Id0d1a3a82c3d670cbb041884554b5d79fdfb0f28
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
e7361067ac OsmoGGSN: typo: priveleges
Change-Id: Id7e59f5dfcbb632fde6c35ef014e9b85099fe06d
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
606837597f OsmoGGSN: add Routing section for IP forward and masquerading
Change-Id: Ie49ca7a45113f49e89ce09017500008cbec757f5
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
5f8b332e6b OsmoGGSN: multiple instances: mention GTP port
Change-Id: I781feeb955ace17d93206bc98d12bc423584ce32
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
43001cbc7a OsmoGGSN: more info on non-root operation / tun creation
Add examples for 'ip addr add' and mention correspondence to config file,
add examples for enabling masquerading and IP forwarding,
place the non-root config in its own section and highlight the diffs.

Add tiny hint at systemd-networkd.

Change-Id: I02bd9cfa35c7f2fb338d5d92c2e968fe80574a78
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
65d61c347b GGSN: don't say 'NITB'
Change-Id: I960ce8ee749621176ceaa556a1fe93b54e08b6fc
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
c8ca02b937 refactor Makefile build rules, don't use the FORCE
The initial goal was to make sure we don't have overall FORCE rules causing
unnecessary rebuilds -- annoying while writing documentation. As I looked
through possible dependencies, I finally understood what's going on here.

Remove code dup and nicely sort which belongs where in build/Makefile.*.inc. In
each, describe in a top comment how to use it, and also unify how they are
used:

- Rename Makefile.inc to Makefile.docbook.inc and refactor
- Add Makefile.vty-reference.inc
- Add Makefile.common.inc

Make sure that we accurately pick up all dependencies.

Drop use of the macro called 'command', that silenced the actual command lines
invoked and replaced them with short strings: it obscures what is actually
going on and makes the Makefiles hard to read and understand.

Each manual's makefile is greatly reduced to few definitions and a Makefile
include, e.g. one for asciidoc, one for VTY reference.

Move common/bsc_vty_additions.xml to OsmoBSC/vty/libbsc_vty_additions.xml, link
from OsmoNITB. It applies only to OsmoBSC and OsmoNITB.

Add a script that combines a VTY reference file with *all* additions files
found in a manual's vty/ dir. Call this from Makefile.vty-reference.inc.

Change-Id: I9758e04162a480e28c7dc83475b514cf7fd25ec0
2018-11-27 18:27:47 +01:00
Harald Welte
3ce5a3648a GGSN: Document how 'ip tuntap' is used for non-root; call netdev 'apn0'
* Some people want to manually create/configure their tun devices,
  show them how to do this using ip with the correct parameters
* Let's not call the network device 'ggsn' but rather 'apn0', as
  the device has a 1:1 correspondence to the APN, not to the GGSN.

Change-Id: I2fef818bfcb8cb521397136539f492922d5f6def
2018-11-27 18:27:47 +01:00
Max
a4cb02699e Expand OsmoGGSN manual
* add cross-references
* add example of running without root priviledges

Change-Id: I1743f370ee2b351d2847f2e29e0f59f35cd401f4
2018-11-27 18:27:47 +01:00
Harald Welte
f0fb2c2ddd OsmoGGSN: Add VTY reference manual
Change-Id: Iddf6fe26689172d7db001198943c816eaaed7931
2018-11-27 18:27:47 +01:00
Harald Welte
8a1e7b8658 initial version of OsmoGGSN user manual
Closes: OS#1721
Change-Id: I7cdf150e8dd4f9dfc5e6d28e780d05dc1e1e5458
2018-11-27 18:27:47 +01:00
Neels Hofmeyr
b7782d4d41 Importing history from osmo-gsm-manuals.git
Change-Id: I79f406ae78de4a82966cffebac0dcec2abab21c2
2018-11-27 18:27:29 +01:00
Stefan Sperling
b0b9c28284 properly store IPv6 addresses in struct tun_t
All addresses in struct tun_t were stored as an in_addr.
But IPv6 addresses need an in6_addr, so switch tun_t addresses
to the in64_addr wrapper struct.

This is an ABI break, as documented in TODO-RELEASE.

Fixes an out of bounds memcpy() identified by Coverity.

Change-Id: Idd2431ad25d7fa182e52e2bd5231ceb04d427c34
Related: CID#174278
2018-11-22 14:12:40 +00:00
Stefan Sperling
3730c550cd fix a format string directives in queue_seqset()
Coverity pointed out that a format string used inappropriate
format string directives for variables of type size_t.

Change-Id: I889019aad963932fdc032421e60a72c809a93bca
Related: CID#135197
2018-11-22 13:17:18 +00:00
Stefan Sperling
cc8181fefe fix format string error in ippool_printaddr()
The variable this->listsize is an unsigned int, but the format
string assumed ptrdiff_t. Found by Coverity.

Change-Id: Ib2a55907adae98f8aa7b079f1c9a3b4fc5f67fc5
Related: CID#188879
2018-11-22 13:17:01 +00:00
Stefan Sperling
7327360d10 initialize local variable addr in ippool_new()
Coverity points out that addr.len was potentially being used
uninitialized, via calls to in46a_inc(&addr).

Change-Id: Idb67394e5f4c2072380a33f46c848d92c4317245
Related: CID#174189
2018-11-22 13:16:50 +00:00
Stefan Sperling
e405c2f196 replace bogus memcpy() call in ippool_newip()
When copying an address to a reused static hash table member
with memcpy(), this code mistakenly passed the size of a
pointer as the amount of bytes to be copied, rather than
the actual size of the address.

This means the IP pool could contain bogus IP addresses because
only addr->len (a uint8_t) and 3 further bytes of the address
were actually copied on 32 bit platforms. On 64 bit platforms,
a sufficient amount of bytes were copied for IPv4 to work
correctly, but too few bytes were copied for IPv6.

This problem was found by Coverity.

Replace the bogus memcpy() call with direct assignments to the
appropriate struct in64addr union members, and assert that the
length recorded for the address actually corresponds to the
length used by the address family (IP4, IPv6).

Change-Id: Ic21560f7519e776107485a8779702fb1279d065c
Related: CID#57921
2018-11-22 13:16:29 +00:00
Stefan Sperling
411ff3b984 fix allocation of ippool's hash table
The calloc() call in ippool_new() had two problems.

The first problem is benign: The order of arguments were reversed.
Pass the number of elements in the array first, then the size of
each element, as calloc() expects.
This problem was found by me. There are more instances of this
problem in this file, which I'll address in follow-up patches.

The second problem is that the requested allocation was larger than
necessary: The hash table is an array of pointers to ippoolm_t, not
an array of struct ippoolm_t. Fix the required size passed to calloc().
This problem was found by Coverity.

Change-Id: I93fa5bc539771ca19714f6a665558c9140e2ce07
Related: CID#57920
2018-11-22 07:00:54 +00:00
Stefan Sperling
aee905b790 check ioctl() call return value in tun_new()
Coverity complains about a missing ioctl() return value check.
Check for failure of the TUNSETNOCSUM ioctl and log a warning
if it fails.

Change-Id: I88da2164d975d7a232619b8d31c5eadeef0f3a80
Related: CID#57661
2018-11-21 14:14:10 +01:00
Harald Welte
fb75adfeda ippool.c: Use "%td" format string for ptrdiff_t
Change-Id: Iacafa0919baebac6b5a799deb41a673c022c6743
Fixes: Coverity CID#135225
2018-10-21 13:30:07 +02:00
Harald Welte
7b9230acfe sgsnemu: Fix printing of tun device name
Change-Id: I6cd89b7b59a6c1d506cfbe9d3088cb844d133313
Fixes: Coverity CID#178638
2018-10-21 13:30:07 +02:00
Harald Welte
5662cb2152 osmo-ggsn.cfg: Ensure well-formed config file example
Change-Id: Ic7fd91745e7442eda741d46748c0a4a02dedef80
2018-09-25 18:52:02 +00:00
Alexander Couzens
e1412d9493 libgtp: implement gtp_clear_queues to clear req/resp queue
Clearing the request and response queue is useful for debugging
to reset "some" state. Otherwise some tests will get un-expected
packets.

Change-Id: I279d1d7cbf5d37dd5609c2b968f317fe9a0e348d
2018-09-16 10:30:10 +00:00
Pau Espin Pedrol
d1e2342f91 Install sample cfg file to /etc/osmocom
Change-Id: If41e69295ac23a61df138ceea83794059f111086
2018-09-12 18:37:08 +02:00
Pau Espin Pedrol
381b723543 Install systemd services with autotools
Change-Id: I563559f5b501eded44efafc60bb0c9ffdea20b3e
2018-09-10 16:10:05 +02:00
Harald Welte
ee44b82b96 debian/rules: Don't overwrite .tarball-version
The .tarball-version file should contain the *source version* uniquely
identifying the git commit, and not the Debian package name.

With https://gerrit.osmocom.org/#/c/osmo-ci/+/10343/ there is a correct
.tarball-version file in the .tar.xz of the nightly source packages.

Change-Id: I1466936033c2f60edd1078eb41f3508d87da4402
Related: OS#3449
2018-08-06 11:15:00 +02:00
Pau Espin Pedrol
b5f93346df gtp: Add new replacement cb_recovery2 for cb_recovery
Sometimes the originating pdp ctx causing the Recovery Procedure is
required, in order to drop all pdp ctx but this one, which specs specify
should be handled as valid:
"""
The SGSN receiving the Recovery information element shall handle it as when an
Echo Response message is received but shall consider the PDP context being created as active if the response indicates
successful context activation at the GGSN.
"""

Change-Id: I53e92298f2f6b84d662a3300d922e8c2ccb178bc
2018-07-23 11:25:53 +02:00
Pau Espin Pedrol
8e8c7ef3c7 gtp: Add new API to avoid freeing pdp contexts during DEL CTX REQ
With this API, user is expectd to free the PDP ctx when the confirmation
for the release has been received (cb_conf time). This way user can
maintain the pdp ctx alive during all this time. Extra code is added to
gtp_delete_pdp_resp() since it's now possible to match it and push it up
to the user cb_conf.

This way, cb_conf() can be used for locally-initiated DEL CTX REQ, while
delete_context() cb is left for remotely-initiated DEL CTX REQ. In this
later case, when the DEL CTX RESP is sent the ctx is deleted and the
delete_context() is called, where the user can do related actions or
trigger consequence events (in the case of SGSN, it will drop all
related GGSN bits for that PDP ctx and forward the DEACT PDP CTX to the
MS).

Change-Id: I29d366253bb98dcba328c7ce8aa3e4daf8f75e6c
2018-07-21 17:22:54 +00:00
Stefan Sperling
57238889eb fix support for multiple IPCP in PDP protocol configuration options
Parse multiple IPCP IEs embedded in Protocol Configuration Options,
and return IPCP responses for all of them. Makes the associated
TTCN3 GGSN test pass.

Depends: Ia1410abb216831864042f95679330f4508e1af3d
Change-Id: I51ecab4e35f3ee638e68ca773b0da90cc0294ab0
Related: OS#3319
2018-07-19 19:45:01 +02:00
Stefan Sperling
d70ab97fa4 fix unaligned access in build_ipcp_pco()
IPCP data can begin at any byte location in the pco_req->v array.
Casting to a 'struct ipcp_hdr' pointer could lead to unaligned access.
Parse IPCP data with u_int8_t pointers instead to avoid this problem.

Add some length checks while here.
pco_contains_proto() and ipcp_contains_option() now receive the minimum
size of the data the caller is looking for, and only return pointers
to items of sufficient size.

Also fix an inifinite loop in ipcp_contains_option() by refusing
IPCP options with length small than 2. Previously, a zero length
option would trigger an infinite loop in the parser.

Change-Id: Ia1410abb216831864042f95679330f4508e1af3d
Related: OS#3194
2018-07-19 19:37:41 +02:00
Pau Espin Pedrol
d1bd6fce9c gtp: Log ignore CTX DEL REQ due to no teardown and only 1 ctx active
Change-Id: Ic950c04d309d5686bfbeab332f79c48678e743ae
2018-07-13 19:11:59 +02:00
Pau Espin Pedrol
a32e4c4fb8 gtp: Allow recv DEL CTX REQ in sgsn and DEL CTX RSP in ggsn
According to 3GPP TS 29.060 section "7.3.5
Delete PDP Context Request", both directions are valid in both GSNs.

This allows osmo-sgsn receive delete ctx indication (cb_delete_context)
in order to implement GGSN initiated requests.

Change-Id: I6927c07be4ddf74defe338d01d947056e15cd14d
2018-07-13 19:05:03 +02:00
Pau Espin Pedrol
3b84e92ab3 gtp: Log type name of unexpected signalling message
Change-Id: Iae0f045e4128cf97aa7824d7d774b59bf966cbe8
2018-07-13 18:32:38 +02:00
Pau Espin Pedrol
3e0baa6146 ggsn: ctrl iface: listen on IP configured by VTY
Previosuly, the CTRL iface of osmo-ggsn was always bound to 127.0.0.1

Fixes: OS#3287
Change-Id: I9b2c1b310c7dc94ef09642f7f256ae259b41619d
2018-06-19 11:52:00 +02:00
Pau Espin Pedrol
b673d1c438 Bump version: 1.2.1.3-6a28 → 1.2.2
Change-Id: Idbc183ca37196082e95a107901bea53d37aa2ff3
2018-05-31 12:44:54 +02:00
Philipp Maier
6a2856bab5 ggsn: make sure ipcp_option_hdr and and ipcp_hdr are packed
struct ipcp_option_hdr and struct ipcp_hdr are not declared as
packed explicitly, but they are used to parse memory blobs by
casting pointers.  Add __attribute__((packed)) to ensure that
those structs are stored packed.

Change-Id: I14e10bb3ce482347b3f0c4d3a75168a55df15f20
Related: OS#3288
2018-05-28 17:50:09 +02:00
Philipp Maier
0d95ca59f9 ggsn: fix misinterpreted length field in ipcp_contains_option()
The abort condition of the while loop in ipcp_contains_option()
is accessing ipcp->len directly. Unfortunately this field is an
uint16_t which as to be interpreted as little endian value. If
it is used without prior conversion the value may appear larger
than actually intended and the loop will then not stop at the
end of end of the buffer.

This can cause unpredictable results when the value given with
the parameter enum ipcp_options opt is not found.

The loop will then eventually cause a segmentation fauld or
is likely to hang as soon as cur_opt->len points to a zero
byte in memory.

- Make sure that ipcp->len interpreted correctly by accessing
  it through ntohs()

Change-Id: Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5
Related: OS#3288
2018-05-28 17:48:19 +02:00
Vadim Yanitskiy
906c2099da ggsn_vty.c: fix: use CONFIG_NODE as parent by default
There are some configuration nodes, which are handled by extenral
libraries, such as libosmoctrl. So, when switching back to the
parent node, this should be kept in mind.

Change-Id: I65be7910dc46166caa34a0984a6763e1477dec99
2018-05-09 23:13:09 +07:00
Pau Espin Pedrol
ac07625086 Bump version: 1.2.0.1-36c4 → 1.2.1
Change-Id: I4a8bdcbee300296496f039b90795ff981018e17d
2018-05-04 12:19:58 +02:00
Pau Espin Pedrol
36c4fac9c9 debian/rules: Fix debian packaging after 1.2.0 release
The 1.2.0 release bumped lib version to 3 and updated the debian package
file accordingly, but forgot to increase dh_strip line in debian/rules.

Change-Id: Ib54f231943348c06acecd6f413b2c96b24f6db28
2018-05-04 11:28:24 +02:00
Pau Espin Pedrol
a06b2d3877 Bump version: 1.1.0.90-5468-dirty → 1.2.0
Change-Id: I2af8c8ff75d5153456b814b9dfe4fbddafe5af7a
2018-05-03 16:05:28 +02:00
Harald Welte
546884d9a1 ggsn: don't use gtp_kernel_tunnel_{add,del}() for userspace tun
Change-Id: I00cc8eb8c4d44532f975f78783ff4e12814b3416
2018-04-25 21:44:50 +02:00
Harald Welte
f2286395e9 Move kernel GTP support from ggsn/ to lib/
This way, the IP address / route handling between TUN devices and kernel
GTP can be shared, which will provide not only a unified codebase but
also a more consistent behavior.

This also paves the road for to use kernel GTP from sgsnemu in the future.

Related: OS#3214
Change-Id: Ic53a971136edd0d8871fbd6746d7b0090ce3a188
2018-04-25 21:44:46 +02:00
Harald Welte
9eebe15cd1 lib/tun: Remove tun_setaddr() API, as everyone is using tun_addaddr() now
Change-Id: I02e057d30b6773c17ea6bc31094e53587971e9e7
2018-04-25 21:41:43 +02:00
Harald Welte
31e1dab2c0 sgsnemu: Convert from tun_setaddr() to tun_addaddr()
This converts the last caller of tun_setaddr() outside of lib/tun.c to
use tun_addaddr().

Change-Id: Ia301d6a4ee3d02c1af1c85f2fe1041d3013268b0
2018-04-25 21:41:43 +02:00
Harald Welte
db0366c9e4 ggsn: Don't explicitly use tun_setaddr() API anymore
tun_addaddr() internally contains a fallback to tun_setaddr() for the
first address, so we can unify the API usage a bit and use tun_addaddr()
from all call sites

Change-Id: I34de003a1a040254bd38b29e48caea34cb0c88d2
2018-04-25 21:41:43 +02:00
Harald Welte
47adad0817 lib/netdev.c: Cosmetic changes (coding style / cleanups)
Change-Id: I60cbca616a4f727e2374c52715f9286a0f4c5e4b
2018-04-25 21:41:43 +02:00
Harald Welte
c5efb5bccb lib/tun: split generic network device related stuff to lib/netdev
Change-Id: Ib021e392637a43d5cf1b40e0d50621fe7e854ba5
2018-04-25 21:41:41 +02:00
Harald Welte
9a6da455b9 lib/tun.c: Generalize tun_{set,add}addr*() functions
There's nothing really tun-specific about the adding and removing of
addresses to network devices.  Let's generalize the related code.

Change-Id: I139a950dd81a4b1199953be1608cd109a060f562
2018-04-25 21:40:30 +02:00
Harald Welte
b4c0828039 lib/tun.c: generalize tun_*route() to netdev_*route()
There's nothing specific to tun devices in adding a route to the kernel.

Change-Id: Ib077934aa5f3c9bed06e2cf16a980c965a7a046d
2018-04-25 20:46:05 +02:00
Harald Welte
df3dcac439 lib/tun.c: Generalize tun_sifflags() to netdev_sifflags
There's nothing "tun" specific about that function, let's clarify that.

Change-Id: Iae7ced700245d6c1ac7e9807ab80d12fde8da116
2018-04-25 20:46:05 +02:00
Harald Welte
0757504a86 fix segfault in case of kernel gtp-u
There's a problem during the initial start-up of osmo-ggsn in case
of kernel gtp-u: apn->ggsn->gsn is not yet set while parsing the
'apn' nodes from the config file.  This member is only set after
the last 'apn' node has been parsed at the end of the 'ggsn' node.

Closes: OS#3217
Change-Id: I022a5e5ebc1f155e8f94938856d310462f79bbe8
2018-04-25 20:46:05 +02:00
Pau Espin Pedrol
042a445cf3 use osmo_init_logging2
Change-Id: Ic38fff17cc985238b91999c8acdd92d22fd28c72
2018-04-17 14:31:42 +02:00
Stefan Sperling
a16c7501a4 remove the -f option from osmo-ggsn.service
This option was removed in dda21ed7d4
and the behaviour previously implied by -f has since been the default.

Change-Id: Iba13df713af03771739a4feff4b222a0c3352394
Related: OS#3044
2018-03-20 14:05:34 +01:00
Neels Hofmeyr
9f98822255 jenkins.sh: use --enable-werror configure flag, not CFLAGS
Change-Id: I64e542ad4da34a7ac3bc1b599a122ecff47e892d
2018-03-05 20:53:20 +01:00
Neels Hofmeyr
fc8357a2db configure: add --enable-werror
Provide a sane means of adding the -Werror compiler flag.

Currently, some of our jenkins.sh add -Werror by passing 'CFLAGS="-Werror"',
but that actually *overwrites* all the other CFLAGS we might want to have set.

Maintain these exceptions from -Werror:
a) deprecation (allow upstream to mark deprecation without breaking builds);
b) "#warning" pragmas (allow to remind ourselves of errors without breaking
   builds)

As a last configure step before generating the output files, print the complete
CFLAGS and CPPFLAGS by means of AC_MSG_RESULT.

Change-Id: Ifcde5a110cbed0eaa250dd946927e3b0f4f9bd13
2018-03-05 20:42:45 +01:00
Harald Welte
3e443ca502 Add talloc context introspection via VTY
This requires libosmocore with Change-Id
I43fc42880b22294d83c565ae600ac65e4f38b30d or later.

Change-Id: I460efff3a3dfa2c7d955871aca78b37552a29aff
2018-02-14 00:54:32 +00:00
Martin Hauke
2c10211d60 build: Remove AC_PROG_CXX, C++ is never used
Change-Id: Ifda126ab2e5fdd98317e723aa6b10d964b4519c2
2018-02-14 00:46:41 +00:00
Pau Espin Pedrol
5fdda13f89 sgsnemu: listen param is a host, not an interface
This param is parsed by gethostbyname() and it's confusing to document
it as an interface, because users will then attempt to pass "lo" to it,
which fails.

Change-Id: Id8ef0e12ddcaf8bfd199a44de0ba4280f05d4431
2018-02-14 00:43:22 +00:00
Pau Espin Pedrol
dbeaa044f8 sgsnemu: Fix bad ptr during context deallocation
Older commit switched pdp_t to have an array of 2 peers instead of
only one in order to accomodate for ipv4v6 contexts, which can have 2
addresses assigned. The usage of peer field was not updated in sgsnemu
accordingly, which means the wrong memory portion was being accessed.

Fixes: 2d6a69e69a ("Add support for IPv4v6 End User Addresses")

Change-Id: I9e563522173a82b265e93b1ef9dc93ced40fefa2
2018-02-12 19:11:33 +01:00
Viktor Tsymbalyuk
7ad4d5e8cb sgsnemu: fix: no outgoing GTP-U in "createif" mode
in "createif" mode uplink traffic not forwarding
from tun interface into Gn, inside GTP-U.
create_pdp_conf get iphash (ipm) with pdp ==  0x0
Fix - in create_pdp_conf - instead of casting using already
definned iphash in ipset function.

Change-Id: Icd58450548b3a47cb933d70a2e3166c067552b2c
2018-02-12 14:00:45 +02:00
Viktor Tsymbalyuk
ab4db10750 sgsnemu: created "pinghost" and "createif" modes for mutual exclusion
No warnings when used options from "pinghost" and "createif" groups
in a same time. sgsnemu created tun0 interface and send pings inside
G-PDU, but didn't calculate replys. Added options modes to avoid
mutual exclusion options.

Change-Id: I196df7838212dcddecd64a64a6cba613b6cfced0
2018-02-09 11:17:39 +00:00
Pau Espin Pedrol
dddbbaaee1 ggsn.c: cb_tun_ind: Don't drop packets targeting pdp ctx ll addr
Change-Id: I72602a78baa2a7e3412d8b69c1bf1b3ac0efa434
2018-01-30 22:50:14 +01:00
Pau Espin Pedrol
134855c45e ggsn.c: cb_tun_ind: log dst addr of packet without pdp ctx
Change-Id: Ib3a87ec2b2d0014376295028a648750fa3124485
2018-01-30 22:50:13 +01:00
Pau Espin Pedrol
a4942e6566 ggsn.c: cb_tun_ind: Convert ifelse to switch statement
Change-Id: I4fc97f367ae615cdf0a9501f89419990c2fd4599
2018-01-30 22:49:26 +01:00
Pau Espin Pedrol
4e43ef5ab0 ggsn: Print all addresses on successful pdp ctx creation
Change-Id: I0c57df17d91bade127027e03633494adb6f818c5
2018-01-26 18:20:22 +00:00
Pau Espin Pedrol
4ae8d8232d ggsn: Parse PCO_IPCP for IPv4v6 pdp ctx
pdp_has_v4 only take into account IPv4 EUAs.

Change-Id: I1cf8d6548951e5732075beeea1412d12fb6bdec3
2018-01-26 18:20:22 +00:00
Pau Espin Pedrol
0bdd8bf5bc ggsn: Parse PCO_IPCP
Improvements include:
- Use Identifier received from request instead of using hardcoded id=0.
- Don't add DNS to response if they were not included in request.

Change-Id: Ic8aa5d634e526683b2ad8ed5d14088e171c41c98
2018-01-26 18:20:22 +00:00
Pau Espin Pedrol
5b1ef9589c ggsn: Validate packet src addr from MS
Closes: OS#2422

Change-Id: Ie658a7f161103bb6f631ab0508e45e55fb42a442
2018-01-26 18:20:22 +00:00
Pau Espin Pedrol
7d54ed48e7 ggsn: encaps_tun: Avoid forwarding packet if EUA is unassigned, fix crash
Check (before forwarding received GTP packets into the tun) if the pdp ctx
associated with the packet requested was assigned an EUA of the given IP version.
This way we avoid for instance forwarding an IPv6 packet (or sending
back a response to a Router Solicitation packet) in case the APN was
configured without IPv6 support or if the MS/SGSN didn't ask for an IPv6
while requesting an EUA.

As a side effect, this commit fixes an OSMO_ASSERT hit introduced in handle_router_mcast
in 2d6a69e69a due to a deffective MS
sending an icmpv6 Router Solicitation over IPv6 after having been
requesting and assigned an IPv4 EUA (so no IPv6 packets expected).
Before that commit, there was no crash but the message was being wrongly
answered and used an uninitialized .v6 addr field from the peer struct.

Fixes: OS#2843

Change-Id: Ib6d18a64c2b71f3bcf6cb7e3a978d2d3f9c7a79b
2018-01-26 18:20:22 +00:00
Pau Espin Pedrol
07730bb9cc gtp/gtp.c: Use uint8_t for version param in static functions
Change-Id: I9afc36e2304f1060615219e88dd28821fb74e300
2018-01-26 18:20:21 +00:00
Pau Espin Pedrol
7b38af5cd3 gtp/gtp.c: Mark non exported functions as static
Functions not exported in gtp.h should be static.
There's no need to mark functions as extern in the .c file.

Change-Id: Ie61d5c6e0ae45ef3885911cedf71c826ed1705d0
2018-01-26 18:20:21 +00:00
Pau Espin Pedrol
85ef5833cb gtp/gtp.c: Remove unused function char2ul_t
Change-Id: I0d7493404ea05ce2e795958041bbb6cb75a04d31
2018-01-26 18:20:21 +00:00
Viktor Tsymbalyuk
a2a08f7602 sgsnemu: sgsnemu stopped after recieving "Request accepted" from ggsn
"sgsnemu" stopped with the message "Received create PDP context response. Cause value: 128",
but normaly at that poit it should continue working and create "user plane".
Reason: Funtion "create_pdp_conf" checking result of "in46a_from_eua" and mistakenly
returned EOF when more than 1 IP address provided by GGSN.
Now function "create_pdp_conf" stopped with error when 0 IP provided or error code comes from "in46a_from_eua".
Fixes: 2d6a69e69a ("Add support for IPv4v6 End User Addresses")

Change-Id: I7881b8e1f27c432007cb6e5ff665a2ce55f103b5
2018-01-26 13:30:51 +00:00
Pau Espin Pedrol
282d4e3dda gtp.c: gtp_gpdu_ind: Early return to avoid use of uninitialized var
If the version received is not known, pdp is then uninitalized so we
should not be using it. Let's return an error to inform the caller.

Change-Id: Ib3e23b61a3521bd3c9002d3165ca8eff4361a35e
2018-01-25 18:20:55 +01:00
Pau Espin Pedrol
42d3250d17 gtp.c: gtp_gpdu_ind: Convert ifelse to switch statement
Change-Id: I99b73f7a6d4100789fa92021c6ec9117869c881b
2018-01-25 18:18:07 +01:00
Pau Espin Pedrol
5aed8de11d gtp/pdp: Remove unused APIs pdp_ntoeua pdp_euaton
Change-Id: I00db99ba8de3f3d90e85bf593ed31555eedb439b
2018-01-25 18:09:51 +01:00
Pau Espin Pedrol
5f5fcff5f3 gtp/pdp: Fix trailing whitespace
Change-Id: I1bc65ef9af1144779ee91a2c9b9887233ad15671
2018-01-25 18:09:02 +01:00
Pau Espin Pedrol
a884a95a7b gtp.c: Log unsupported GTP version number
Change-Id: Idbc6e4c912b958bde5916b87ec53c3c4db70bee0
2018-01-25 17:28:26 +01:00
Pau Espin Pedrol
a4aada0b5f gtp.c: Determine GTP version from header
Change-Id: I843071a090e877fd529e1e0b799df3585bf836d8
2018-01-25 17:24:38 +01:00
Pau Espin Pedrol
732131d4d0 gtp.c: Fix trailing whitespace
Change-Id: I636c81d0c0ff53c97e6aedbc00f90c1325a3d607
2018-01-25 17:23:09 +01:00
Harald Welte
36b940d1fe README.md: Remove misleading sentence on sgsnemu
As reported by Viktor Tsymbalyuk, "Use the same LAN switch as the one
your SGSN is connected to." is of course completely bogus.  As long as
you have IP routing in place, it doesn't matter at all which switch you
are using.

Change-Id: I748752337b863b317d2899017b1dc255ced2515d
2018-01-19 15:09:15 +01:00
Max
e661277b48 Add GTP message names
Change-Id: I65eb80db4bcdc6da4d267bef3b907d3f98942a2e
2018-01-17 09:42:40 +00:00
Max
6f539aa259 Fix stow-enabled jenkins build failure
The error is:
CC       gtp-kernel.o
gtp-kernel.c:19:26: fatal error: libgtpnl/gtp.h: No such file or directory
 #include <libgtpnl/gtp.h>
                          ^
compilation terminated.

Fix it by using proper CFLAGS/LIBS for libgtpnl.

Change-Id: I5a24076778ea3ce263ac27211a6f45f935155b33
2018-01-16 16:52:04 +01:00
Max
1c8c62667f Enable sanitize for CI tests
Change-Id: I7559807d54bec5da45ea5c41b10d396d992cb1b7
2017-12-21 17:12:46 +01:00
Pau Espin Pedrol
e5a082d64a ggsn_vty.c: Print ipv6 link-local cmd when writing config to file
Previous commit added the ipv6 link-local vty cmd but forgot to add code
to print its value in config_write_apn.

Fixes: 37c45e3998

Change-Id: I08aeaa98d6dc318b7e9740d837ba4ac48cd7051c
2017-12-15 15:55:32 +01:00
Pau Espin Pedrol
37c45e3998 ggsn: Add 'ipv6 link-local' vty cmd
This vty cmd let's you set up a new link-local IP for a specific APN to
be used during ICMPv6 Router Advertisement procedure.

osmo-ggsn hence requires a link-local IPv6 address to be added to the
tun interface, otherwise the apn will not be configured correctly and it
won't be able to allocate addresses from the ipv6 pool later on.

This feature is useful in case your OS doesn't support autoconfiguring
link-local IPs when the interface is brought up (some linux versions are
known to fail at this) or in case you configured your OS specifically to
avoid automatic set up (sysctl net.ipv6.conf.*.autoconf).

If "no ipv6 link-local" is provided (default), osmo-ggsn will rely on the
OS or the ipup-script setting up the link-local IP for the tun
interface at creation time, then fetching it after ipup-script time and
using the first link-local ip found. On the other hand, if the "ipv6
link-local" cmd is provided, osmo-ggsn will add the link-local IP to the
interface manually and use that one for later Router Advertisement
procedures.

Change-Id: I09ef27f54940d4c47150e5f9016d1cd4298c16b5
2017-12-14 16:01:35 +00:00
Pau Espin Pedrol
f5e40b7011 Set tun_addaddr ipv agnostic and add support for ipv6
sgsnemu (the only user of this API so far) has been modified to use the
new API with in46_addr.

FreeBSD code for IPv6 has not been tested.

Change-Id: Ie36afe6eaf393855a4a708000ef4ad0192bf4767
2017-12-14 14:49:12 +00:00
Pau Espin Pedrol
02e21af657 tun.c: tun_addaddr: Fix segfault and wrong usage of tun_nlattr
First of all, dstaddr can be NULL, avoid copying it in that case.
Second, we want to copy the addr data, not the pointer. I tested it and
the IP was not added (not shown in ip addr) until I copied the content
instead of the address.

Change-Id: I8da637b155f0e913cab6c5b0dde355c9f33375b5
2017-12-14 14:49:12 +00:00
Pau Espin Pedrol
bffc3f9012 ggsn.c: Improve logging info on link-local ipv6 addr not found
Change-Id: I18fb952514712ff30d18c7626f84309055d3efa1
2017-12-14 14:49:11 +00:00
Pau Espin Pedrol
7c4de0776b cosmetic: sgsnemu.c: Fix trailing whitespace
Change-Id: Ic392ed35946e076a39aa5f7bf80a8c2ffe73562c
2017-12-14 14:49:11 +00:00
Pau Espin Pedrol
077b903e11 contrib: jenkins.sh: Build libgtpnl as dep when building with gtp kernel support
Change-Id: I7ee741d4940e3c10a4944b676c9765d6808afba9
2017-12-14 15:29:24 +01:00
Pau Espin Pedrol
2d6a69e69a Add support for IPv4v6 End User Addresses
Before this commit, when an MS requested an ipv4v6 context osmo-ggsn
returned an error stating the type was unknown, and this text was
printed in the log:
Processing create PDP context request for APN 'ims'
Cannot decode EUA from MS/SGSN: f1 8d

This patch has been tested with an MS running the 3 types of addresses:
- IPv4 and IPv6: no regressions observed, the context is activated and
packets are sent to the ggsn.
- IPv4v6: Wireshark correctly parses request and reponse, and then
ICMPv6 traffic from both sides. Finally I see the MS using the IPv4 and
IPv6 DNS addresses advertised and TCP traffic over IPv4 (because
probably my IPv6 network setup is not correct). I also checked I can
disable/enable data (pdp ctx delete and activate) several times without
any issue.

Change-Id: Ic820759167fd3bdf329cb11d4b942e903fe50af5
2017-12-11 11:39:18 +01:00
Harald Welte
4f0343233b ggsn: Ignore PCO with length 0, don't abort processing
The existing code would abort iterating over the list of PCO TLVs
if a TLV of length zero was encountered.  However, there's nothing
in the spec that would make a zero-length PCO invalid, so we should
continue to iterate over any PCO TLVs after the zero-length one.

This issue was discovered while writing test cases in
osmo-ttcn3-hacks.git

Change-Id: I36660566a8ee2ca80ae6ee99c86e167e7c208df2
2017-12-05 17:29:24 +00:00
Harald Welte
bcab7fb4af ggsn.c: Fix byte order of IPCP IPv4 DNS servers
... this probably didn't show up as 8.8.8.8 is dual-endian. doh!

The address was already in network byte order, but msgb_put_u32 "of
course" expects host byte order, ending up the wrong way in the actual
packets :/

Change-Id: Ia4bcac5fcebfc24760432eb66be258a01d78f65f
Closes: OS#2685
2017-12-05 17:29:24 +00:00
Max
427699e6eb Log APN and tun names for packets
Change-Id: I6f7ce33f6585b2b78e2b8a5c0f7111f0316d6ddd
2017-12-05 17:42:09 +01:00
Pau Espin Pedrol
9c0f4f49e9 tests: Split ipv6 specific tests into a new test group
This way they can be easily disabled later on when IPv6 support is made
optional.

Change-Id: I3906dbf55ccf1650083398e08ac870add0bbdcef
2017-12-04 13:25:02 +01:00
Pau Espin Pedrol
ac51c7e68e Remove unused empty src/Makefile.in
Change-Id: I207362e055dbfafc42fad2cfdd0cf1da9dcad88b
2017-12-04 13:25:02 +01:00
Pau Espin Pedrol
55d639f0fb ggsn.c: Print version of unhandled ip packet
Change-Id: I7e226a12b074c96c572f90e3aaf62716d0cd47c5
2017-12-04 13:25:02 +01:00
Pau Espin Pedrol
b9ace14717 cosmetic: Reorder tun_addaddr to get rid of decl of tun_setaddr4
In any case, if we add support for ipv6 in tun_addaddr we will need
tun_setaddr (and also change the API of tun_addaddr to use in46_addr).

Change-Id: Iadf51379455174a642b477040ec96f28022c24c7
2017-12-01 15:40:32 +01:00
Pau Espin Pedrol
d9fff0c543 tun_setaddr6: Fix log typo
Change-Id: Id7f7d33a33730d57c5ecf7ebf5612f4744cf5163
2017-12-01 15:39:28 +01:00
Neels Hofmeyr
1d85bea152 sanitize build: ensure uint16/32 alignment in gtpie_test and in46a_test
Fixes sanitize build failures:

  Testing gtpie_tlv()
  ../../../../src/osmo-ggsn/tests/gtp/gtpie_test.c:30:2: runtime error: load of misaligned address 0x55c0a0830f21 for type 'uint16_t', which requires 2 byte alignment
  0x55c0a0830f21: note: pointer points here
   00 00 00  17 00 06 01 02 03 04 05  06 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
                ^
  Testing gtpie_tv0()
  Testing gtpie_tv1()
  Testing gtpie_tv2()
  ../../../../src/osmo-ggsn/tests/gtp/gtpie_test.c:76:2: runtime error: load of misaligned address 0x55c0a0830f21 for type 'uint16_t', which requires 2 byte alignment
  0x55c0a0830f21: note: pointer points here
   00 00 00  2a ab cd 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
                ^
  Testing gtpie_tv4()
  ../../../../src/osmo-ggsn/tests/gtp/gtpie_test.c:90:2: runtime error: load of misaligned address 0x55c0a0830f21 for type 'uint32_t', which requires 4 byte alignment
  0x55c0a0830f21: note: pointer points here
   00 00 00  2a ab cd 01 23 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
                ^
  Testing gtpie_tv8()
  ../../../../src/osmo-ggsn/tests/gtp/gtpie_test.c:104:2: runtime error: load of misaligned address 0x55c0a0830f21 for type 'uint32_t', which requires 4 byte alignment
  0x55c0a0830f21: note: pointer points here
   00 00 00  2a 00 01 02 03 04 05 06  07 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00
                ^
  ../../../../src/osmo-ggsn/tests/gtp/gtpie_test.c:105:2: runtime error: load of misaligned address 0x55c0a0830f25 for type 'uint32_t', which requires 4 byte alignment
  0x55c0a0830f25: note: pointer points here
   00 01 02 03 04 05 06  07 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00
               ^

Change-Id: I9eb16450af942d6464211e190f6a4d5a1d814842
2017-11-29 16:20:57 +00:00
Pau Espin Pedrol
f1e44c5493 examples: Add secondary ipv6 google DNS to osmo-ggsn.cfg
Change-Id: I5efbd1848a7974cb8dc614c4567de2658b9a7269
2017-11-28 11:13:55 +01:00
Harald Welte
bebd75c2d1 Merge changes Id4724fe0,I5c619712
* changes:
  contrib/jenkins.sh: Enable Werror in C(PP)FLAGS
  ggsn_vty: Stop using deprecated API vty_install_default
2017-11-18 10:32:37 +00:00
Neels Hofmeyr
878ece768b add --enable-sanitize config option
Change-Id: I439ff2b2cb36a5c29347a914c0f2e21bed598b06
2017-11-17 02:05:34 +01:00
Pau Espin Pedrol
a00e79242b contrib/jenkins.sh: Enable Werror in C(PP)FLAGS
Change-Id: Id4724fe07f6641e82c3bd9cde2d8d759aa492288
2017-11-16 17:09:06 +01:00
Pau Espin Pedrol
840ce8a0a8 ggsn_vty: Stop using deprecated API vty_install_default
Changes made as requested by the deprecation text.

Fixes warning below:
 warning: ‘vty_install_default’ is deprecated: Now happens implicitly with install_node() [-Wdeprecat
ed-declarations]
  vty_install_default(GGSN_NODE);
  ^~~~~~~~~~~~~~~~~~~

Change-Id: I5c6197129e0c251a4e8dd174027b011c8f6476c6
2017-11-16 17:01:51 +01:00
Harald Welte
afd76a731f contrib/jenkins.sh: Allow jenkins job to specify if kernel GTP is used
Change-Id: I83319aa6e5e7dde229ae5a036b5a1800879cbf81
2017-11-14 14:48:32 +09:00
Harald Welte
fd30bd1032 gtp-kernel: Add device nime in pdp_debug() log statements
Change-Id: Iad0e7a9fa48fcddc31b8d555244581efdbd61b4e
2017-11-14 00:08:51 +09:00
Harald Welte
227034c88e gtp-kernel: Add function name to pdp_debug() function calls
This allows us to distinguish "add" from "del" operatons in the log

Change-Id: Ibe2e76a6eecc7b5fa5f44ab2c1578597138e30b9
2017-11-14 00:08:51 +09:00
Harald Welte
3dad951171 gtp-kernel: Get rid of SYS_ERR where not applicable
SYS_ERR is for logging an error from the (operating) system including
the errno value.  For general logging, we have DEBUGP/LOGP.  Let's
convert the gtp-kernel logging over.  This also fixes the related line
ending mess-up as SYS_ERR adds a LF while LOGP/DEBUGP don't.

Change-Id: Idb4069a28227b770e20d62bf306cd294f47146ae
2017-11-14 00:08:51 +09:00
Harald Welte
318795635e gtp-kernel: proper cleanup in error path
When genl_socket_open() succeeds but genl_lookup_family() fails,
we have to clean up the socket that we just opened.

This requires a new version of libgtpnl :/

Change-Id: I31df046530347f88cb7b16c37a899b456ed1b080
2017-11-14 00:08:51 +09:00
Harald Welte
22e1573831 gtp-kernel: Make sure repeated calls to gtp_kernel_init() are safe
We have to factor out the "run once" code and make sure to really
only run that once, while the per-device code remains in the
gtp_kernel_init() function.

Change-Id: Iba5bd71e4b725eef59fe4f233fbb965e396a06c3
2017-11-14 00:08:51 +09:00
Harald Welte
c85e89961a gtp-kernel: Avoid global state variable
Whether or not GTP kernel support is enabled is the property of a
given APN, and not a global state variable.

Change-Id: Iff3bd8a52bd6c20f9811ee41ff700486d08591f3
2017-11-14 00:08:51 +09:00
Harald Welte
2fc2bc6bc4 gtp-kernel: Align logging for APN start in kernel-gtp case with that of TUN
Change-Id: Ie53d37f151e8b6448636a8cde5777b3841989d05
2017-11-14 00:08:51 +09:00
Harald Welte
0d0e242685 gtp-kernel: shut down kernel GTP device in apn_down()
When we take the APN down, we should also take the GTP device down.

Change-Id: Idd250dd454a1603834d388884a24a63e044fdd7b
2017-11-14 00:08:51 +09:00
Harald Welte
698a2339eb gtp-kernel: Get rid of hard-coded kernel GTP device name
The existing kernel GTP support code inherited from OpenGGSN was overly
simplistic and didn't support multiple GTP devices or user-defined GTP
device names.  Let's remove that restriction in this patch

Change-Id: I51df223788fd5b7cf8099463b8aa0ca4a4fd1c96
2017-11-14 00:08:48 +09:00
Harald Welte
490782d18e gtp-kernel: Re-add support for kernel GTP-U acceleration
When we branched off osmo-ggsn from the old openggsn code base, the
support for kernel-gtp got temporarily removed.  This patch
re-introduces support for handling the GTP-U plane in the Linux kernel
by means of libgtpnl + the kernel GTP-U driver.

This only works for IPv4 at the moment, until the kernel GTP-U code
gains IPv6 support.

Kernel GTP currently also is restricted to a single APN per GSN.

Change-Id: Ieb1bc1bd0d51d41947f0abd6ebbc2e5d102592d6
2017-11-13 23:59:40 +09:00
Harald Welte
e3c5918aee gtp_kernel: Change gtp_kernel_init() function signature
Rather than taking an explicit in_addr, prefix_length and a
string-formatted prefix, let's pass in an in46_prefix and derive
the other representations from it.

Also, don't refer to a no-longer-existing global 'ipup' variable but
add it as a function argument.

Change-Id: Ife87142c86589b4fa4062d62afe3670467548589
2017-11-13 23:57:58 +09:00
Harald Welte
e2a1de5ca5 Properly NULL-out blacklist in alloc_ippool_blacklist()
This ensures that in case of error, any caller can still safely
call talloc_free() on the blacklist pointerm as free on NULL
is well-defined.  With the code prior to this patch we fear
a double-free.

Change-Id: Idc511cb3f0dfb922920aba8f88ea77df1722ecdc
2017-11-13 23:57:58 +09:00
Harald Welte
4c7d29107f factor out netdev_ip_local_get() from tun_ip_local_get()
netdev_ip_local_get() is a generalized version of tun_ip_local_get()
which supports the net device as argument, rather than a tun_t.

Change-Id: I072aa1a55e7bf110706e9207021b776d9b977fb6
2017-11-13 23:57:58 +09:00
Harald Welte
f55a039048 remove unused argument to alloc_ippool_blacklist()
Change-Id: I4d3ea077ba46446e537ec9a6de6f4080fcaa428c
2017-11-13 23:57:58 +09:00
Harald Welte
fc6676c4a0 ippool: Correctly compute size of static pool
* we have to use stataddr, not addr (dynamic)
* we have to multiply the length of the address by 8 to get its bit length
* we can simplify the -1 +1 logic (like dynamic)

Change-Id: I174102051bef95f7df34b7d7c480a00ae408be7d
Fixes: Coverity CID#174189
2017-11-06 03:38:54 +09:00
Harald Welte
1af543f44c tun: Don't copy 16byte IPv6 address to 'struct in_addr'
The 'struct tun' curently only has an in_addr (v4-only) member to
store the address of the tun device, so let's not attempt to store
an IPv6 address in it.

FIXME: This entire code needs an overhaul. The assumption that there's
only one address, and only either v6 or v4 is broken to begin with.

Change-Id: If0b626d688841d6e0a3867834f4cb1b70084050e
Fixes: Coverity CID#174278
2017-11-06 03:32:52 +09:00
Harald Welte
bd228244da gtp: Explicit OSMO_ASSERT to ensure pdp variable is set
Change-Id: I09e37e25fd118ac0a54ab788304d3f5083463050
Fixes: Coverity CID#174335
2017-11-06 03:16:49 +09:00
Harald Welte
a06120de77 gtp: Fix buffer overflow in imsi_gtp2str()
The string buffer allocated for the IMSI must be sized for a length
twice the number of input bytes (each byte has two nibbles) plus 1
byte for NUL.  We missed the "twice" part :/

Change-Id: I1ecaa811815ae522af71feabc5d0c1ea8b4edde9
Fixes: Coverity CID#174336
2017-11-06 03:12:54 +09:00
Harald Welte
b589e78f13 sgsnemu: Free strings in error path
In create_pdp_conf(), we have to free() any strings both in the
success and in the error case.

Change-Id: If59cc8d6d151c123f46c1d029091209fd82b3c8e
Fixes: Coverity CID#187636, CID#187633
2017-11-06 03:10:31 +09:00
Harald Welte
b11ed0f132 sgsnemu: Make sure buffer has space for terminating-NUL
In proc_ipv6_conf_read() we allocatea buffer on the stack but
forgot the terminating NUL byte.

Change-Id: I54126d8bc08c137859f2de4b47ef23fc0714fdd7
Fixes: Coverity CID#178641
2017-11-06 03:07:26 +09:00
Harald Welte
9c332104eb sgsnemu: Fix format string in printing tun-device name
Change-Id: Ie05050a78a135a1a76473337a341fd723bbe4976
Fixes: Coverity CID#178654
2017-11-06 02:44:42 +09:00
Harald Welte
51127ea962 sgsnemu: Don't leak FILE handle in proc_read()
Change-Id: Ie22e6a9bc172427e867e7a4001b6c710477a232b
Fixes: Coverity CID#178660
2017-11-06 02:42:59 +09:00
Neels Hofmeyr
dabb8b4860 fix compiler warnings: return 0 in main(), in 3 tests
Change-Id: I9e49ceba6b0a8dffd331e5707667d9bb007f3ec7
2017-10-31 01:02:00 +01:00
Harald Welte
ff069172ce Tag/Release Version 1.1.0
Change-Id: I30a9e72fa9c3d6fc755c5531844b663c08c3ac06
2017-10-28 19:01:30 +02:00
Harald Welte
7bee06e1cc Debian: include the systemd service file for osmo-ggsn
Change-Id: I5ebee0135e638b7327a16218bdce466ada9aee56
2017-10-28 18:58:38 +02:00
Harald Welte
6c10aa0e6f Debian: package libgtp debug symbols as libgtp-dbg
... and some more Description for debian/control

Change-Id: I099735f8550134441a77c29e8c4d4d3c2490e379
2017-10-28 18:58:38 +02:00
Harald Welte
a4e24f5546 Debian: libgtp is libgtp2 for some time, not libgtp1 anymore
In Change-Id Ie631880155513b1b78d1e9dd473dc5dc50e05943 we changed
LIBVERSION but didn't update debian/control.

Change-Id: I7a1349e9609cb455c0fe9d63d085e7c44dff96ef
2017-10-28 18:34:08 +02:00
Neels Hofmeyr
29caaab817 jenkins: use osmo-clean-workspace.sh before and after build
See osmo-ci change I2409b2928b4d7ebbd6c005097d4ad7337307dd93 for rationale.

Depends: I2409b2928b4d7ebbd6c005097d4ad7337307dd93
Change-Id: I1424dff06c7d4f695af0936671ad6faa504aaf16
2017-10-27 22:54:29 +02:00
Pau Espin Pedrol
859f9b0752 ippool: Implement and use blacklist instead of blindly using IPPOOL_NOGATEWAY
Commit dda21ed7d4 modified previous calls
to ippool_new() removing the pass of flags to avoid allocating certain
problematic IPs from the pool to MS, such as the network, gateway and
broadcast IPs.

Today I did some unsucessful tests with osmo-ggsn with a pool "ip prefix
dynamic 176.16.222.0/24", and thus IP 176.16.222.0 was being assigned to
the MS. De-capsulated DNS packets were received in the tun interface,
but the Linux system in there was unable to correctly forward the
packets to the gateway interface connected to the Internet. However,
adding a second MS which got 176.16.222.1 had its packets forwarded
correctly.

However, previous implementation relies on flag IPPOOL_NOGATEWAY flag to
blindly blacklist first IP after the network ip (ie, .0 and .1 are
removed), which limits the IP reserved for the tun device to be .1. If a
different IP in the range is assigned, it may cause issues. As a result,
a blacklist is introduced in this commit to dynamically fetch the tun IP
address and exlucde it from the pool of available IPs.

Change-Id: I8e91f7280d60490c858a769dd578c1c8e54e9243
2017-10-17 19:10:24 +02:00
Pau Espin Pedrol
a037e5908a tun: Convert tun_ipv6_linklocal_get to be more generic
Add support for IPv4 and IPv6 global IPs. Also return the prefix length
of the IP address by using a in46_prefix.

Change-Id: I277af191dc611b6bbcb83479f4ae338083740322
2017-10-16 17:45:48 +02:00
Pau Espin Pedrol
2e7b9ff891 lib/in46a: Introduce in46a_netmasklen API
Change-Id: I06e3e038afd8f7afaec2a3fa67b1616500c8db80
2017-10-16 17:45:40 +02:00
Pau Espin Pedrol
361cb9e910 lib/ippool: Fix listsize calculated 1 elem too small
Take the chance this commit is changing test output to also remove use
of IPPOOL_NOGATEWAY which is going to be removed soon, and instead test
IPPOOL_NOBROADCAST.

Change-Id: I95c24bc690490155bec9e3933d678e4668d7745f
2017-10-16 11:59:43 +02:00
Harald Welte
5bacb59a6c Merge "sgsnemu: Use getprotobynumber() in print_ipprot()" 2017-10-15 16:01:08 +00:00
Harald Welte
5b0096a236 Merge "sgsnemu: Remove dead code: encaps_printf()" 2017-10-15 16:01:08 +00:00
Harald Welte
df6a105024 Merge "sgsnemu: Mark local functions 'static'" 2017-10-15 16:01:08 +00:00
Harald Welte
226e95af1f Merge "sgsnemu: Make use of "dependon" feature in gengetopt" 2017-10-15 16:01:08 +00:00
Harald Welte
e37f48eaf9 sgsnemu: Use getprotobynumber() in print_ipprot()
There's no point in sgsnemu doing a poor mans reimplementation
of what the C library provides already by means of getprotobynumber()

Change-Id: I8cdc460e4fa5d86d80addf6e5f341d2d80093a35
2017-10-14 16:39:07 +02:00
Harald Welte
8a55263a1b sgsnemu: Remove dead code: encaps_printf()
This function is never used/called, remove it.

Change-Id: I37a447e4d5387e3fc5f4433ab20ceba7c446684b
2017-10-14 16:39:07 +02:00
Harald Welte
fed3389112 sgsnemu: Mark local functions 'static'
We don't need to export those to the global name space as they're
not called from code in other files.

Change-Id: I454249335ba46abdb3afbc669c4a06a06f39ae72
2017-10-14 16:39:07 +02:00
Harald Welte
081f30cba4 sgsnemu: Print warnings on broken IPv6 configuration (acept_ra)
When sgsnemu is used for an IPv6 pdp context, we rely on the router
discovery procedure and SLAAC to set the correct IPv6 address/prefix
on the tun device.  This requires the system to be configure to accept
router-advertisements on the tun device.  Let's print a warning
if accept_ra for the specific tun device is set to a wrong value.

We're leaving it up to the user to either set a system-wide
/proc/sys/net/ipv6/conf/default/accept_ra or to configure this in an
ip-up script used together with sgsnemu.

Change-Id: I563092ca35bc74f035a5023e11256779aac46e11
2017-10-14 16:39:07 +02:00
Harald Welte
ea0c26a436 sgsnemu: Make use of "dependon" feature in gengetopt
The gengetopt syntax can specify that a particular command line argument
depends on some other argument/option present.  We can use this to
provide useful feedback to the user at the command line parsing state,
like --pingrate making no sense without --pinghost being specified.

Change-Id: Ief27275e90e6bce23aed1e83874dbac98dd0926b
2017-10-14 16:39:07 +02:00
Harald Welte
9d9d91b8e8 ggsn: Avoid crash on wrong EUA type
If the EUA in the Create PDP Context Request was not supported by
the given APN (e.g. IPv6 request for a v4-only APN), we crashed.

Avoid this and add proper handling of this error case.

Change-Id: I8d1f7ec727c5d2d4427232015f81ed57d3440dff
2017-10-14 16:39:07 +02:00
Harald Welte
73abc38dc5 sgsnemu: Add '--tun-device' option to specify TUN device name
This way, multiple sgsnemu instances can be runnig in parallel, each
of them creating a different tun device for their respective PDP context

Change-Id: Id12fbadf924a60db255b6d51b9f647aa51dd2e16
2017-10-14 08:17:07 +02:00
Harald Welte
be4baa6d97 Merge "Add unit tests for libgtp gtpie.[ch] functions" 2017-10-14 06:16:36 +00:00
Harald Welte
d369013250 Merge "gtpie_{encaps,encaps2}(): RAI is a fixe 6-byte length field, not 8 bytes" 2017-10-14 06:16:36 +00:00
Harald Welte
8afec5f86d Merge "gtpie.h: Add IE identifier definitions up to 29.60 v11.8.0 Release 11" 2017-10-14 06:16:36 +00:00
Harald Welte
5943cbb73f Add unit tests for libgtp gtpie.[ch] functions
This doesn't yet cover all the functions in gtpie.[ch], but testing half
of them is better than not testing any of them, so let's merge this
current state with a couple of TDOO's on what we still need to test.

Change-Id: I30a6dd8a01b7a074ef2d3936d186dfff6c79e6c0
2017-10-14 08:11:13 +02:00
Harald Welte
f6c5f9524f gtpie_{encaps,encaps2}(): RAI is a fixe 6-byte length field, not 8 bytes
gtpie_decaps() always had this right, but the encapsulation functions
treated it as 8-byte fixed length IE.

I hope we had a chance to convert all of this to the normal libosmogsm
tlv_parser one day.  This would have one description table for all TLV
types which then is used from encoder and decoder.

Change-Id: I48471f2735511806ac424b5ffc1929e85bb156f3
2017-10-14 07:59:07 +02:00
Harald Welte
bc41c8d581 gtpie.h: Add IE identifier definitions up to 29.60 v11.8.0 Release 11
Change-Id: I6ab7bfb31f93f52f9f6b1b5880dcb2c232bba794
2017-10-14 07:49:15 +02:00
Harald Welte
89e1abcb18 Allow Common flags 0x94 and ignore them in PDP activation
extended from https://github.com/osmocom/openggsn/pull/2

Change-Id: I31b3e4b378e74bb5a0a2f54af6d2a15b629876cf
2017-10-14 07:43:58 +02:00
Harald Welte
8376972050 gtpie: Add missing #include of <arpa/inet.h> for htonl() and friends
Change-Id: Id69d957d0860ee49e7f0db5c64ab8ba976f8c8d6
2017-10-13 16:36:43 +02:00
Harald Welte
a964027344 gtpie_decaps: const-ify pointer to input packet data
Change-Id: Ia048abcd80f29581c6ac02cd7f534f2617005671
2017-10-13 16:36:43 +02:00
Harald Welte
c5150cecc5 gtpie: Add doxygen API documentation
libgtp should have proper API documentation, let's start with the
gtpie.[ch] parts.

Change-Id: I97df5bd3c8dcc5c97a114c8c6abadabf33147b05
2017-10-13 16:36:43 +02:00
Harald Welte
02af9b3ca2 gtpie_tlv() gtpie_tv0(): const-ify read-only input argument
Change-Id: Ide487e34884c8356694246f43c3f1f562357304c
2017-10-13 16:36:43 +02:00
Harald Welte
db924d3908 Add unit tests for lib/in46_addr.c code
Change-Id: Id032c330405e5dca8ecfc0970d128341ed75c675
2017-10-13 16:36:39 +02:00
Harald Welte
34a7416ec0 in46a_to_sas(): Return AF_INET6 in case of IPv6 address
Change-Id: Ia2f9ac60f08823d5f7c1a76c0b7cbd65ac615e26
2017-10-13 16:28:01 +02:00
Pau Espin Pedrol
45ce2725ac tests: Remove Makefile.in
Change-Id: Ie21e8bfab7cda52aa696dd26280efc05c4b51bba
2017-10-13 16:28:01 +02:00
Harald Welte
a2eb5eb760 update .gitignore
Change-Id: I030bd616dd27d49e55b5bdcc7c0b4fa3eb523da4
2017-10-13 16:28:01 +02:00
Pau Espin Pedrol
fdd732b130 Remove trailing whitespace
Change-Id: I8e24f95a88bef3a59006a89c219871e6156963d7
2017-10-13 16:28:01 +02:00
Harald Welte
1d8ffc6b23 Add ippool unit-test for 'make check' runs
This test creates a variety of v4 (and one v6) pool and performs
allocations until the pool is full, then frees a random number of
randomly distributed addresses, re-allocates them and again checks that
they're all available and finally once the pool is full allocations
fail.

Change-Id: Ibf4588e8f3ae71684e5262c0caaa2689aee73a94
2017-10-13 16:28:01 +02:00
Pau Espin Pedrol
58c0da7833 lib/tun.c: tun_ipv6_linklocal_get(): fix memory leak with getifaddrs()
From getifaddrs(3) man:
"The data returned by getifaddrs() is dynamically allocated and should
be freed using freeifaddrs() when no longer needed"

Change-Id: If6300d1c8d36fcafef294a4c11bbda31a158bb9c
2017-10-12 18:00:16 +02:00
Pau Espin Pedrol
958256f5cf create_context_ind(): Fix crash on apn not found
Program terminated with signal SIGSEGV, Segmentation fault.
0  create_context_ind (pdp=0xb6b391b0 <pdpa>)
    at /usr/src/debug/osmo-ggsn/1.0.0+gitrAUTOINC+ab5e160937-r0/git/ggsn/ggsn.c:453

453             if (!apn->started)

(gdb) bt
0  create_context_ind (pdp=0xb6b391b0 <pdpa>)
    at /usr/src/debug/osmo-ggsn/1.0.0+gitrAUTOINC+ab5e160937-r0/git/ggsn/ggsn.c:453
1  0xb6b225e0 in gtp_create_pdp_ind (gsn=gsn@entry=0x74f28, version=version@entry=1, peer=0x0,
    peer@entry=0xbee6ead4, fd=-1092167056, fd@entry=8, pack=pack@entry=0xbee6eae4, len=len@entry=179)
    at /usr/src/debug/osmo-ggsn/1.0.0+gitrAUTOINC+ab5e160937-r0/git/gtp/gtp.c:1591
2  0xb6b245e4 in gtp_decaps1c (gsn=0x74f28)
    at /usr/src/debug/osmo-ggsn/1.0.0+gitrAUTOINC+ab5e160937-r0/git/gtp/gtp.c:2986
3  0x41d770c0 in osmo_select_main () from /usr/lib/libosmocore.so.8
4  0x000121b8 in main (argc=4, argv=0xbee70e54)
    at /usr/src/debug/osmo-ggsn/1.0.0+gitrAUTOINC+ab5e160937-r0/git/ggsn/ggsn.c:897

Fixes: dd266066c7, b16c46b4c3

Change-Id: Ie4ec74e87aaf1d067dd1717d986673be56c4d6ed
2017-10-11 20:37:24 +02:00
Harald Welte
6748dc90b8 sgsnemu: Add IPv6 support via tun device and "-t v6 --createif"
The idea is to only implement the GTP-C plane and configure the right
link-local source address on the tun-device and let the regular (Linux)
kernel take care of sending router solicitations and
accepting/processing the related router advertisement.  This avoids a
lot of complexity in sgsnemu.

For this to work, you must have /proc/sys/net/ipv6/conf/$tun/accept_ra
set to either 1 (works only if no IPv6 forwarding/routing configured on
your sgsnemu-running system) or 2 (works even if forwarding/routing is
configured).

Change-Id: I57e4c53ee648e1efecfba3eea592d1129849557c
Closes: OS#2518
2017-10-10 08:56:09 +08:00
Harald Welte
7bd7b6815a Merge "create_context_ind(): ignore a non-started default APN" 2017-10-01 10:31:09 +00:00
Harald Welte
b16c46b4c3 create_context_ind(): ignore a non-started default APN
If the default APN has not been started, it is not eligible to be
used in starting of new PDP contexts.

Change-Id: I93b5c205c033f275824ee8bc8cdcf1428fb086df
2017-10-01 18:29:41 +08:00
Harald Welte
840a8e9713 sgsnemu: Allow specification of PDP (EUA) Type IPv4 or IPv6
This just adds the capability to sgsnemu to request a certain PDP
EUA type.  It doesn't mean it actually handles anything beyond the
existing IPv4 yet.

Change-Id: I157f9157a7ff2ea56c37a4a902d4706de4c7d35d
2017-10-01 18:19:07 +08:00
Harald Welte
cee7546f15 Replace EUA magic numbers for IETF, IPv4 and IPv6 with #defines
Change-Id: I33f65e404217e717bd795e5229c8d9456a7b3739
2017-10-01 18:19:07 +08:00
Harald Welte
ed1ba2c902 apn_start(): Extend error message when setting IPv6 address fails
Tell the user about possible causes of failure to set the IPv6
address of the tun device, such as general lack of IPv6 support in
the kernel/OS, or the use of /proc/sys/net/ipv6/conf/default/disable_ipv6

Change-Id: I5ff812425ee12b8386bb66521e05c93e825a4506
2017-10-01 18:19:07 +08:00
Harald Welte
ed08eb1c5a apn_stop(): Print tun device name when closing tun device
Change-Id: If981cc0696122cb69c01ceac6f54ae01bcbf4a2d
2017-10-01 18:19:07 +08:00
Harald Welte
2e84d2c29a create_context_ind(): ignore any non-started APNs
If we receive a GTP-C CREATE PDP CONTEXT for an APN that we were
unable (or not configured) to start, ignore that APN.

Change-Id: I8011a9ccc1d5effd3779f184c9055af46838ccaf
2017-10-01 18:19:07 +08:00
Harald Welte
dd266066c7 apn_start(): fix clean-up after errors bringing up APN
When there's an interim error (e.g. in resolving the link-local address
or setting up the tun device), apn_start() simply calls apn_stop()
on the not-yet-fully-started apn_ctx.

This only works if apn_stop() doesn't bail out early in case of
a not-started apn_ctx, so let's remove the related check at the
start of the function.

Change-Id: I2917a6258cb73cc12fd9d81296ff0eaa616890b9
2017-10-01 18:19:07 +08:00
Pau Espin Pedrol
b5624c3d48 contrib: osmo-ggsn.service: Use expected suffix for cfg file
files in doc/examples/ dir end with .cfg, as well as all configuration
files present in all projects.

Change-Id: I361c67809d095dd08b0f400de2a6f84f981411c5
2017-09-27 20:57:06 +02:00
Max
6a21527a2d Move extended PDP logging macro to header
It might be useful for any user of libgtp who uses libosmocore so let's
make generalized version of it available as part of installable header.

Change-Id: I79aba10ef989384a28f059c30899e65c771ae5e1
Related: SYS#3610
2017-09-25 10:35:34 +02:00
Harald Welte
1a8bc9839a Merge "sgsnemu: Add --no-tx-gpdu-seq option to suppress transmission of G-PDU sequence numbers" 2017-09-24 15:20:23 +00:00
Harald Welte
79aa4bd837 Merge "ggsn: Add per-APN VTY configuration option on G-PDU sequence numbers" 2017-09-24 15:20:23 +00:00
Harald Welte
fbb9c7f59a sgsnemu: Add --no-tx-gpdu-seq option to suppress transmission of G-PDU sequence numbers
Related: OS#2519
Change-Id: Idc650d896f0f72329090b56a37d9c16359294860
2017-09-24 23:10:05 +08:00
Harald Welte
3c1cce245e libgtp: Allow each PDP context to specify if it transmits G-PDU sequence numbers
GTP sequence numbers on GTP-U are optional for G-PDU type messages (i.e.
user-ip messages).  Let's allow the user to specify this behavior by
a new pdu_t.tx_gpdu_seq flag.  The flag is enabled by default to stay
compatible with the prior behaviour.

Related: OS#2519
Change-Id: Icf22a2ddd5c4a968ef5bda7c202b921d93fb49e6
2017-09-24 23:10:01 +08:00
Harald Welte
93fed3bc51 ggsn: Add per-APN VTY configuration option on G-PDU sequence numbers
This per-APN vty option determines if we are transmitting GTP sequence
numbers in downlink G-PDU messages.  This behavior is optional as per
GTP spec.  The default behavior is "true", like before this change.

Related: OS#2519
Change-Id: Ibf0de261f83951309b01b4feae998b6656c77664
2017-09-24 23:10:01 +08:00
Harald Welte
00d346092b Merge "ggsn: Fix double whitespace in writing "ifconfig" lines" 2017-09-24 14:58:50 +00:00
Harald Welte
3ca419a2ef ggsn: Fix config file writing of IPv6 DNS settings
There was a copy+paste mistake that created syntax errors during the
write of a config file that contained IPv6 DNS server settings.

Change-Id: Ida40c32c72dba8155f8294b93484e46e8bd27739
2017-09-24 22:49:21 +08:00
Harald Welte
ff438174aa ggsn: Fix double whitespace in writing "ifconfig" lines
This is merely a cosmetic issue, no functional change.

Change-Id: I8663ee633524eedeed5ddd45ddb65a06825052ac
2017-09-24 22:49:21 +08:00
Harald Welte
f85fe9720b ICMPv6: Send router advertisement from own link-local address
I'm not quite sure how I ended up doing this, but for some strange
reason the code before this commit is sending the ICMPv6 Router
Advertisements from some weird non-standard source address.  This is
a violation of RFC4861 which clearly states that the source address
of router advertisements "MUST be the link-local address assigned to the
interface from which this message is sent."

Change-Id: Ib444af70fc8f0b433d371281601fd5a37b29039e
2017-09-24 20:51:47 +08:00
Harald Welte
fed598f41d gtp: Avoid magic numbers when operating on GTP header flags
Let's introduce a couple of #defines that make the code much more
readable.

Change-Id: I3635d679fd54507274b46e99a02bdbbe41d7684e
2017-09-24 16:53:16 +08:00
Harald Welte
471e349ecc libgtp: Avoid extra memcpy() in gtp_data_req() by using sendmsg()
Adresses two "TODO Should be avoided" comments about an extra memcpy()
before sendto() that can be replaced by a single sendmsg() call with an
iovec array: 1 record for the GTP header + 1 record for the user payload.

Change-Id: Ie332a6b15972330fcf540753898eb84ecb84fe24
2017-09-24 16:12:39 +08:00
Harald Welte
7e1175f6d8 sgsnemu: Fix gengetopt package name
gengetopt by default picks the program name from PACKAGE (autotools),
which is osmo-ggsn and is obviously wrong in case of sgsnemu.

After this patch, "sgsnemu --help" no longer shows "osmo-ggsn" but
"sgsnemu" at the top of the help text.

Change-Id: Ifabc2435a503ef71aa5a002ca46833f329068b37
2017-09-24 10:53:53 +08:00
Harald Welte
f621498129 sgsnemu: Re-generate cmdline.[ch] using gengetopt
This will replace the manual additions to cmdline.[ch] with
auto-generated code from gengetopt.  We need to fix-up the RAT Type in
sgsnemu.c as the manually-added code diverged from what gengetopt
generates.

Change-Id: Ia687e13d5cec1655a57078a767d2123aa022842c
2017-09-24 10:27:07 +08:00
Harald Welte
7c20148e39 sgsnemu: Fix up gengetopt file for --norecovery
In commit 3a4c67b4bf we introduced the
--norecovery command line option, but this was apparently done by
manually editing the C source code rather than adding it to the .ggo
and letting gengetopt do its magic.  Let's fix this up.

Change-Id: I1698280a699b17cea65651c3736ef149aba7e432
2017-09-24 08:56:14 +08:00
Harald Welte
b6fc227763 sgsnemu: Fix up gengetopt file for RAI
In commit 41af5691ef we introduced the
--rai command line options, but this was apparently done by
manually editing the C source code rather than adding it to the .ggo
and letting gengetopt do its magic.  Let's fix this up.

Change-Id: Iaab404c3bcfc0c3943764f6616763f4f407d5644
2017-09-24 08:53:58 +08:00
Harald Welte
1d94585f96 sgsnemu: Fix up gengetopt file for rattype, userloc, mstz, imeisv
In commit 944dce3e66 we introduced various
command line options, but this was apparently done by manually editing
the C source code rather than adding it to the .ggo and letting
gengetopt do its magic.  Let's fix this up.

Change-Id: Ib8e7ef1cad5fc4423a1a4af628950aa93a4e073a
2017-09-24 08:51:02 +08:00
Harald Welte
05ac095006 sgsnemu: Fix up gengetopt file for QoS Extensions of 24.008
In commit 11a398fbc3 we introduced the
--qose{1,2,3,4} command line options, but this was apparently done by
manually editing the C source code rather than adding it to the .ggo
and letting gengetopt do its magic.  Let's fix this up.

Change-Id: I4cd827a96ac17f6eb9f824342f195727426d0e20
2017-09-24 08:41:14 +08:00
Harald Welte
73d28c9dda sgsnemu/cmdline.ggo: Remove 'unsigned' which is no longer supported
It seems like modern gengetopt no longer supports 'unsigned int'
argument types, and we need to use 'int' instead.  tested with 2.22.6

Change-Id: I34ca86cb3cc482400a7c4b3bf77c8668aaef562e
2017-09-24 08:34:36 +08:00
Max
ea70f3619a Fix leftovers after rename
* Use proper name in jenkins test
* Fix naming in systemd service
* Fix git-review config

Change-Id: I934f897002215d7d4e610cbd312383181bbe97c9
2017-09-15 12:19:23 +02:00
Harald Welte
98146776dd ggsn: Add ability to specify local IP addresses for GTP-C and GTP-U
In case the GGSN is behind some kind of DNAT, the public GTP-C and
GTP-U IP addresses as exposed inside the GTP payload information
elements are different from the (internal, behind-nat) IP address
to which it listens/binds.

Change-Id: I548c9011c9abd66d46f963b1def61575f3dabb89
2017-09-06 12:22:31 +02:00
Harald Welte
b5b02c2a51 Bump version: 0.94.34-23e4 → 1.0.0
Change-Id: I00a00a7d537fd3c1ff8f8fe128c5bf82d39bda76
2017-09-06 12:22:28 +02:00
Harald Welte
bd60930f36 libgtp: Bump major LIBVERSION for recent API/ABI breakage
in Change-Id I68ae49a765828fa681054c68bf7f5e74dbe48ad2 we introduced
a new struct member that breks ABI and API.

Change-Id: Ie631880155513b1b78d1e9dd473dc5dc50e05943
2017-09-06 12:22:05 +02:00
Harald Welte
720c939799 clarify relationship of OsmoGGSN to OpenGGSN.
Change-Id: If0e18fb02a7dcc472f5f5fbfaf53a107382ef7e5
2017-09-06 12:11:44 +02:00
Harald Welte
4aa22db1b4 debian: fix name of config file
Change-Id: I9e563d41b74c334fd98bb71fad946e93f214fa34
2017-09-06 10:54:14 +02:00
Harald Welte
db08819f85 debian: Remove no longer existing NEWS file from 'docs'
Change-Id: Ieb319ea29179ed97d746e13a9e63b3ceea2b917a
2017-09-06 10:54:13 +02:00
Harald Welte
8fcfe58269 debian: Fix debian/copyright syntax
Change-Id: I819ca05440cca041f26e7800821f4763f887c08b
2017-09-06 10:54:11 +02:00
Harald Welte
ce316f4962 Move examples to doc/examples and include them in DIST
Change-Id: I0846e21ac63774939934ab629c6d7212269be9a6
2017-09-06 09:17:15 +02:00
Harald Welte
59ffc89d42 remove bogus 'version' script
Change-Id: I3977cd4777aa4cf37a1d6e21eba0bc37d61421f3
2017-09-06 09:17:15 +02:00
Harald Welte
632e843e5f Rename OpenGGSN to OsmoGGSN
Osmocom has maintained this program since about 7 years now, while
the original author / copyright holder has completely disappeared.

With the introduction of Osmocom-style CTRL and VTY interfaces,
the way how the program is used and configured has substantially
changed.  In order to avoid confusion in terms of configuration file
format etc, let's rename it to OsmoGGSN.

Change-Id: I2da30f7d4828e185bfac1a4e2d8414b01cbe4f9d
2017-09-06 09:17:15 +02:00
Harald Welte
e80494726c ggsn: Handle SIGTERM like SIGINT and terminate
Change-Id: I0c8773bd6ef41332b91b5b025aef9ef129af8289
2017-09-06 09:17:15 +02:00
Harald Welte
3591437e0f Documentation update: Remove NEWS, README.Solaris, update README.md
* README.Solaris is obsolete and related code has been removed
* NEWS file was unmaintained for more than a decade, remove it
* Remove "Performance" chapter about 550MHz Athlon
* gengetopt is no longer needed for ggsn
* remove compilation/installation instructions horribly out of date
* command line syntax of 'ggsn' program has changed

Change-Id: I45d627911503c7b733cae6a1396ca4d69a9994db
2017-09-06 09:17:15 +02:00
Harald Welte
dda21ed7d4 Introduce a VTY, factually turning OpenGGSN into an Osmocom program
Change-Id: I9613ca3436e77ea132c47f0096df7c5050d7e826
2017-09-06 09:17:11 +02:00
Harald Welte
2778ae2b8f lib/tun: Mark internal helper functions 'static'
Change-Id: I53a8a89abb0080a39a153e9d3864c17b29aa193c
2017-09-05 23:13:14 +02:00
Harald Welte
1b6e8e7b5e Remove __sun__ code that is unmaintained
We haven nobody maintaining this platform, let's remove it.

In fact, only Linux and FreeBSD are part of the jenkins build tests,
so even Apple/MacOS is up for disposal.  However, as it's more
popular, let's keep the code.

Change-Id: Id6b8179259bacade52c39f96e688f828eff164ac
2017-09-05 23:13:14 +02:00
Harald Welte
e257be1d69 libgtp: Add back-reference to gsn from pdp context
This is required once one wants to support multiple GSNs in a single
application.

WARNING: This breaks ABI compatibility, LIBVERSION must be adjusted

Change-Id: I68ae49a765828fa681054c68bf7f5e74dbe48ad2
2017-09-05 23:13:14 +02:00
Harald Welte
8a03ea8a32 libgtp: Remove ctrl_handle from gsn_t, replace with private context
The control interface handle never belonged into libgtp in the first
place.  Commit 727417dd28 should not
have added this to the shared library (used by sgsnemu, osmo-sgsn, ...),
but to some private state of the GGSN.

Introducing a private context pointer at the same location will keep
ABI compatibilty.

Change-Id: I4f17516dae3e04114564828a3e5f6e2ea54212a5
2017-09-05 23:13:10 +02:00
Harald Welte
9e6dfa0558 lib/tun.c: Proper cleanup during tun_new() error paths
Change-Id: I285be20df76774ac7258b6edb3d4f2d28703757d
2017-09-05 22:42:18 +02:00
Harald Welte
4857f3c2f3 lib/ippool: Move ippool_aton() out of ippool_new()
we rather pass the in46_prefix directly into ippool_new()

Change-Id: Iadf6274e881a9bfc75eb41f9380f5ae2d8c92a0f
2017-09-05 22:42:18 +02:00
Harald Welte
b513b951bd lib/ippool: Add back-pointer from pool member to pool
This allows us to remove pool members without having to keep
a pointer to the pool around.

Change-Id: I9042eb85989c5451d7894678eca110dd19e78002
2017-09-05 22:42:17 +02:00
Harald Welte
33520b43ec lib/in46_addr: Avoid ASSERT() when in46a_ntop() is called on uninitialized address
Change-Id: I42d41ec1370b9cc15d372b649d8e1bc78e76af9b
2017-09-05 22:42:17 +02:00
Harald Welte
7fc8694b97 lib/in46_addr: Add 'struct in46_prefix' to represent addr + prefix
Change-Id: I797d105117e81951732bcfc2cc26a8d00fd69443
2017-09-05 22:42:17 +02:00
Harald Welte
b62983d3c3 lib/in46_addr: Add in46a_ntoa() function, similar to inet_ntoa()
Change-Id: I752b7033a106a74dc219047da5c3a7ad3cd3602e
2017-09-05 22:42:17 +02:00
Harald Welte
881e97ed00 lib/tun: Add 'void *priv' pointer to tun_t
This allows the application to attach some private state to the tun
device, such as the context from which it was created/allocated

Change-Id: Ief43b9b5fab5830fa8e28362c795f88f0b4d353b
2017-09-05 22:42:17 +02:00
Harald Welte
c55ece8d91 lib/tun: Add missing #include to net/if.h for IFNAMSIZ
Change-Id: I979867d643c9fa912884fe55105333dbad39ab97
2017-09-05 22:42:17 +02:00
Harald Welte
8ffd7fc782 gtp-kernel: Remove dependency to cmdline.[ch]
Change-Id: I760f25df609c309eba4d5716f3e23b49320449bf
2017-09-05 22:42:17 +02:00
Harald Welte
e57cbe2e74 update jenkins.sh to conform with current build environment
Change-Id: I999d35cdffbdb61984da15d616f675005aa0688c
2017-09-05 22:42:17 +02:00
Pau Espin Pedrol
0ab62fe081 ggsn: Fix DNS not sent in PDP context response
During IPv6 support implementation, helper function pco_contains_proto
was added which contains an error: It is only capable of finding first
protocol correctly, and as a consequence, in my setup DNS servers where not
sent back to the SGSN/MS, resulting in phone being able to connect to
IPs but not to domain names which required DNS resolution.

The condition in the while loop is also changed to match the increment
of the variable inside the loop to make it easier to understand at first
glance.

Fixes: 1ae98777d9

Change-Id: Icc2e6716c33d78d3c3e000f529806228d8aa155e
2017-08-30 15:56:27 +02:00
Max
bdc504e29c Use release helper from libosmocore
See
https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
for details.

Change-Id: Icdcb388ad22b0c009dac7968408d1e2504c838c1
Related: OS#1861
2017-08-28 12:29:28 +02:00
Max
b87da75ae4 Use value string check from osmo-ci
Change-Id: I036ed452826b9a6848d22d45bdcc95e20a110b8b
2017-08-26 06:10:17 +00:00
Max
14b1b63710 libgtp: expand logging
* print destination address on sendto error
* print address length on conversion error
* log listening address
* log GTP version on PDP context errors
* fix incorrect logging message for unknown GSN peer

Related: SYS#3610
Change-Id: I0f8ad8687acb7f6f0eeeb962f007e87cca0c4c27
2017-08-22 10:07:28 +00:00
Harald Welte
367baa3776 update debian/changelog to 0.94 + fix pkg-config version
This updates the debian changelog to 0.94 and adds some logic
to debian/rulres which fixes the version of the libgtp.pc file
built as part of our OBS builds (used to be UNKNOWN since
commit 23eea1d132)

Change-Id: I883feaef35ff5ffd1b22fb255b7c36112b4a8f3b
2017-08-14 00:21:57 +02:00
Harald Welte
37d5b1557b libgtp: Delete PDP context on receiving GTPv1 Error Indication
When a peer GSN receives a GPDU for an unknown PDP context, it sends
a GTP Error Indication.  This Error Indication should be used to
delete the offending PDP context locally.

In GTPv1, the Error Indication contains some mandatory IEs using
which we can look up the PDP context and delete it.

The existing code only dealt with GTPv0 Error Indications which lack
those IEs and use the TEI in the header instead.

Change-Id: I3e843f9ef1d6fd7868cc992e083c0891d16b6da9
Closes: OS#2426
2017-08-13 00:01:35 +02:00
Harald Welte
54d082e5e8 libgtp: Add missing mandatory IEs in GTP Error Indication
Change-Id: Iadd1fe3de7c476576a4409f22f5e84e9eade6b6e
2017-08-12 22:53:59 +02:00
Harald Welte
b10ee08c2f Properly format IMSI before using it in trap
For some reason Max' commits introducing the CTRL/trap interface
about one year ago didn't convert the IMSI to its actual textual
representation before usign it in the CTRL interface.

Let's clean that up by properly interpreting the IMSI.

Change-Id: I8b20d2e47a29de266d93a7ddd5e6877f7e346a63
2017-08-12 22:53:54 +02:00
Harald Welte
23eea1d132 Use osmocom-style git-version-gen / .version magic
This generates the version number from the latest tag + git history

Change-Id: I71e1c3f8f534d9e9690c94068eccdee29a6fee12
2017-08-11 13:48:14 +02:00
Harald Welte
81bc2aea53 tun_new(): Fix array overflow in FreeBSD related code
Change-Id: I096e3b614e82e402886163274cfcf9355bd57580
2017-08-11 13:12:09 +02:00
Harald Welte
ab6d189f8f replace hand-coded tun_gifindex() with standard POSIX if_nametoindex()
Change-Id: I738472765ab09f530dcf071455e1bb4e6fb3f6e5
2017-08-11 13:12:09 +02:00
Harald Welte
2e48a44952 Support setting TUN device IPv6 address + prefix
As we can now have PDP contexts with IPv6 user IP payload,
it is useful to extend the TUN related code to be able to
configure the tun device IPv6 address + prefix length

Change-Id: I899d21e52d02e0b8384af29ddd489ff19c8f2cf6
2017-08-11 13:12:04 +02:00
Harald Welte
72a38b55e3 IPv6: in46_addr: OSMO_ASSERT() in case of unsupported calls
There's a bit of trickery with the ip_pool and it's "lengty=8" IPv6
prefix handling, let's make sure we don't accidentially call any
support functions with addresses of wrong length.

Change-Id: I444c190bdcd18780344e1f0dad4faf3bcf9da5a5
2017-08-11 10:46:00 +02:00
Harald Welte
1ae98777d9 IPv6: Support PCO for IPv6 DNS addresses
In IPv6, DNS server information is not passed along as IPCP6 like
in IPv5 with IPCP.  The reason is that IPCP6 (for PPP) doesn't
support passing DNS server information.  Rather, the relevant RFCs
indicate DHCPv6 should be used even over point-to-point links.

3GPP decided to avoid DHCPv6 dependency for stateless autoconfiguration
(the only mandatory IPv6 configuration mechanism) and added some new
non-PPP-style PCO information elements ("containers") which can among
other things inform a MS about IPV6 DNS servers.

That same mechanism can also be used to inform the MS about IPv4 DNS
servers, so for IPv4 there are now two competing mechanisms: IPCP and
the new "native" PCO container.  With this patch, we support both
for IPv4.

Change-Id: I21499afd61def8c925f7838bde76f34d28214b56
2017-08-11 10:46:00 +02:00
Harald Welte
d46bcd236e IPv6: Implement IPv6 prefix assignment via ICMPv6 router advertisement
The 3GPP specs are quite strange when it comes to how an IPv6 address
or rather prefix is assigned to an IPv6 PDP context.  The designated
method for allocating the IPv6 address via the PDP EUA (End User
Address) Information Element in the GTP signalling plane is *not*
used to allocate the address/prefix.  Instead, the EUA is used to
allocate an "interface identifier" to the MS, which it the uses
to derive its link-local source address to send a router solicitation.

The GGSN subsequently answers witha router advertisement, advertising
a single/64 prefix, whihcthe MS then uses to generate it's real IPv6
source address for subsequent communication.

Change-Id: Icddf7d30e01d76a4784bcef5787b36f52f703a9f
2017-08-11 10:45:56 +02:00
Harald Welte
d4d6e09fd2 ippool: Extend pool to work with /64 prefixes
In IPv6 GPRS, we actually don't want to allocate an individual v6
address (like in IPv4), but we want to allocate a prefix.  The
standard prefix lengh is 8 bytes, i.e. a /64 prefix.  This patch
extends the pool to be able to work with such v6 prefixes.

Change-Id: I0cf700b6baf195a2e5fbea000531f801acaaa443
2017-08-09 22:37:57 +02:00
Harald Welte
365f8fa462 in46_addr: Add new function in46a_prefix_equal()
This function is used to compare an IPv6 address against another,
using the smaller of the two prefix lengths.

Change-Id: Ic993d8abdc90897cb55276f01ae3b8a5eadf5a0d
2017-08-09 22:09:34 +02:00
Harald Welte
d1bf1e11ba ggsn: Send proper errors in create_context_ind()
When we receive PDP context requests for unknown PDP types or if
we run out of dynamic addresses, we need to inform the SGSN that
PDP context creation failed.

Change-Id: Ibf199c1726130d27c8f80230b30ee51101c93b06
2017-08-09 22:09:34 +02:00
Harald Welte
a0d281db1c IPv6 support for user IP
This patch enables the use of IPv6 PDP contexts.  The phone will
have to request an IPv6 End-user-Address, and the GGSN will have
to be configured for an IPv6 pool.

The outer transport-layer IP between SGSN and GGSN must still be
IPv4, it is not modified by this patch

Change-Id: I22c3bf32a98e5daf99d6eaeac8c9f95cc7574774
2017-08-09 22:09:34 +02:00
Harald Welte
53165ede24 ippool_new(): const-ify input arguments
Change-Id: If3e53584e8c9c1f06bba4c183c9fd65fae913904
2017-08-09 22:09:34 +02:00
Harald Welte
63ebccdfe3 lib/tun.h: Remove non-endian-safe redefinition of IP header
We can simply use 'struct iphdr' from netinet/ip.h to achieve
the same goal (and be portable).

Change-Id: Ieece22e127dc14a7ffdc3b05656628989ad00b32
2017-08-09 22:09:34 +02:00
Harald Welte
d12eab9c4e ippool: Add IPv6 support to IP pool implementation
Extend the IP pool implementation to be able to manage both pools
of 32bit addresses (IPv4) as well as pools of 128bit addresses (IPv6)

Change-Id: Ib98cc4bf634d6be9a7bf8c03a24e629455fcafc8
2017-08-09 22:08:57 +02:00
Harald Welte
d9d8862a58 Proper fix for "Force Dynamic IP" in Create PDP CTX
An EUA length of *2* octets indicates dynamic IP address, while
an EUA length of 0 is invalid.  Let's fix this hack (which needs
to finally be removed anyway).

Change-Id: Ib1b57eb0654327882044d6862d955f4b32aa6bcd
2017-08-04 00:23:57 +02:00
Max
283188790b libgtp: improve error logging and propagation
* propagate error code from gtp_new() to caller instead of always
  returning -1
* on socket-related failures log explicitly which kind of socket caused
  error
* log expected GTP version for unexpected packets

Change-Id: Ie07f1e4246eb178838b7df21946a08a1f60f2084
related: SYS#3610
2017-06-09 08:53:10 +00:00
Max
3142d8d30b ctrl: cleanup trap creation
Move common trap create/send code into separate function.

Change-Id: Iaadc921b951aeb9b3ad5ab796e13d52017139468
2017-05-16 17:10:25 +02:00
Daniel Willmann
a2861a7428 contrib: Start openggsn after networking
Change-Id: Ic617c618db17e7109ee864c4e6c86f3bee081d02
2017-05-09 17:50:03 +02:00
Harald Welte
19e19e3609 track README.md rename in spec file and debian/docs
When README was renamed to README.md, the debian and rpm packaging
information was not updated.

Change-Id: I3fb3016defb74cf4e9c0a363f70eff9d6f71a5f5
2017-03-18 14:23:01 +01:00
Harald Welte
93c3b386cf Update README with general project information + convert to Markdown
Change-Id: Ib4213388dffab125e75d9b1f7d72319e041059ea
2017-03-17 18:36:14 +01:00
Harald Welte
bf6de7a289 Add MAkefile.* to EXTRA_DIST to ensure they end up in tarballs
Change-Id: Ibbae061fda3db49f8ecda263cfc3ca6873c0b1b3
2017-03-17 18:25:03 +01:00
Neels Hofmeyr
1fce2ce0b3 jenkins: add value_string termination check
Change-Id: I7c676debcdfef2471004deb9ef5a63e8f4e97e15
Depends: libosmocore change-id I2bc93ab4781487e7685cfb63091a489cd126b1a8
2017-03-16 19:00:27 +00:00
bjovan
a8f71eb24e Code formatted to be in line with formatting rules.
Change-Id: I546dc0a8d814527b9a96943a52f2f6b700285167
2017-02-27 09:56:28 +01:00
Harald Welte
8c25b97d3f Update AUTHORS file to reflect the last 12 years
Change-Id: I0a8f5a69f2a943344331d36ba225c02b0209beeb
2017-02-23 22:10:12 +01:00
Harald Welte
a892177dce remove ChangeLog, it hasn't been updated since 2004
We have a detailed log in git instead.

Change-Id: I6a7fe97995b5f65080a04423fee77030dea26b84
2017-02-23 22:10:08 +01:00
Harald Welte
9225bfc48c update version to 0.93
Change-Id: If65b8281933b5833b5ce83239688e775cc267f4c
2017-02-23 21:52:56 +01:00
Harald Welte
bf5c0bb4b9 gtp.c: Don't print ""Unknown packet flags" error message in get_seq()
get_seq() is called also from contexts where GTP-U is used, and GTP-U
doesn't have sequence numbers.  Thus, it is perfectly normal if no
sequence number and/or no S flag in the header is present.

Change-Id: Ie19b95bbb4427e547843a019f5213a231a9f83da
2017-02-23 21:11:05 +01:00
Harald Welte
875e4dc8c3 gtp-kernel: Fix tunnel creation/removal for GTP Version 1
When Linux Kernel GTP-U support is enabled, OpenGGSN so far only worked
with GTPv0,but not with GTPv1, as the TEI values were not correctly
configured.  This patch fixes the initialzation of the local and remote
TEI before using libgtpnl to create a tunnel context in the kernel.

Change-Id: I3e953ff5b4ab44c26dbbe20d18b61038fa57ff32
2017-02-23 21:10:48 +01:00
Holger Hans Peter Freyther
68d244d302 abi/debian: Bump ABI version of libgtp after struct size change
The gsn_t changed the size with the addition of the ctrl pointer.
Bump the SO version to not break osmo-sgsn/ggsn on upgrade.

Call the -dev package libgtp-dev to follow the rest of Osmocom and
to ease making releases here.

Change-Id: Iac4d6d2effde1a6b2f60b1e1b49c91513d5ca8c3
2017-01-26 11:14:59 +01:00
Max
7716860845 Integrate Debian packaging changes
debian/control:
    * restructure to make it easier to incorporate further changes
    * update package descriptions
    * update project URL

debian/rules:
    * use proper hardening syntax
    * remove useless comment

debian/copyright: update to match Debian format

Change-Id: Ia7f0a3a583ad63f5c6e5cf5e5de2ff7dd9eed8a9
Related: OS#1694
2016-12-22 14:10:07 +00:00
Harald Welte
d37b80a6d2 gtp.c: Improve debug statements about GTP header flags
* as there are muptiple flags in the field, use plural
* print the flags as hex value, not decimal.  Hex is customary for bitfields.

Change-Id: Ib23d80fae32b4e9fa146d82d8f5a1dada1a3cb2b
2016-12-15 20:55:54 +01:00
Max
dbd7024919 Only send TRAP for defined PDP peer
Do not attempt to send TRAP message on PDP context deletion if peer is
unknown.

Change-Id: I5e02c1d42bb7aaf1ef81a9824aab7b12047cdd3e
Fixes: Coverity CID 150135
2016-11-02 09:32:31 +00:00
Neels Hofmeyr
f41f5866ce gsn_restart file: wrap umask change tightly around file creation
An fopen("w") error used to omit the umask() call to reinstate the previous
umask. Also an fopen("r") at the top will never create a file and hence does
not need a umask set.

Instead, wrap the umask change and change-back tightly around the single
fopen("w") call.

Change-Id: If7d948e2f2ba47ecebba5614f18235a53b273d14
2016-10-14 11:39:49 +00:00
Neels Hofmeyr
f7611c3cee fix gsn_restart file buffer overflow and missing path sep
Fix errors during gsn_restart file path composition:

- possible buffer overflow because the wrong remaining length was fed to
  strncat().
- missing path separator: put restart file in dir/gsn_restart instead of
  ../dirgsn_restart.

This assumes that the path separator is '/'.

Use talloc_asprintf() to fix all filename length problems and shorten the code.

In order to free the allocated path, add a free_filename label, and jump there
instead of returning from the fopen("w") failure branch. Also don't return from
"fclose failed" branch in order to free the path, remove the if {} braces.

Change-Id: Idf0a64ff45720aa818f2f9de1e8ba2fe2c82631b
2016-10-14 11:39:49 +00:00
Neels Hofmeyr
38929c9131 configure: check for pkg-config presence
Change-Id: I658152eb24fd783fce9ceac35872ab918c80209a
2016-10-12 23:26:17 +00:00
Neels Hofmeyr
ee9d34a9cc build: be robust against install-sh files above the root dir
Explicitly set AC_CONFIG_AUX_DIR.

To reproduce the error avoided by this patch:

  rm install-sh        # in case it was already generated.
  touch ../install-sh  # yes, outside this source tree
  autoreconf -fi

This will produce an error like

  ...
  configure.ac:16: error: required file '../ltmain.sh' not found
  configure.ac:5: installing '../missing'
  src/Makefile.am: installing '../depcomp'
  autoreconf: automake failed with exit status: 1

See also automake (vim `which automake`) and look for 'sub locate_aux_dir'.

Change-Id: I4aef311d7a475800e09f48110a499c3759c69f5d
2016-10-12 23:26:17 +00:00
Max
727417dd28 Add control interface
Only generation of TRAP messages over Control Interface is supported so
far.

Note: requires corresponding version of libosmoctrl.

Change-Id: Ia76f841d2c9cd14394e9316fcd39f4060e23c898
Related: OS#1646
2016-10-12 09:30:30 +00:00
Max
cd93f4f4be Add .gitreview to simplify gerrit integration
Change-Id: Ib141dc9ae03c2b10b8925e30a2782bf2d932e192
2016-10-12 09:25:49 +00:00
Max
395e213894 Remove unused function
Change-Id: Iff0f1499660b12a47277b16a435efecb42fab038
2016-10-11 15:31:49 +02:00
BJovke
03dbafb000 Add 'Bearer Control Mode' IE
This IE is known to be sent by a Cisco GGSN, and was added in
ETSI TS 129 060 V7.17.0 (2011-10) /
3GPP TS 29.060 version 7.17.0 Release 7

See https://lists.osmocom.org/pipermail/osmocom-net-gprs/2016-September/000711.html
Subject "sgsnemu failing to create PDP context with Cisco GGSN"
Tue Sep 13 08:00:37 UTC 2016

Tweaked-by: Neels Hofmeyr <nhofmeyr@sysmocom.de>
2016-09-15 13:53:13 +02:00
Alexander Couzens
86540de7f3 gtp/queue/queue_seqdel(): fix element check which was always true
Fix an apparent typo that prevented queue iteration to find the correct item to
be removed. Instead, the first item was always returned. Calling code has been
analyzed to find that mostly this fault is not visible, since usually, the
first item is indeed the correct item to be returned. See mail thread
http://lists.osmocom.org/pipermail/osmocom-net-gprs/2016-June/000618.html
Date: Wed Jun 1 11:51:38 UTC 2016
Subject: "[PATCH] gtp/queue/queue_seqdel(): fix element check which always was true"
2016-06-06 00:45:10 +02:00
Ruben Undheim
cc077ae0bc Description: Fix some typos in the man pages and in the binary 2016-05-24 23:31:47 +02:00
Holger Hans Peter Freyther
6bf2f05df6 debian: Bump the version to ease upgrading from Debian
Debian SID has version 0.92-1 and we had 0.92. Bump it to 0.93.
2016-05-24 22:55:38 +02:00
Pablo Neira Ayuso
0eaa5b8e6c gtp: fix several compilation warnings
CC       gtpie.lo
gtpie.c: In function 'gtpie_encaps':
gtpie.c:437:22: warning: variable 'm' set but not used [-Wunused-but-set-variable]
  union gtpie_member *m;
                      ^
gtpie.c: In function 'gtpie_encaps2':
gtpie.c:537:22: warning: variable 'm' set but not used [-Wunused-but-set-variable]
  union gtpie_member *m;
                      ^

lookup.c: In function ‘lookup’:
lookup.c:40:24: warning: typedef ‘ub1’ locally defined but not used [-Wunused-local-typedefs]
  typedef unsigned char ub1; /* unsigned 1-byte quantities */
                        ^

Still one compilation warning left in cmdline.c, but that code
is autogenerated.
2016-05-12 17:02:34 +02:00
Pablo Neira Ayuso
176e895bd6 ggsn: fix compilation error with --disable-gtp-kernel
gtp-kernel.h: In function ‘gtp_kernel_init’:
gtp-kernel.h:25:15: error: ‘struct gengetopt_args_info’ has no member named ‘gtpnl_given’
  if (args_info->gtpnl_given) {
               ^
Makefile:422: recipe for target 'ggsn

Reported-by: Holger Freyther <holger@freyther.de>
2016-05-12 16:54:56 +02:00
Pablo Neira Ayuso
23d9976039 get rid of accidental copy of ggsn.conf
Included accidentaly in 8419e33 ("examples: ggsn.conf: document
tp-linux toggle").
2016-05-10 19:18:06 +02:00
Pablo Neira Ayuso
466da99934 configure: rename from --enable-gtp-kernel to --enable-gtp-linux
This software seems to run on other *nixes, so indicate explicitly that
this is the Linux kernel datapath support.
2016-05-10 19:11:43 +02:00
Pablo Neira Ayuso
8419e33c4a examples: ggsn.conf: document gtp-linux toggle
Enable Linux kernel GTP datapath driver.
2016-05-10 19:06:54 +02:00
Pablo Neira Ayuso
d9d7be339d ggsn: cmdline: no need to specify interface anymore
--gtpnl is now gone, instead you have --gtpkernel that behaves as an on/off
toggle. We full rely on the kernel routing base to select the real device to
transmit.

I have updated ggsn/cmdline.ggo and then run 'gengetopt' to refresh the
automatic code generation for command line options that openggsn uses.
2016-05-10 19:06:01 +02:00
Pablo Neira Ayuso
7b31987a46 ggsn: gtp-kernel: adapt gtp_dev_create() to its new interface
Andreas modified this interface, so update so this compiles again.
2016-05-10 18:51:00 +02:00
Neels Hofmeyr
f89dc4e127 queue_new(): fix NULL dereference on allocation failure
Coverity complains about a 'Dereference before null check' on *queue.
So, push the NULL check further up.

Though I doubt that 'return EOF' is the proper way to handle allocation
failure, this patch is only about the NULL dereference.

Fixes: CID#57918
2016-04-29 13:01:06 +02:00
Holger Hans Peter Freyther
b29ff1da55 jenkins: Add the build script from jenkins here
This can be used to replicate a build issue more easily.
2016-04-13 19:02:13 -04:00
Daniel Willmann
d997552d29 gtp: Handle gtpv1 in gtp_update_pdp_conf() correctly
libgtp cannot understand its own update pdp request (in gtp v1)
Only require the conditional and mandatory fields for gtpv1 and not
others.
Refer to 3GPP TS 29.060 Ch. 7.3.4
2016-02-05 07:48:20 +01:00
Daniel Willmann
05f3ef3eb8 gtp: Make gtp_update_pdp_conf() work for gtp0 and gtp1 connections
pdp_getgtp1(&pdp, get_tei(pack)) works like pdp_getgtp0 for gtp0
connections.
Using get_hlen() for gtpie_decaps is used in other places to decode ies
for both version 0 and 1.
2016-02-04 13:17:19 +01:00
Daniel Willmann
134a7752fd gtp: Pass pdp along when calling gtp_req() in gtp_update_context()
With no pdp parameter gtp_req() will send the packet to TEID 0 which is
not what we want. When trying to modify an established pdp context the
correct TEID of that context must be used.
2016-02-04 13:17:02 +01:00
Holger Hans Peter Freyther
8ddb6805a9 gtp: Do not leak the restart counter file handle in case of error
If the file exists but can not be read the file would not be closed.
Jump to a label that will close f.

Fixes: CID#57917
2016-01-23 10:40:52 +01:00
Holger Hans Peter Freyther
3a9befb516 gtp: Fix a bunch of compiler warnings when just including gtp.h
Attempt to fix a bunch of compiler warnings in OpenBSC.
‘struct pdp_t’ declared inside parameter list
2016-01-23 10:16:53 +01:00
Andreas Schultz
c80680a9c4 ggsn: fix autotool pkg-config invokation
see https://autotools.io/pkgconfig/pkg_check_modules.html, Optional Modules
for explanation

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
2015-12-21 08:37:50 +01:00
Andreas Schultz
c5fbf9bd68 ggsn: update gpt-kernel logging to libosmocore
Signed-off-by: Andreas Schultz <aschultz@tpip.net>
2015-12-21 08:37:26 +01:00
Pablo Neira Ayuso
4b075b6cb8 ggsn: add support for GTP kernel data encapsulation
This patch adds the -g, --gtpnl=device option that allows you to
enable the GTP kernel tunneling mode in openggsn. You have to specify
the real downlink device that will be used to tunnel traffic, eg.

	-g=eth0

This means that the gtp0 device will be created and it will use eth0
as the real device to encapsulate packet coming from the Internet that
are addressed to the MS (so the tunnel devuce encapsulates these IP
packets in GTP packets when traveling to the SGSN).

Alternatively, you can also add this to the ggsn.conf configuration file:

	gtpnl eth0

The device has to be the real device that can route packets to the SGSN,
if you select the wrong device, the kernel routing code may not find a
way to reach the SSGN, you've been warned.

Therefore, if this option is set, the operational becomes the following:

1) A gtp0 device is created via rtnetlink and configure the socket
   encapsulation infrastructure in the kernel.
2) Whenever a PDP context is created, this adds the necessary tunnel
   configuration via genetlink GTP interface.
3) Whenever a PDP context is destroyed, this deletes the tunnel via
   genetlink GTP interface.
4) Destroy the gtp0 device if ggsn is stopped, including all of the
   existing tunnels.

You require the osmo-ggsn.git tree, which contains the kernel module
gtp.ko and the libgtpnl library that you have to compile and install.
Make sure you have loaded the gtp.ko kernel module before launching
the ggsn daemon using the kernel driver mode, otherwise you will get
a nice "operation not supported" error message ;-).

This patch also adds supports for "ipup" configuration option to invoke
an external script after the gtp0 device has been brought up. Typical
command to add the route to reach the MS behind the GGSN is required,
eg. ip route add 10.0.0.0/8 dev gtp0.

The (horrible) ggsn parser has been manually extended to support the
new configuration option. That code doesn't look nice, but it just
mimics what we already have there for consistency, please don't blame
me for that.

If you want to run in debugging mode, I suggest you to use:

	sudo ggsn -c ggsn.conf -f -d

Note that you do have to run openggsn as root to bring up the gtp0
device. You have to see this message that announce that the GTP kernel
mode is enabled.

openggsn[1106]: ggsn.c: 656: Using the GTP kernel mode (genl ID is 25)

This patch also automagically sets up route to reach MS from Internet
just like tun mode does. This is fundamental to get this working,
better don't leave to the admin, he may forget to add this route.

In this patch, I tried to encapsulate this new feature as much as
possible as Harald initially suggested.

To compile this feature, you have to pass --enable-gtp-kernel, ie.

./configire --enable-gtp-kernel

Otherwise, the code to interact with the gtp kernel part is not compiled.

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
2015-12-21 08:37:11 +01:00
Holger Hans Peter Freyther
89dcb614e8 Release 0.92 of the GGSN needed for the gtphub 2015-11-30 14:06:09 +01:00
Harald Welte
ac0b4f17fe update version to 0.92 2015-11-20 10:34:17 +01:00
Andreas Schultz
10abfba949 convert literal APN name to protocol encoded version before use
The definition of the APN field format in GTPv1 is hidden in a chain
of documents.

3GPP TS 29.060 (the GTPv1-C specification) Section 7.7.30:

> The Access Point Name contains a logical name (see 3GPP TS 23.060 [4]).
> It is coded as in the value part defined in 3GPP TS 24.008

3GPP TS 24.008 Section 10.5.6.1:

> The value part is defined in 3GPP TS 23.003.

3GPP TS 23.003 Section 9.1:

> The APN consists of one or more labels. Each label is coded as a one
> octet length field followed by that number of octets coded as 8 bit
> ASCII characters

This converts a literal APN (e.g. Label1.Label2.Label3) to a structured
field (e.g. \006Label1\006Label2\006Label3)

Signed-off-by: Andreas Schultz <aschultz@tpip.net>
2015-11-13 17:16:03 +01:00
Holger Hans Peter Freyther
a377b0874a Revert "Makefile.am: define ACLOCAL_AMFLAGS, include directory m4"
aclocal: couldn't open directory `m4': No such file or directory

This reverts commit 04cbae494d.
2015-11-07 20:47:26 +01:00
Alexander Huemer
04cbae494d Makefile.am: define ACLOCAL_AMFLAGS, include directory m4 2015-11-07 12:41:25 +01:00
Alexander Huemer
db852a14fe fix some format specifiers 2015-11-07 12:40:48 +01:00
Alexander Huemer
e740e81281 configure.in -> configure.ac 2015-11-07 12:39:32 +01:00
Neels Hofmeyr
2ea010a1ed gitignore: add 'compile' (from autoconf) 2015-11-02 14:27:53 +01:00
Neels Hofmeyr
041824dfc8 sgsnemu: improve an error message 2015-11-02 14:27:44 +01:00
Holger Hans Peter Freyther
cd14094bb6 Dump dead code and never look at it again
This seems to be a wrong search. It seems to assume that there are
no buckets. Let's just remove it before looking at it too much.
2015-11-02 14:13:31 +01:00
Neels Hofmeyr
0dc4748447 add todo comments 2015-11-02 14:13:31 +01:00
Neels Hofmeyr
6c06d25667 make install: also install gtpie.h 2015-10-27 14:57:18 +01:00
127 changed files with 87897 additions and 6537 deletions

70
.gitignore vendored
View File

@@ -1,7 +1,9 @@
# autotools
Makefile
Makefile.in
aclocal.m4
autom4te.cache
compile
config.guess
config.h.in*
config.h
@@ -14,33 +16,69 @@ install-sh
libtool
ltmain.sh
missing
openggsn.spec
stamp-h1
doc/Makefile.in
ggsn/Makefile.in
gtp/Makefile.in
sgsnemu/Makefile.in
debian/openggsn/
debian/*.debhelper
debian/libgtp/
debian/*.log
INSTALL
m4/
Makefile
osmo-ggsn-*.tar*
.version
.tarball-version
# debian
debian/osmo-ggsn/
debian/*.debhelper
debian/libgtp*/
debian/osmo-ggsn-dbg
debian/*.log
debian/autoreconf.*
debian/*.substvars
debian/tmp/
sgsnemu/sgsnemu
debian/files
debian/libgtp-dev/
# programs / libraries
sgsnemu/sgsnemu
libgtp.pc
ggsn/ggsn
m4/
*.swp
ggsn/osmo-ggsn
# compiler results
*.o
*.a
*.la
*.lo
*.pyc
.deps
.libs
# misc
*.swp
.dirstamp
.deps
*.orig
*.new
*.rej
*/.deps
*/.libs
*/Makefile
*~
osmo-ggsn.cfg
sgsnemu.pid
gsn_restart
# testsuite
tests/atconfig
tests/*/*_test
tests/testsuite
tests/testsuite.log
tests/package.m4
# manuals
doc/manuals/*.html
doc/manuals/*.svg
doc/manuals/*.pdf
doc/manuals/*__*.png
doc/manuals/*.check
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

3
.gitreview Normal file
View File

@@ -0,0 +1,3 @@
[gerrit]
host=gerrit.osmocom.org
project=osmo-ggsn

23
AUTHORS
View File

@@ -1,9 +1,16 @@
OpenGGSN - Gateway GPRS Support Node
Copyright (C) 2002 Mondru AB.
The initial developer of the original code is
Jens Jakobsen <jj@openggsn.org>
Contributor(s):
OsmoGGSN - Osmocom Gateway GPRS Support Node, based on OpenGGSN
Copyright (C) 2002-2004 Mondru AB, Author: Jens Jakobsen <jj@openggsn.org>
Copyright (C) 2010-2017 Harald Welte <laforge@gnumonks.org>
Copyright (C) 2012-2016 Holger Hans Peter Freyther <zecke@selfish.org>
Copyright (C) 2014-2016 Pablo Neira Ayuso <pablo@gnumonks.org>
Copyright (C) 2014-2016 sysmocom - s.f.m.c. GmbH
Contributors:
Emmanuel Bretelle <chantra@debuntu.org>
Yann BONNAMY <yann_bonnamy@yahoo.fr>
Eric Butler <eric@codebutler.com>
Michael McTernan <mike.mcternan@wavemobile.com>
Alexander Huemer <alexander.huemer@xx.vu>
BJovke <bjovan@gmail.com>
Alexander Couzens <lynxis@fe80.eu>
Ruben Undheim <ruben.undheim@gmail.com>

142
ChangeLog
View File

@@ -1,142 +0,0 @@
2004-12-30: Jens Jakobsen <jj@openggsn.org>
Initial MAC OS X support
Quality assurance and improved error logging
QoS length bug fix.
2004-09-11: Jens Jakobsen <jj@openggsn.org>
Added selection mode option to sgsnemu.
Added charging characteristics option to sgsnemu.
Only include charging characteristics in create PDP context
request is if flags are set. (Thanks to Loic Bernable
<leto@vilya.org>).
PPP PCO length bug fix. (Thanks to Loic Bernable
<leto@vilya.org>).
IP pool hash table bugfix and improved logging.
Improved configure.in and Makefile.am for compilation under
Solaris. New config.sub and config.guess.
2004-04-28: Jens Jakobsen <jj@openggsn.org>
Improved Solaris support. OpenGGSN now correctly initializes
tun/tap driver under Solaris. As a consequence the ggsn network
interface IP address is set to the network address plus one.
Added routing manipulation and IP address alias capability for
FreeBSD.
2004-01-19: Jens Jakobsen <jj@openggsn.org>
Initial FreeBSD port (Thanks to Pavel Andreev <pavel.andreev@hp.com>).
IMSI bugfix. The IMSI encoding used by create PDP context was
missing the leading '1111' to indicate that the 16'nd digit was
unused. (Thanks to Pavel Andreev <pavel.andreev@hp.com>).
2004-01-15: Jens Jakobsen <jj@openggsn.org>
Added iptables firewall script.
2004-01-14: Jens Jakobsen <jj@openggsn.org>
Changes to allow compilation under Solaris: u_int8_t changed to uint8_t
and tun api changed for sun platform (#ifdef).
2004-01-09: Jens Jakobsen <jj@openggsn.org>
Fixed bug which included NSAPI in GTPv0 create PDP context messages.
2003-11-10: Jens Jakobsen <jj@openggsn.org>
Added --net option for sgsnemu. Allow user to specify the network
address and mask of the local interface.
Added --gtpversion option for sgsnemu. Allow user to specify which
GTP version to use.
Added --nsapi option for sgsnemu. Allow user to specify which
NSAPI to use.
Changed the functionality for multiple contexts. Previously
contexts were differentiated by nsapi. This limited the number of
contexts to 16. Now each context is established with a new imsi
and msisdn.
2003-10-22: Jens Jakobsen <jj@openggsn.org>
Support for GTP1. Currently without support for the secondary pdp
context activation procedure.
sgsnemu will first attempt to use GTP1. If that fails it will
proceed with GTP0.
Various gtplib API changes to allow support for GTP1.
gtplib now listens to 3 separate UDP ports: GTP0, GTP1 control
plane and GTP1 user plane. A socket for each port has to be
included in the application select loop.
gtplib now verifies that messages are valid for the particular
type of support node. As an example a received Create PDP Context
Request message is not allowed for an SGSN.
Standards compliance document.
2003-07-07: Jens Jakobsen <jj@openggsn.org>
Added spec.in file for building binary RPM packages. Now openggsn
will install binaries, man pages as well as scripts.
Added ggsn and sgsnemu man pages
Added ggsn Sys V init script
Added bootstrap script for autotools automation
2003-04-11: Jens Jakobsen <jj@openggsn.org>
Added -ggdb to gtp, sgsnemu and ggsn makefiles in order to include
debugging information.
Added ippool.c and ippool.h to ggsn. This allows for generic
allocation of dynamic ip addresses based on a <net>/<mask>
description of ip address space. The same files are also used in
sgsnemu, but only for hashing IP addresses. At the same time the
corresponding functionality is removed from pdp.c.
Added syserr.h and syserr.c to ggsn and sgsnemu. These files allow
writing to syslog with file name and line number. Later this
should also be introduced in gtp.
Added support for DNS protocol configuration options in ggsn for
create context response. This allow the MS to setup DNS
configuration correctly.
tun.c and tun.h have been updated to allow setting interface IP
addresses and routes by means of ioctl and netlink. This allow
sgsnemu to allocate an interface IP address for each context
established.
2003-01-29: Jens Jakobsen <jj@openggsn.org>
Added -L../gtp to sgsnemu and ggsn makefiles so that make will
work without an installed libgtp.
Added sgsnemu check to check for valid pointer when deleting tun.
Removed enabling of ip_forward = 1 from ggsn.c and sgsnemu. From a
security point of view it was not very good that openggsn
automatically enabled routing.
Added ipup, ipdown and createif to sgsnemu/cmdline.ggo. Now
sgsnemu will set up default route and then execute ipup script
after tun device has been set up. After tun has been deleted the
ipdown script is executed.
Added support for ping to sgsnemu.
Added ipup and ipdown to ggsn/cmdline.ggo.

View File

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

78
NEWS
View File

@@ -1,78 +0,0 @@
OPENGGSN NEWS
=============
OpenGGSN - Gateway GPRS Support Node
Copyright (C) 2002, 2003, 2004 Mondru AB.
Version 0.84
============
* Initial MAC OSX support (Thanks to Pekka Nikander)
* Quality assurance and improved error logging (Thanks to Pekka
Nikander and Jonny Winberg)
Version 0.83
============
* Added selection mode and charging characteristics option to sgsnemu.
* Bug fixes on charging characteristics and PPP PCO length.(Thanks to
Loic Bernable <leto@vilya.org>).
* Improved Solaris support, hash table bugfix and improved logging.
Version 0.82
============
* Improved Solaris support.
* Routing manipulation and IP address alias capability for FreeBSD.
* Initial Debian port (Thanks to ARAKI Yasuhiro <ar@debian.org>).
Version 0.81
============
* Initial FreeBSD port (Thanks to Pavel Andreev <pavel.andreev@hp.com>).
* IMSI '1111' bugfix (Thanks to Pavel Andreev <pavel.andreev@hp.com>).
Version 0.8
===========
* Support for compilation under Solaris.
* Iptables firewall script.
* New options for sgsnemu
Version 0.7
===========
* Support for GTP1. Currently without support for the secondary pdp
context activation procedure.
* sgsnemu will first attempt to use GTP1. If that fails it will
fallback to using GTP0.
* Standards compliance document.
Version 0.6
===========
* Improved README file.
* Now uses ioctl instead of ifconfig and route in ggsn and sgsnemu.
* Absolute path to gtp library in ggsn/Makefile.am and ggsn/Makefile.am
* Compiles with gengetopt 2.8 (Thanks to Lorenzo Bettini <bettini@gnu.org>)
* sgsnemu is now able to handle several contexts and allocate
interface IP addresses for each context.
* ggsn now supports protocol configuration option DNS
addresses. This allow mobile stations to set up DNS based on
information configured in the ggsn.
* Ping facility in sgsnemu allow testing without the need to route
packets through the tun interface.
* Man pages for ggsn and sgsnemu.
* Sys 5 init script.
* Spec file for building binary RPM packages.
* If not --createif exit after "ping" or "echo" finishes
* If sgsnemu echo failure, exit with code != 0
Version 0.5
===========
* Initial release. See README file for installation and usage
instructions.

View File

@@ -1,4 +1,4 @@
OpenGGSN/FreeBSD notes
OsmoGGSN/FreeBSD notes
FreeBSD support is experimental, please test and report bugs. The FreeBSD port is
tested on FreeBSD 4.x, but may also work on 5.x series.

View File

@@ -1,4 +1,4 @@
OpenGGSN/Mac OS X notes
OsmoGGSN/Mac OS X notes
Mac OS X support is experimental, please test and report bugs. The
Mac OS X port is tested on Mac OS X 10.3.5, but may also work on

View File

@@ -1,41 +0,0 @@
OpenGGSN/Solaris notes
======================
Solaris support is experimental, please test and report bugs. The
Solaris port is tested under Solaris 8.
Compiling
---------
You need to edit the following line in ggsn/Makefile.in and
sgsnemu/Makefile.in:
LDFLAGS = -Wl,--rpath -Wl,/usr/local/lib @EXEC_LDFLAGS@
should be changed to:
LDFLAGS = -lresolv -lsocket -lnsl @EXEC_LDFLAGS@
After this you install by the following commands:
./configure
make
make install
TUN
---
You might or might not need to install the tun driver manually. For
general information about tun see http://vtun.sourceforge.net/tun/
Known problems
--------------
Currently multiple IP addresses on the same network interface is not
implemented for Solaris.
Currently routing table manipulation is not implemented for
Solaris. You have to set the routes manually after you start ggsn or
sgsnemu.

View File

@@ -1,23 +1,79 @@
OPENGGSN README
===============
OsmoGGSN - Open Source GGSN
===========================
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.
Homepage
--------
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
There is a cgit interface at http://git.osmocom.org/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.
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
subscription options and the list archive.
Please observe the [Osmocom Mailing List
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
when posting.
Contributing
------------
Our coding standards are described at
https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
We us a gerrit based patch submission/review process for managing
contributions. Please see
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
QuickStart
==========
Requirements
------------
*Linux*
OpenGGSN was developed and tested using Redhat 8.0 and 9.0. It should
run also on other Linux distributions as well as FreeBSD, but this is
OsmoGGSN was originally developed and tested using Redhat 8.0 and 9.0
and is these days mostly developed on Debian GNU/Linux. It should run
also on other Linux distributions as well as FreeBSD, but this is
untested. Compilation on Solaris 2.8 has also been verified.
*Tun*
The tun driver is required for proper operation of openggsn. For linux
kernels later than 2.4.7 the driver is typically included, but need
to be configured for automatic loading:
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
@@ -26,10 +82,10 @@ to be configured for automatic loading:
Installation from binary
------------------------
rpm -i openggsn-<version>.rpm
This will install binaries, man pages, configuration files as well as
a Sys V init script for the ggsn.
OsmoGGSN is built for common versions of Debian and Ubuntu as 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.
Installation from source
@@ -77,19 +133,19 @@ can use sgsnemu to test the GGSN.
Support
-------
If you have any questions drop me a line at jj@openggsn.org.
Please contact the Mailing List above for community-based support.
Features
========
OpenGGSN is an open source implementation of GPRS Support Nodes
OsmoGGSN is an open source implementation of GPRS Support Nodes
(GSNs). It implements the GPRS tunneling protocol (GTP) version 0 and
version 1.
OpenGGSN provides 3 components:
OsmoGGSN provides 3 components:
* gtplib
* ggsn
* osmo-ggsn
* sgsnemu
*gtplib*
@@ -99,8 +155,8 @@ GSN. gtplib supports both GTPv0 (GSM 09.60) and GTPv1 (3GPP
29.060). At the moment no interface documentation is available for
download.
*ggsn*
The ggsn implements a Gateway GPRS Support Node. The GGSN is a small
*osmo-ggsn*
The osmo-ggsn implements a Gateway GPRS Support Node. The GGSN is a small
application which is provided in order to test and demonstrate the use
of gtplib. It is fully compliant to the 3GPP standards, but lacks
important functionality such as charging and management. Use this
@@ -116,33 +172,13 @@ exchange. sgsnemu will first attempt to use GTPv1. If unsuccessful it
will fallback to GTPv0.
Performance
===========
Two experiments were performed in order to test the performance of
sgsnemu and ggsn. The ggsn used a 550 MHz Athlon with 384 MB of
RAM. sgsnemu used a 1 GHz Athlon with 256 MB of RAM. Both machines had
100 Mb/s NICs (RTL-8139) and were connected through a crossed patch
cable. Both tests were performed by sending ICMP echo packets from
sgsnemu to the ggsn.
89.5 Mb/s IP throughput when sending 10000 ICMP ping packets with a
payload of 1400 bytes. Transfer time 1.27 sec, no packets lost.
71.4 Mb/s IP throughput when sending 10000 ICMP ping packets with a
payload of 1000 bytes. Transfer time 1.15 sec, no packets lost.
12,1 Mb/s IP throughput when sending 10000 ICMP ping packets with a
payload of 100 bytes. Transfer time 0.84 sec, no packets lost.
Required software
=================
Tun
---
Both ggsn and sgsnemu uses the tun package. You need at least tun
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:
@@ -151,9 +187,6 @@ version 1.1. With Linux tun is normally included from kernel version
Alternatively you can execute "modprobe tun" on the commandline.
For Solaris the tun driver needs to be installed manually. For general
information about tun see http://vtun.sourceforge.net/tun/
Gengetopt
---------
@@ -161,10 +194,6 @@ Gengetopt is required if you want to change the options defined in the
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 ggsn do the following:
cd ggsn
gengetopt < cmdline.ggo --conf-parser
To use gengetopt for the sgsnemu do the following:
cd sgsnemu
gengetopt < cmdline.ggo --conf-parser
@@ -176,111 +205,19 @@ http://www.gnu.org/software/gengetopt/gengetopt.html
Compilation and Installation
============================
Setting up autotools
--------------------
You do not need to perform this step if you are only going to compile
the package:
1. Get version from somewhere: Script to extract version from configure.in
2. Copy the latest config.guess and config.sub from ftp://ftp.gnu.org/gnu/config
3. Run autoscan and copy configure.scan to configure.in
4. Add/edit the following lines in configure.in:
- AC_INIT(openggsn, 0.70, jj@openggsn.org)
- AC_CONFIG_SRCDIR([gtp/gtp.c])
- AM_CONFIG_HEADER([config.h])
- AC_PROG_LIBTOOL
- AM_PROG_LIBTOOL
- AM_INIT_AUTOMAKE()
5. libtoolize --automake --copy
(ads copy of ltmain.sh)
6. aclocal
7. autoheader
8. automake --add-missing --copy
(Ads copy of mkinstalldirs missing, install-sh, depcomp)
9. automake
10. autoconf
The above will initialise the project to the current version of
autotools (As installed in RedHat 8.0). See
http://sources.redhat.com/autobook/autobook/autobook_25.html#SEC25
for details on autotools.
Please refer to the project homepage
Checking out from CVS
---------------------
Running osmo-ggsn
=================
To download the latest source code from anonymous CVS:
cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/ggsn login
cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/ggsn co openggsn
Or to download from developer CVS:
export CVS_RSH=ssh
cvs -z3 -d:ext:developername@cvs.sourceforge.net:/cvsroot/ggsn co openggsn
Both the above sets of commands creates a new directory called openggsn.
Compilation and installation
----------------------------
If compiling under Solaris you need to edit the following line in
ggsn/Makefile.in and sgsnemu/Makefile.in:
LDFLAGS = -Wl,--rpath -Wl,/usr/local/lib @EXEC_LDFLAGS@
should be changed to:
LDFLAGS = -lresolv -lsocket -lnsl @EXEC_LDFLAGS@
Note that the above is not necessary on other platforms. Compilation
and installation is performed by the following steps:
1. ./configure
2. make clean
3. cd gtp
4. make
5. make install (as root)
6. cd ..
(Step 3 to 6 you only need to run the first time to install libgtp)
7. make
8. make install (as root)
9. Add /usr/local/lib to /etc/ld.so.conf
10. run ldconfig
(Steps 9 and 10 are not required as path to libgtp is included in Makefile)
Documentation can be converted to html by issuing:
1. txt2html -pm -tf README > README.html
2. txt2html -pm -tf NEWS > NEWS.html
3. txt2html -pm -tf ChangeLog > ChangeLog.html
4. man2htm ggsn.8 > ggsn.html
5. man2htm sgsnemu.8 > sgsnemu.html
Installation from binary
------------------------
1. rpm -i openggsn-<version>.rpm
This will install binaries, man pages, configuration files as well as
a Sys V init script for the ggsn.
Running ggsn
============
Use ggsn -h for a list of available options. All options available on
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/ggsn.conf for the format of this file.
examples/osmo-ggsn.cfg for the format of this file.
Start the ggsn as root using the command:
Start osmo-ggsn as root using the command:
ggsn -c examples/ggsn.conf --fg -l 10.0.0.40 --net 192.168.0.0/24 --dynip 192.168.0.0/24
osmo-ggsn -c 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
@@ -309,9 +246,9 @@ Remember to enable routing:
echo 1 > /proc/sys/net/ipv4/ip_forward
If you installed using a binary RPM package it is possible to start
ggsn by using the Sys 5 script:
osmo-ggsn by using the Sys 5 script:
/etc/init.d/ggsn start
/etc/init.d/osmo-ggsn start
Running sgsnemu
@@ -326,8 +263,7 @@ following:
1. Install sgsnemu on a Linux Box. See under installation above.
2. Connect your Linux box with sgsnemu installed to the GPRS core
network. Use the same LAN switch as the one your SGSN is connected
to. You also need a free IP address that can be used by sgsnemu.
network. You also need a free IP address that can be used by sgsnemu.
3. You need to configure networking in terms of interface address,
subnet mask and default route. See the Linux Networking HOWTO for
details.
@@ -337,7 +273,6 @@ sgsnemu --listen 10.0.0.50 --remote 10.0.0.40 --dns 10.20.38.51 --timelimit 10 -
sgsnemu will print something like the following on the screen:
<PRE>
Using DNS server: 10.20.38.51 (10.20.38.51)
Local IP address is: 10.0.0.50 (10.0.0.50)
@@ -347,7 +282,7 @@ sgsnemu will print something like the following on the screen:
Using MSISDN: 46702123456
Initialising GTP library
OpenGGSN[1823]: GTP: gtp_newgsn() started
OsmoGGSN[1823]: GTP: gtp_newgsn() started
Done initialising GTP library
Sending off echo request
@@ -355,8 +290,6 @@ sgsnemu will print something like the following on the screen:
Received echo response. Cause value: 0
</PRE>
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
you did not get an echo response it means that something is wrong
@@ -377,8 +310,6 @@ sgsnemu --listen 10.0.0.50 --remote 10.0.0.40 --dns 10.20.38.51 --timelimit 10 -
sgsnemu will print something like the following on the screen:
<PRE>
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)
@@ -387,7 +318,7 @@ sgsnemu will print something like the following on the screen:
Using MSISDN: 46702123456
Initialising GTP library
OpenGGSN[1838]: GTP: gtp_newgsn() started
OsmoGGSN[1838]: GTP: gtp_newgsn() started
Done initialising GTP library
Sending off echo request
@@ -400,7 +331,6 @@ sgsnemu will print something like the following on the screen:
/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
</PRE>
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
@@ -420,11 +350,7 @@ After --timelimit seconds the PDP context is disconnected with the
following messages from sgsnemu:
<PRE>
Disconnecting PDP context #0
Received delete PDP context response. Cause value: 128
Deleting tun interface
</PRE>

9
TODO-RELEASE Normal file
View File

@@ -0,0 +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:
# 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 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

274
configure.ac Normal file
View File

@@ -0,0 +1,274 @@
# Process this file with autoconf to produce a configure script.
AC_INIT([osmo-ggsn],[m4_esyscmd(./git-version-gen .tarball-version)],[osmocom-net-gprs@lists.osmocom.org])
AC_CONFIG_SRCDIR([gtp/gtp.c])
AC_CONFIG_HEADERS([config.h])
dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
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])])
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_AWK
AC_PROG_CPP
LT_INIT
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'])])
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
AC_MSG_WARN([You need to install pkg-config])
fi
PKG_PROG_PKG_CONFIG([0.20])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_LIBOBJ_DIR([lib])
AC_ARG_ENABLE(static-exec,
[ --enable-static-exec Enable static linking of executables],
[ EXEC_LDFLAGS="-all-static"])
AC_SUBST(EXEC_LDFLAGS)
case "${host}" in
i*86-*-linux-gnu*)
EXEC_LDADD="" ;;
*solaris*)
EXEC_LDADD="-lresolv -lsocket -lnsl" ;;
esac
AC_SUBST(EXEC_LDADD)
# Checks for libraries.
# FIXME: Replace `main' with a function in `-le':
#AC_CHECK_LIB([e], [main])
# FIXME: Replace `main' with a function in `-lgtp':
#AC_CHECK_LIB([gtp], [main])
# FIXME: Replace `main' with a function in `-links':
#AC_CHECK_LIB([inks], [main])
dnl include release helper
RELMAKE='-include osmo-release.mk'
AC_SUBST([RELMAKE])
dnl GTP Linux kernel dependencies
AC_ARG_ENABLE([gtp-linux],
AS_HELP_STRING([--enable-gtp-linux], [Build GTP tunneling Linux kernel]),
[enable_gtp_linux="$enableval"], [enable_gtp_linux="no"])
AS_IF([test "x$enable_gtp_linux" = "xyes"], [
PKG_CHECK_MODULES([LIBGTPNL], [libgtpnl >= 1.2.0])
])
AM_CONDITIONAL([ENABLE_GTP_KERNEL], [test "$enable_gtp_linux" = "yes"])
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h])
# Check for if header. Some versions of linux/if.h fail without sys/socket.h included beforehand:
# see https://algorithmicallyrandom.blogspot.com/2012/07/error-on-including-include.html
AC_CHECK_HEADERS([linux/if.h net/if.h], [], [], [#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
# endif
])
# Check for tun header
AC_CHECK_HEADERS([linux/if_tun.h net/if_tun.h])
# Check for netlink and rtnetlink headers
AC_CHECK_HEADERS([linux/netlink.h linux/rtnetlink.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_MODE_T
AC_TYPE_SIZE_T
AC_HEADER_TIME
# check for ifaliasreq
AC_MSG_CHECKING(whether struct ifaliasreq exist)
AH_TEMPLATE(HAVE_IFALIASREQ)
AC_EGREP_HEADER(ifaliasreq, net/if.h,
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_IFALIASREQ])],
AC_MSG_RESULT(no))
# check for ifreq.ifru_netmask
AC_MSG_CHECKING(whether struct ifreq.ifru_netmask exist)
AH_TEMPLATE(HAVE_IFREQ_IFRU_NETMASK)
AC_EGREP_HEADER(ifru_netmask, linux/if.h,
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_IFREQ_IFRU_NETMASK])],
AC_MSG_RESULT(no))
# check for rt_msghdr
AC_MSG_CHECKING(whether struct rt_msghdr exist)
AH_TEMPLATE(HAVE_RT_MSGHDR)
AC_EGREP_HEADER(rt_msghdr, net/route.h,
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RT_MSGHDR])],
AC_MSG_RESULT(no))
AC_MSG_CHECKING(whether struct iphdr exists)
AH_TEMPLATE(HAVE_IPHDR)
AC_EGREP_HEADER(struct iphdr, netinet/ip.h,
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_IPHDR])],
AC_MSG_RESULT(no))
# Address generation modes (enum) implemented in linux 3.17 (bc91b0f07ada5535427373a4e2050877bcc12218)
# /proc/sys/net/ipv6/conf/${iface}/addr_gen_mode was added in linux 4.11 (d35a00b8e33dab7385f724e713ae71c8be0a49f4)
AC_MSG_CHECKING(whether enum in6_addr_gen_mode.IN6_ADDR_GEN_MODE_NONE exists)
AH_TEMPLATE(HAVE_IN6_ADDR_GEN_MODE_NONE)
AC_EGREP_HEADER(IN6_ADDR_GEN_MODE_NONE, linux/if_link.h,
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_IN6_ADDR_GEN_MODE_NONE])],
AC_MSG_RESULT(no))
# Checks for library functions.
AC_PROG_GCC_TRADITIONAL
# AC_FUNC_MALLOC
# AC_FUNC_MEMCMP
AC_CHECK_FUNCS([gethostbyname inet_ntoa memset select socket strdup strerror strtol])
AC_CHECK_FUNCS(inet_aton inet_addr, break)
# check for getopt in standard library
adl_FUNC_GETOPT_LONG
AM_INIT_AUTOMAKE([foreign])
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.5.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.5.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.5.0)
AC_ARG_ENABLE(sanitize,
[AS_HELP_STRING(
[--enable-sanitize],
[Compile with address sanitizer enabled],
)],
[sanitize=$enableval], [sanitize="no"])
if test x"$sanitize" = x"yes"
then
CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
fi
AC_ARG_ENABLE(werror,
[AS_HELP_STRING(
[--enable-werror],
[Turn all compiler warnings into errors, with exceptions:
a) deprecation (allow upstream to mark deprecation without breaking builds);
b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
]
)],
[werror=$enableval], [werror="no"])
if test x"$werror" = x"yes"
then
WERROR_FLAGS="-Werror"
WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
CFLAGS="$CFLAGS $WERROR_FLAGS"
CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
fi
# Generate manuals
AC_ARG_ENABLE(manuals,
[AS_HELP_STRING(
[--enable-manuals],
[Generate manual PDFs [default=no]],
)],
[osmo_ac_build_manuals=$enableval], [osmo_ac_build_manuals="no"])
AM_CONDITIONAL([BUILD_MANUALS], [test x"$osmo_ac_build_manuals" = x"yes"])
AC_ARG_VAR(OSMO_GSM_MANUALS_DIR, [path to common osmo-gsm-manuals files, overriding pkg-config and "../osmo-gsm-manuals"
fallback])
if test x"$osmo_ac_build_manuals" = x"yes"
then
# Find OSMO_GSM_MANUALS_DIR (env, pkg-conf, fallback)
if test -n "$OSMO_GSM_MANUALS_DIR"; then
echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from env)"
else
OSMO_GSM_MANUALS_DIR="$($PKG_CONFIG osmo-gsm-manuals --variable=osmogsmmanualsdir 2>/dev/null)"
if test -n "$OSMO_GSM_MANUALS_DIR"; then
echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from pkg-conf)"
else
OSMO_GSM_MANUALS_DIR="../osmo-gsm-manuals"
echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (fallback)"
fi
fi
if ! test -d "$OSMO_GSM_MANUALS_DIR"; then
AC_MSG_ERROR("OSMO_GSM_MANUALS_DIR does not exist! Install osmo-gsm-manuals or set OSMO_GSM_MANUALS_DIR.")
fi
# Find and run check-depends
CHECK_DEPENDS="$OSMO_GSM_MANUALS_DIR/check-depends.sh"
if ! test -x "$CHECK_DEPENDS"; then
CHECK_DEPENDS="osmo-gsm-manuals-check-depends"
fi
if ! $CHECK_DEPENDS; then
AC_MSG_ERROR("missing dependencies for --enable-manuals")
fi
# Put in Makefile with absolute path
OSMO_GSM_MANUALS_DIR="$(realpath "$OSMO_GSM_MANUALS_DIR")"
AC_SUBST([OSMO_GSM_MANUALS_DIR])
fi
# https://www.freedesktop.org/software/systemd/man/daemon.html
AC_ARG_WITH([systemdsystemunitdir],
[AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
[with_systemdsystemunitdir=auto])
AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
AS_IF([test "x$def_systemdsystemunitdir" = "x"],
[AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
[AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
with_systemdsystemunitdir=no],
[with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
[AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
AC_MSG_RESULT([CFLAGS="$CFLAGS"])
AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
AC_CONFIG_FILES([Makefile
doc/Makefile
doc/examples/Makefile
ggsn/Makefile
gtp/Makefile
lib/Makefile
intl/Makefile
po/Makefile
utils/Makefile
sgsnemu/Makefile
doc/manuals/Makefile
contrib/Makefile
contrib/systemd/Makefile
contrib/osmo-ggsn.spec
tests/Makefile
tests/lib/Makefile
tests/gtp/Makefile
libgtp.pc])
AC_OUTPUT
echo "
osmo-ggsn Configuration:
GTP Linux kernel support: ${enable_gtp_linux}"

View File

@@ -1,121 +0,0 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(openggsn, 0.91, laforge@gnumonks.org)
AC_CONFIG_SRCDIR([gtp/gtp.c])
AM_CONFIG_HEADER([config.h])
#AC_CONFIG_HEADER([config.h])
AC_CANONICAL_SYSTEM
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_AWK
AC_PROG_CPP
AC_PROG_CXX
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_LIBOBJ_DIR([lib])
AC_ARG_ENABLE(static-exec,
[ --enable-static-exec Enable static linking of executables],
[ EXEC_LDFLAGS="-all-static"])
AC_SUBST(EXEC_LDFLAGS)
case "${host}" in
i*86-*-linux-gnu*)
EXEC_LDADD="" ;;
*solaris*)
EXEC_LDADD="-lresolv -lsocket -lnsl" ;;
esac
AC_SUBST(EXEC_LDADD)
# Checks for libraries.
# FIXME: Replace `main' with a function in `-le':
#AC_CHECK_LIB([e], [main])
# FIXME: Replace `main' with a function in `-lgtp':
#AC_CHECK_LIB([gtp], [main])
# FIXME: Replace `main' with a function in `-links':
#AC_CHECK_LIB([inks], [main])
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h])
# Check for if header
AC_CHECK_HEADERS([linux/if.h net/if.h])
# Check for tun header
AC_CHECK_HEADERS([linux/if_tun.h net/if_tun.h])
# Check for netlink and rtnetlink headers
AC_CHECK_HEADERS([linux/netlink.h linux/rtnetlink.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_MODE_T
AC_TYPE_SIZE_T
AC_HEADER_TIME
# check for ifaliasreq
AC_MSG_CHECKING(whether struct ifaliasreq exist)
AH_TEMPLATE(HAVE_IFALIASREQ)
AC_EGREP_HEADER(ifaliasreq, net/if.h,
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_IFALIASREQ])],
AC_MSG_RESULT(no))
# check for ifreq.ifru_netmask
AC_MSG_CHECKING(whether struct ifreq.ifru_netmask exist)
AH_TEMPLATE(HAVE_IFREQ_IFRU_NETMASK)
AC_EGREP_HEADER(ifru_netmask, linux/if.h,
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_IFREQ_IFRU_NETMASK])],
AC_MSG_RESULT(no))
# check for rt_msghdr
AC_MSG_CHECKING(whether struct rt_msghdr exist)
AH_TEMPLATE(HAVE_RT_MSGHDR)
AC_EGREP_HEADER(rt_msghdr, net/route.h,
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RT_MSGHDR])],
AC_MSG_RESULT(no))
# Checks for library functions.
AC_PROG_GCC_TRADITIONAL
# AC_FUNC_MALLOC
# AC_FUNC_MEMCMP
AC_CHECK_FUNCS([gethostbyname inet_ntoa memset select socket strdup strerror strtol])
AC_CHECK_FUNCS(inet_aton inet_addr, break)
# check for getopt in standard library
adl_FUNC_GETOPT_LONG
AM_INIT_AUTOMAKE()
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.6.4)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0)
AC_CONFIG_FILES([Makefile
doc/Makefile
ggsn/Makefile
gtp/Makefile
lib/Makefile
intl/Makefile
po/Makefile
sgsnemu/Makefile
tests/Makefile
libgtp.pc
openggsn.spec])
AC_OUTPUT

1
contrib/Makefile.am Normal file
View File

@@ -0,0 +1 @@
SUBDIRS = systemd

63
contrib/jenkins.sh Executable file
View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# jenkins build helper script for openbsc. This is how we build on jenkins.osmocom.org
#
# environment variables:
# * GTP: configure GTP tunneling Linux kernel (values: "--enable-gtp-linux" or "--disable-gtp-linux")
# * WITH_MANUALS: build manual PDFs if set to "1"
# * PUBLISH: upload manuals after building if set to "1" (ignored without WITH_MANUALS = "1")
#
if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
exit 2
fi
set -ex
base="$PWD"
deps="$base/deps"
inst="$deps/install"
export deps inst
osmo-clean-workspace.sh
mkdir "$deps" || true
if [ "x$GTP" == "x--enable-gtp-linux" ]; then
osmo-build-dep.sh libgtpnl
fi
osmo-build-dep.sh libosmocore "" ac_cv_path_DOXYGEN=false
verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$inst/lib"
export PATH="$inst/bin:$PATH"
# Additional configure options and depends
CONFIG=""
if [ "$WITH_MANUALS" = "1" ]; then
CONFIG="--enable-manuals"
fi
set +x
echo
echo
echo
echo " =============================== OsmoGGSN ==============================="
echo
set -x
cd "$base"
autoreconf --install --force
./configure --enable-sanitize --enable-werror $GTP $CONFIG
$MAKE $PARALLEL_MAKE
DISTCHECK_CONFIGURE_FLAGS="$CONFIG" $MAKE $PARALLEL_MAKE distcheck
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
make -C "$base/doc/manuals" publish
fi
$MAKE $PARALLEL_MAKE maintainer-clean
osmo-clean-workspace.sh

View File

@@ -1,10 +1,10 @@
#!/bin/sh
#
# ggsn This shell script takes care of starting and stopping
# ggsn.
# osmo-ggsn This shell script takes care of starting and stopping
# osmo-ggsn.
#
# chkconfig: - 65 35
# description: ggsn is a Gateway GPRS Support Node.
# description: osmo-ggsn is a Gateway GPRS Support Node.
# Source function library.
. /etc/rc.d/init.d/functions
@@ -12,18 +12,18 @@
# Source networking configuration.
. /etc/sysconfig/network
if [ -f /etc/sysconfig/ggsn ]; then
. /etc/sysconfig/ggsn
if [ -f /etc/sysconfig/osmo-ggsn ]; then
. /etc/sysconfig/osmo-ggsn
fi
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -f /usr/bin/ggsn ] || exit 0
[ -f /etc/ggsn.conf ] || exit 0
[ -f /usr/bin/osmo-ggsn ] || exit 0
[ -f /etc/osmo-ggsn.cfg ] || exit 0
RETVAL=0
prog="ggsn"
prog="osmo-ggsn"
start() {
# Start daemons.
@@ -37,30 +37,30 @@ start() {
# echo 1 > /proc/sys/net/ipv4/ip_forward
# Check for runtime directory of nonvolatile data
if [ ! -d /var/lib/ggsn ]; then
mkdir /var/lib/ggsn
if [ ! -d /var/lib/osmo-ggsn ]; then
mkdir /var/lib/osmo-ggsn
fi
# Check for GTP restart counter
if [ ! -d /var/lib/ggsn/gsn_restart ]; then
echo 0 > /var/lib/ggsn/gsn_restart
if [ ! -d /var/lib/osmo-ggsn/gsn_restart ]; then
echo 0 > /var/lib/osmo-ggsn/gsn_restart
fi
daemon /usr/bin/ggsn
daemon /usr/bin/osmo-ggsn
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/ggsn
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/osmo-ggsn
return $RETVAL
}
stop() {
# Stop daemons.
echo -n $"Shutting down $prog: "
killproc ggsn
killproc osmo-ggsn
RETVAL=$?
echo
[ $RETVAL = 0 ] && rm -f /var/lock/subsys/ggsn /var/run/ggsn.pid
[ $RETVAL = 0 ] && rm -f /var/lock/subsys/osmo-ggsn /var/run/osmo-ggsn.pid
return $RETVAL
}
@@ -78,14 +78,14 @@ case "$1" in
RETVAL=$?
;;
condrestart)
if [ -f /var/lock/subsys/ggsn ] ; then
if [ -f /var/lock/subsys/osmo-ggsn ] ; then
stop
start
RETVAL=$?
fi
;;
status)
status ggsn
status osmo-ggsn
RETVAL=$?
;;
*)

137
contrib/osmo-ggsn.spec.in Normal file
View File

@@ -0,0 +1,137 @@
#
# spec file for package osmo-ggsn
#
# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
## Disable LTO for now since it breaks compilation of the tests
## https://osmocom.org/issues/4114
%define _lto_cflags %{nil}
Name: osmo-ggsn
Version: @VERSION@
Release: 0
Summary: GPRS Support Node
License: GPL-2.0-only AND LGPL-2.1-or-later
Group: Productivity/Telephony/Servers
URL: https://osmocom.org/projects/openggsn
Source: %{name}-%{version}.tar.xz
BuildRequires: libtool >= 2
BuildRequires: pkgconfig >= 0.20
%if 0%{?suse_version}
BuildRequires: systemd-rpm-macros
%endif
BuildRequires: pkgconfig(libgtpnl) >= 1.2.0
BuildRequires: pkgconfig(libosmocore) >= 1.5.0
BuildRequires: pkgconfig(libosmoctrl) >= 1.5.0
BuildRequires: pkgconfig(libosmovty) >= 1.5.0
Obsoletes: openggsn
%{?systemd_requires}
%description
Osmo-GGSN is a C-language implementation of a GGSN (Gateway GPRS
Support Node), a core network element of ETSI/3GPP cellular networks
such as GPRS, EDGE, UMTS or HSPA.
%package -n libgtp6
Summary: Library implementing GTP between SGSN and GGSN
License: GPL-2.0-only
Group: System/Libraries
%description -n libgtp6
libgtp implements the GPRS Tunneling Protocol between SGSN and GGSN.
%package -n libgtp-devel
Summary: Development files for the GTP library
License: GPL-2.0-only
Group: Development/Libraries/C and C++
Requires: libgtp6 = %{version}
%description -n libgtp-devel
libgtp implements the GPRS Tunneling Protocol between SGSN and GGSN.
This subpackage contains libraries and header files for developing
applications that want to make use of libgtp.
%package -n gtp-echo-responder
Summary: Small program answering GTP ECHO Request with GTP ECHO Response
License: MIT
Group: System/Libraries
%description -n gtp-echo-responder
Small program answering GTP ECHO Request with GTP ECHO Response for both GTPCv1
and GTPCv2.
%prep
%setup -q
%build
echo "%{version}" >.tarball-version
autoreconf -fi
%configure \
--enable-gtp-linux \
--disable-static \
--docdir="%{_docdir}/%{name}" \
--with-systemdsystemunitdir=%{_unitdir} \
--includedir="%{_includedir}/%{name}"
make %{?_smp_mflags} V=1
%install
%make_install
find %{buildroot} -type f -name "*.la" -delete -print
%check
make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%if 0%{?suse_version}
%pre
%service_add_pre %{name}.service
%post
%service_add_post %{name}.service
%preun
%service_del_preun %{name}.service
%postun
%service_del_postun %{name}.service
%endif
%post -n libgtp6 -p /sbin/ldconfig
%postun -n libgtp6 -p /sbin/ldconfig
%files
%license COPYING
%doc AUTHORS README.md
%{_bindir}/osmo-ggsn
%{_bindir}/sgsnemu
%{_mandir}/man8/osmo-ggsn.8%{?ext_man}
%{_mandir}/man8/sgsnemu.8%{?ext_man}
%{_unitdir}/%{name}.service
%dir %{_docdir}/%{name}/examples
%{_docdir}/%{name}/examples/osmo-ggsn-kernel-gtp.cfg
%{_docdir}/%{name}/examples/osmo-ggsn.cfg
%{_docdir}/%{name}/examples/sgsnemu.conf
%dir %{_sysconfdir}/osmocom
%config(noreplace) %{_sysconfdir}/osmocom/osmo-ggsn.cfg
%files -n libgtp6
%{_libdir}/libgtp.so.6*
%files -n libgtp-devel
%{_includedir}/%{name}/
%{_libdir}/libgtp.so
%{_libdir}/pkgconfig/libgtp.pc
%files -n gtp-echo-responder
%{_bindir}/gtp-echo-responder
%changelog

View File

@@ -0,0 +1,10 @@
EXTRA_DIST = \
osmo-ggsn.service \
ggsn.network \
apn0.netdev \
$(NULL)
if HAVE_SYSTEMD
systemdsystemunit_DATA = \
osmo-ggsn.service
endif

View File

@@ -0,0 +1,7 @@
[NetDev]
Name=apn0
Kind=tun
[Tun]
User=username
Group=username

View File

@@ -0,0 +1,6 @@
[Match]
Name=apn0
[Network]
Address=192.168.7.1/24
IPMasquerade=yes

View File

@@ -1,10 +1,11 @@
[Unit]
Description=OpenGGSN
Description=OsmoGGSN
After=networking.service
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/ggsn -c /etc/ggsn.conf -f
ExecStart=/usr/bin/osmo-ggsn -c /etc/osmocom/osmo-ggsn.cfg
RestartSec=2
RestartPreventExitStatus=1

461
debian/changelog vendored
View File

@@ -1,4 +1,463 @@
openggsn (0.91+git34) UNRELEASED; urgency=medium
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 ]
* build: switch AC_CANONICAL_TARGET for AC_CANONICAL_HOST
[ Pau Espin Pedrol ]
* libgtp: Remove packets in tx queue belonging pdp being freed
* libgtp: announce pdp ctx deletion upon CreatePdpCtx being rejected
* Introduce in46a_is_v{4,6}() helpers
* ggsn: Move PCO handling code into its own file
* in46_addr: Improve in46a_ntop documentation
* ggsn_vty.c: Fix wrong use of in46a_from_eua, print IPv6 euas
* ggsn: Split application lifecycle related code into ggsn_main.c
* Move pdp_get_peer_ipv() to lib/util.*
* gtp-kernel.c: Fix wrong use of in46a_from_eua, print IPv6 euas
* Introduce LOGTUN log helper
* ggsn_vty.c: Avoid printing duplicates for pdp context with v4v6 EUAs
* pdp: constify param in pdp_count_secondary()
* ggsn_vty.c: Improve output of VTY show pdp-context
* doc: Update vty reference xml file
* libgtp: Introduce cb_recovery3
* ggsn: Implement echo req/resp and recovery
* cosmetic: fix formatting in if line
* gtp: Log msg retransmits and timeouts
* cosmetic: gtp: Drop commented out code calling pdp_freepdp()
* cosmetic: gtp: Improve documentation of gtp_delete_context_req2()
* ggsn: rx DeletePdpReq confirmation: Improve documentation and use gtp_freepdp()
* gtp: Manage queue timers internally
* ggsn, sgsnemu: Drop use of no-op deprecated gtp_retrans* APIs
[ Vadim Yanitskiy ]
* gtp_update_pdp_ind(): fix NULL-pointer dereference
* gtp_error_ind_conf(): fix: guard against an unknown GTP version
* gtp/gtp.c: cosmetic: use get_tid() where we need TID
* manuals/configuration.adoc: fix Network Address without prefix length
* manuals/configuration.adoc: fix IPv4 address mismatch in <<ggsn_no_root>>
* contrib/systemd: add systemd-networkd examples from manuals
[ Harald Welte ]
* sgsnemu: Fix null-pointer format string argument
* manual: Fix copy+paste error
-- Pau Espin Pedrol <pespin@sysmocom.de> Thu, 02 Jan 2020 20:39:39 +0100
osmo-ggsn (1.4.0) unstable; urgency=medium
[ Max ]
* Don't return error on normal shutdown
[ Harald Welte ]
* process_pco() const-ify 'apn' argument
* ggsn: Remove magic numbers from pco_contains_proto()
* ggsn: const-ify input / read-only arguments of PCO related functions
* ggsn: Remove magic numbers from ipcp_contains_option()
* ggsn: Fix build_ipcp_pco() in presence of invalid IPCP content
* ggsn.c: Refactor PCO processing during PDP activation
* ggsn: Add minimalistic PAP support
* ggsn: More logging from PCO handling (e.g. in case of malconfiguration)
* sgsnemu: Fix format string argument count
[ Vadim Yanitskiy ]
* osmo-ggsn: fix VTY command for getting PDP contexts by APN
* osmo-ggsn: add VTY command to show PDP context by IPv4
* osmo-ggsn: check result of osmo_apn_to_str()
* osmo-ggsn: print requested / actual APN in PDP info
* osmo-ggsn: properly show subscriber's MSISDN in the VTY
[ Pau Espin Pedrol ]
* ggsn: Drop unused param force in apn_stop()
* gtp: Document spec reasoning drop of Rx DeleteCtxReq
* ggsn: Start gtp retrans timer during startup
* gtp: Take queue_resp into account to schedule retrans timer
* gtp: Fix typo dublicate->duplicate
* pdp: Introduce new API pdp_count_secondary
* gtp_create_pdp_ind: simplify code by reordering and compacting parsing
* gtp: Refactor code to use gtp_freepdp(_teardown) APIs
* cosmetic: gtp: Document free pdp ctx in non-teardown scenario
* gtp: Re-arrange free pdp ctx code in non-teardown scenario
* pdp: Drop unused code for haship
* cosmetic: gtp.h: Remove trailing whitespaces
* ggsn: Fix undefined behaviour shifting beyond sign bit
* gtp: Introduce new pdp APIs (and deprecate old ones) to support multiple GSN
* gtp: Make use of new libgtp APIs with multi-gsn support
* ggsn_vty_reference.xml: Update from last code changes
* ggsn: vty: Require ggsn param in <show pdp-context> cmd
* sgsnemu: Replace use of deprecated libgtp API pdp_newpdp with new one
* cosmetic: gtp: queue: remove trailing whitespace
* gtp: Add missing headers
* gtp: queue.c: Document queue APIs
* gtp: queue: Add unit test queue_test
* ggsn: Avoid unaligned mem access reading PCO proto id
* ggsn: Use structures instead of raw arrays when parsing ipcp_hdr
* configure.ac: Replace obosolete macro AC_CANONICAL_SYSTEM
* configure.ac: Use brackets in AC_INIT params
* configure.ac: Use prefered AC_CONFIG_HEADERS over AM_CONFIG_HEADER
* configure.ac: some versions of linux/if.h require including sys/socket.h
* sgsnemu: Fix unaligned pointer access during ip/icmp checksum
* Remove undefined param passed to {logging,osmo_stats}_vty_add_cmds
* Require libosmocore 1.1.0
[ Oliver Smith ]
* debian: create -doc subpackage with pdf manuals
* ggsn: Use gtp_delete_context_req2() everywhere
* contrib/jenkins.sh: run "make maintainer-clean"
[ Daniel Willmann ]
* manuals: Add script to regenerate vty/counter documentation
-- Pau Espin Pedrol <pespin@sysmocom.de> Wed, 07 Aug 2019 21:28:30 +0200
osmo-ggsn (1.3.0) unstable; urgency=medium
[ Pau Espin Pedrol ]
* ggsn: ctrl iface: listen on IP configured by VTY
* gtp: Log type name of unexpected signalling message
* gtp: Allow recv DEL CTX REQ in sgsn and DEL CTX RSP in ggsn
* gtp: Log ignore CTX DEL REQ due to no teardown and only 1 ctx active
* gtp: Add new API to avoid freeing pdp contexts during DEL CTX REQ
* gtp: Add new replacement cb_recovery2 for cb_recovery
* Install systemd services with autotools
* Install sample cfg file to /etc/osmocom
[ Stefan Sperling ]
* fix unaligned access in build_ipcp_pco()
* fix support for multiple IPCP in PDP protocol configuration options
* check ioctl() call return value in tun_new()
* fix allocation of ippool's hash table
* replace bogus memcpy() call in ippool_newip()
* initialize local variable addr in ippool_new()
* fix format string error in ippool_printaddr()
* fix a format string directives in queue_seqset()
* properly store IPv6 addresses in struct tun_t
[ Harald Welte ]
* debian/rules: Don't overwrite .tarball-version
* osmo-ggsn.cfg: Ensure well-formed config file example
* sgsnemu: Fix printing of tun device name
* ippool.c: Use "%td" format string for ptrdiff_t
* initial version of OsmoGGSN user manual
* OsmoGGSN: Add VTY reference manual
* GGSN: Document how 'ip tuntap' is used for non-root; call netdev 'apn0'
* vty-ref: Update URI of docbook 5.0 schema
[ Alexander Couzens ]
* libgtp: implement gtp_clear_queues to clear req/resp queue
[ Neels Hofmeyr ]
* Importing history from osmo-gsm-manuals.git
* refactor Makefile build rules, don't use the FORCE
* GGSN: don't say 'NITB'
* OsmoGGSN: more info on non-root operation / tun creation
* OsmoGGSN: multiple instances: mention GTP port
* OsmoGGSN: add Routing section for IP forward and masquerading
* OsmoGGSN: typo: priveleges
* OsmoGGSN VTY ref: prep: convert newlines to unix
* OsmoGGSN vty: update VTY reference
* OsmoGGSN: fix VTY additions' node IDs
* OsmoGGSN: update vty reference
* ggsn: update vty reference
[ Max ]
* Expand OsmoGGSN manual
[ Oliver Smith ]
* build manuals moved here from osmo-gsm-manuals.git
* Fix DISTCHECK_CONFIGURE_FLAGS override
* contrib/jenkins.sh: build and publish manuals
* contrib: fix makedistcheck with disabled systemd
-- Harald Welte <laforge@gnumonks.org> Sun, 20 Jan 2019 21:34:22 +0100
osmo-ggsn (1.2.2) unstable; urgency=medium
[ Vadim Yanitskiy ]
* ggsn_vty.c: fix: use CONFIG_NODE as parent by default
[ Philipp Maier ]
* ggsn: fix misinterpreted length field in ipcp_contains_option()
* ggsn: make sure ipcp_option_hdr and and ipcp_hdr are packed
-- Pau Espin Pedrol <pespin@sysmocom.de> Thu, 31 May 2018 12:44:54 +0200
osmo-ggsn (1.2.1) unstable; urgency=medium
* debian/rules: Fix debian packaging after 1.2.0 release
-- Pau Espin Pedrol <pespin@sysmocom.de> Fri, 04 May 2018 12:19:58 +0200
osmo-ggsn (1.2.0) unstable; urgency=medium
[ Neels Hofmeyr ]
* fix compiler warnings: return 0 in main(), in 3 tests
* add --enable-sanitize config option
* sanitize build: ensure uint16/32 alignment in gtpie_test and in46a_test
* configure: add --enable-werror
* jenkins.sh: use --enable-werror configure flag, not CFLAGS
[ Harald Welte ]
* sgsnemu: Don't leak FILE handle in proc_read()
* sgsnemu: Fix format string in printing tun-device name
* sgsnemu: Make sure buffer has space for terminating-NUL
* sgsnemu: Free strings in error path
* gtp: Fix buffer overflow in imsi_gtp2str()
* gtp: Explicit OSMO_ASSERT to ensure pdp variable is set
* tun: Don't copy 16byte IPv6 address to 'struct in_addr'
* ippool: Correctly compute size of static pool
* remove unused argument to alloc_ippool_blacklist()
* factor out netdev_ip_local_get() from tun_ip_local_get()
* Properly NULL-out blacklist in alloc_ippool_blacklist()
* gtp_kernel: Change gtp_kernel_init() function signature
* gtp-kernel: Re-add support for kernel GTP-U acceleration
* gtp-kernel: Get rid of hard-coded kernel GTP device name
* gtp-kernel: shut down kernel GTP device in apn_down()
* gtp-kernel: Align logging for APN start in kernel-gtp case with that of TUN
* gtp-kernel: Avoid global state variable
* gtp-kernel: Make sure repeated calls to gtp_kernel_init() are safe
* gtp-kernel: proper cleanup in error path
* gtp-kernel: Get rid of SYS_ERR where not applicable
* gtp-kernel: Add function name to pdp_debug() function calls
* gtp-kernel: Add device nime in pdp_debug() log statements
* contrib/jenkins.sh: Allow jenkins job to specify if kernel GTP is used
* ggsn.c: Fix byte order of IPCP IPv4 DNS servers
* ggsn: Ignore PCO with length 0, don't abort processing
* README.md: Remove misleading sentence on sgsnemu
* Add talloc context introspection via VTY
* fix segfault in case of kernel gtp-u
* lib/tun.c: Generalize tun_sifflags() to netdev_sifflags
* lib/tun.c: generalize tun_*route() to netdev_*route()
* lib/tun.c: Generalize tun_{set,add}addr*() functions
* lib/tun: split generic network device related stuff to lib/netdev
* lib/netdev.c: Cosmetic changes (coding style / cleanups)
* ggsn: Don't explicitly use tun_setaddr() API anymore
* sgsnemu: Convert from tun_setaddr() to tun_addaddr()
* lib/tun: Remove tun_setaddr() API, as everyone is using tun_addaddr() now
* Move kernel GTP support from ggsn/ to lib/
* ggsn: don't use gtp_kernel_tunnel_{add,del}() for userspace tun
[ Pau Espin Pedrol ]
* ggsn_vty: Stop using deprecated API vty_install_default
* contrib/jenkins.sh: Enable Werror in C(PP)FLAGS
* examples: Add secondary ipv6 google DNS to osmo-ggsn.cfg
* tun_setaddr6: Fix log typo
* cosmetic: Reorder tun_addaddr to get rid of decl of tun_setaddr4
* ggsn.c: Print version of unhandled ip packet
* Remove unused empty src/Makefile.in
* tests: Split ipv6 specific tests into a new test group
* Add support for IPv4v6 End User Addresses
* contrib: jenkins.sh: Build libgtpnl as dep when building with gtp kernel support
* cosmetic: sgsnemu.c: Fix trailing whitespace
* ggsn.c: Improve logging info on link-local ipv6 addr not found
* tun.c: tun_addaddr: Fix segfault and wrong usage of tun_nlattr
* Set tun_addaddr ipv agnostic and add support for ipv6
* ggsn: Add 'ipv6 link-local' vty cmd
* ggsn_vty.c: Print ipv6 link-local cmd when writing config to file
* gtp.c: Fix trailing whitespace
* gtp.c: Determine GTP version from header
* gtp.c: Log unsupported GTP version number
* gtp/pdp: Fix trailing whitespace
* gtp/pdp: Remove unused APIs pdp_ntoeua pdp_euaton
* gtp.c: gtp_gpdu_ind: Convert ifelse to switch statement
* gtp.c: gtp_gpdu_ind: Early return to avoid use of uninitialized var
* gtp/gtp.c: Remove unused function char2ul_t
* gtp/gtp.c: Mark non exported functions as static
* gtp/gtp.c: Use uint8_t for version param in static functions
* ggsn: encaps_tun: Avoid forwarding packet if EUA is unassigned, fix crash
* ggsn: Validate packet src addr from MS
* ggsn: Parse PCO_IPCP
* ggsn: Parse PCO_IPCP for IPv4v6 pdp ctx
* ggsn: Print all addresses on successful pdp ctx creation
* ggsn.c: cb_tun_ind: Convert ifelse to switch statement
* ggsn.c: cb_tun_ind: log dst addr of packet without pdp ctx
* ggsn.c: cb_tun_ind: Don't drop packets targeting pdp ctx ll addr
* sgsnemu: Fix bad ptr during context deallocation
* sgsnemu: listen param is a host, not an interface
* use osmo_init_logging2
[ Max ]
* Log APN and tun names for packets
* Enable sanitize for CI tests
* Fix stow-enabled jenkins build failure
* Add GTP message names
[ Viktor Tsymbalyuk ]
* sgsnemu: sgsnemu stopped after recieving "Request accepted" from ggsn
* sgsnemu: created "pinghost" and "createif" modes for mutual exclusion
* sgsnemu: fix: no outgoing GTP-U in "createif" mode
[ Martin Hauke ]
* build: Remove AC_PROG_CXX, C++ is never used
[ Stefan Sperling ]
* remove the -f option from osmo-ggsn.service
-- Pau Espin Pedrol <pespin@sysmocom.de> Thu, 03 May 2018 16:05:27 +0200
osmo-ggsn (1.1.0) unstable; urgency=medium
* libgtp: pdp.h: Addition of new tx_gpdu_seq struct member member
* libgtp: pdp.h: add LOGPDPX() helper to public API
-- Harald Welte <laforge@gnumonks.org> Sat, 28 Oct 2017 19:00:23 +0200
osmo-ggsn (1.0.0) unstable; urgency=medium
* Transition to OsmoGGSN
-- Harald Welte <laforge@gnumonks.org> Wed, 06 Sep 2017 12:19:48 +0200
openggsn (0.94.0) UNRELEASED; urgency=medium
[ Holger Hans Peter Freyther ]
* Bump version to ease upgrading from Debian SID.
* Bump libgtp SO version after ABI change.
[ Harald Welte ]
* various documentation / README updates
* improve error logging and propagation
* endian-safe definition of IP header
* IPv6 user plane support
-- Harald Welte <laforge@gnumonks.org> Sun, 13 Aug 2017 09:34:20 +0200
openggsn (0.92) precise; urgency=medium
* Release 0.92
-- Holger Hans Peter Freyther <holger@moiji-mobile.com> Mon, 30 Nov 2015 14:05:59 +0100
openggsn (0.91+git34) precise; urgency=medium
* Non-maintainer upload.

106
debian/control vendored
View File

@@ -1,36 +1,102 @@
Source: openggsn
Source: osmo-ggsn
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
Section: net
Priority: optional
Maintainer: Harald Welte <laforge@gnumonks.org>
Build-Depends: debhelper (>= 9), autotools-dev, pkg-config, libdpkg-perl, git, dh-autoreconf, libosmocore-dev (>= 0.8.0)
Build-Depends: debhelper (>= 9),
autotools-dev,
pkg-config,
libdpkg-perl, git,
dh-autoreconf,
libosmocore-dev (>= 1.5.0),
osmo-gsm-manuals-dev,
libgtpnl-dev (>= 1.2.0)
Standards-Version: 3.9.6
Homepage: http://sourceforge.net/projects/ggsn/
Vcs-Git: git://ggsn.git.sourceforge.net/gitroot/ggsn/ggsn
Vcs-Browser: http://ggsn.git.sourceforge.net/git/gitweb.cgi?p=ggsn/ggsn;a=summary
Vcs-Browser: http://git.osmocom.org/osmo-ggsn/
Vcs-Git: git://git.osmocom.org/osmo-ggsn
Homepage: https://projects.osmocom.org/projects/openggsn
Package: openggsn
Package: osmo-ggsn
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Gateway GPRS Support Node
Depends: ${shlibs:Depends},
${misc:Depends}
Description: Osmocom Gateway GPRS Support Node (GGSN)
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: libgtp0
Package: libgtp6
Architecture: any
Multi-Arch: same
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Multi-Arch: same
Depends: ${shlibs:Depends},
${misc:Depends}
Description: library implementing the GTP protocol between SGSN and GGSN
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.
.
This library is part of OsmoGGSN and implements the GTP protocol between
SGSN (Serving GPRS support node) and GGSN.
Package: libgtp0-dev
Depends: ${misc:Depends}, libgtp0 (= ${binary:Version})
Multi-Arch: same
Package: gtp-echo-responder
Architecture: any
Section: libdevel
Description: Development files for libgtp
Depends: ${shlibs:Depends},
${misc:Depends}
Description: Small program answering GTP ECHO Request with GTP ECHO Response
Package: openggsn-dbg
Package: libgtp-dev
Architecture: any
Multi-Arch: same
Section: libdevel
Depends: ${misc:Depends},
libgtp6 (= ${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
mobile network infrastructure.
.
The library libgtp implements the GTP protocol between SGSN and GGSN
and this package contains the development files for this library.
Package: osmo-ggsn-dbg
Section: debug
Architecture: any
Priority: extra
Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp0 (= ${binary:Version}), openggsn (= ${binary:Version})
Depends: ${shlibs:Depends}, ${misc:Depends}, libgtp6 (= ${binary:Version}), osmo-ggsn (= ${binary:Version})
Multi-Arch: same
Description: Debug symbols for OpenGGSN
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})
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.
.
The library libgtp implements the GTP protocol between SGSN and GGSN
and this package contains the development files for this library.
Package: osmo-ggsn-doc
Architecture: all
Section: doc
Priority: optional
Depends: ${misc:Depends}
Description: ${misc:Package} PDF documentation
Various manuals: user manual, VTY reference manual and/or
protocol/interface manuals.

92
debian/copyright vendored
View File

@@ -1,46 +1,62 @@
This work was packaged for Debian by:
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: osmo-ggsn
Source: https://osmocom.org/projects/openggsn
Harald Welte <laforge@gnumonks.org> on Tue, 24 Aug 2010 11:23:40 +0200
Files: *
Copyright: 2002-2004 Mondru AB, Author: Jens Jakobsen <jj@openggsn.org>
2010-2017 Harald Welte <laforge@gnumonks.org>
2012-2016 Holger Hans Peter Freyther <zecke@selfish.org>
2014-2016 Pablo Neira Ayuso <pablo@gnumonks.org>
2014-2016 sysmocom - s.f.m.c. GmbH
License: GPL-2
It was downloaded from:
Files: lib/getopt.c
lib/gnugetopt.h
lib/getopt1.c
Copyright: 1987-2001 Free Software Foundation, Inc.
License: LGPL-2.1+
http://sourceforge.net/projects/ggsn
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
Upstream Author(s):
Files: debian/*
Copyright: 2010-2017 Harald Welte <laforge@gnumonks.org>
2016 Ruben Undheim <ruben.undheim@gmail.com>
License: GPL-2
Jens Jakobsen <jj@openggsn.org>
Harald Welte <laforge@gnumonks.org>
Copyright:
License: GPL-2
This package is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License
.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General Public
License version 2 can be found in "/usr/share/common-licenses/GPL-2".
Copyright (C) 2002 Mondru AB
Copyright (C) 2010 Harald Welte <laforge@gnumonks.org>
License:
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
The Debian packaging is:
Copyright (C) 2010 Harald Welte <laforge@gnumonks.org>
you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
License: LGPL-2.1+
This package is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 of the License, or (at
your option) any later version.
.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU Lesser General Public
License version 2.1 can be found in "/usr/share/common-licenses/LGPL-2.1".

3
debian/docs vendored
View File

@@ -1,2 +1 @@
NEWS
README
README.md

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

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

View File

@@ -1,2 +0,0 @@
examples/ggsn.conf
examples/sgsnemu.conf

View File

@@ -1,3 +0,0 @@
/usr/bin/ggsn
/usr/bin/sgsnemu
/usr/share/man/man8/*

1
debian/osmo-ggsn-doc.install vendored Normal file
View File

@@ -0,0 +1 @@
usr/share/doc/osmo-ggsn-doc/*.pdf

3
debian/osmo-ggsn.examples vendored Normal file
View File

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

View File

@@ -1,6 +1,6 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: openggsn
# Provides: osmo-ggsn
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $remote_fs
# Default-Start: 2 3 4 5
@@ -13,18 +13,18 @@
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="OpenGGSN Gateway GPRS Support Node"
DESC="OsmoGGSN Gateway GPRS Support Node"
NAME=ggsn
DAEMON=/usr/bin/ggsn
DAEMON=/usr/bin/osmo-ggsn
DAEMON_ARGS="" # Arguments to run the daemon with
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/openggsn
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/openggsn ] && . /etc/default/openggsn
[ -r /etc/default/osmo-ggsn ] && . /etc/default/osmo-ggsn
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
@@ -46,13 +46,13 @@ do_start()
|| return 1
# Check for runtime directory of nonvolatile data
if [ ! -d /var/lib/ggsn ]; then
mkdir /var/lib/ggsn
if [ ! -d /var/lib/osmo-ggsn ]; then
mkdir /var/lib/osmo-ggsn
fi
# Check for GTP restart counter
if [ ! -f /var/lib/ggsn/gsn_restart ]; then
echo 0 > /var/lib/ggsn/gsn_restart
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 -- \

5
debian/osmo-ggsn.install vendored Normal file
View File

@@ -0,0 +1,5 @@
/etc/osmocom/osmo-ggsn.cfg
/lib/systemd/system/osmo-ggsn.service
/usr/bin/osmo-ggsn
/usr/bin/sgsnemu
/usr/share/man/man8/*

29
debian/rules vendored
View File

@@ -1,24 +1,29 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
#
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
#
# Modified to make a template file for a multi-binary package with separated
# build-arch and build-indep targets by Bill Allombert 2001
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
DEBIAN := $(shell dpkg-parsechangelog | grep ^Version: | cut -d' ' -f2)
DEBVERS := $(shell echo '$(DEBIAN)' | cut -d- -f1)
VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/[+-].*//' -e 's/~//g')
# This has to be exported to make some magic below work.
#export DH_OPTIONS
export DEB_BUILD_HARDENING=1
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
%:
dh $@ --with autoreconf
override_dh_strip:
dh_strip --dbg-package=openggsn-dbg
dh_strip -posmo-ggsn --dbg-package=osmo-ggsn-dbg
dh_strip -plibgtp6 --dbg-package=libgtp-dbg
override_dh_auto_configure:
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:
dh_compress -X.pdf

View File

@@ -7,7 +7,7 @@
</head>
<body>
<h1>Protocol Compliance List</h1>
OpenGGSN supports both GTP0 (GSM 09.60) and GTP1 (3GPP 29.060). In the
OsmoGGSN supports both GTP0 (GSM 09.60) and GTP1 (3GPP 29.060). In the
following tables the support of each individual message type is
detailed. The numbers before each feature indicates the relevant
section in the standard.<br>

View File

@@ -1,6 +1,8 @@
man_MANS = ggsn.8 sgsnemu.8
man_MANS = osmo-ggsn.8 sgsnemu.8
man_aux = $(man_MANS:.1=.x)
EXTRA_DIST = $(man_MANS)
SUBDIRS = \
examples \
manuals \
$(NULL)

31
doc/examples/Makefile.am Normal file
View File

@@ -0,0 +1,31 @@
OSMOCONF_FILES = \
osmo-ggsn.cfg \
$(NULL)
osmoconfdir = $(sysconfdir)/osmocom
osmoconf_DATA = $(OSMOCONF_FILES)
EXTRA_DIST = $(OSMOCONF_FILES)
CFG_FILES = find $(srcdir) -name '*.cfg' -o -name '*.conf' | sed -e 's,^$(srcdir),,'
dist-hook:
for f in $$($(CFG_FILES)); do \
j="$(distdir)/$$f" && \
mkdir -p "$$(dirname $$j)" && \
$(INSTALL_DATA) $(srcdir)/$$f $$j; \
done
install-data-hook:
for f in $$($(CFG_FILES)); do \
j="$(DESTDIR)$(docdir)/examples/$$f" && \
mkdir -p "$$(dirname $$j)" && \
$(INSTALL_DATA) $(srcdir)/$$f $$j; \
done
uninstall-hook:
@$(PRE_UNINSTALL)
for f in $$($(CFG_FILES)); do \
j="$(DESTDIR)$(docdir)/examples/$$f" && \
$(RM) $$j; \
done

View File

@@ -0,0 +1,51 @@
!
! OpenGGSN (0.94.1-adac) configuration saved from vty
!!
!
log stderr
logging filter all 1
logging color 1
logging print category 0
logging timestamp 0
logging level ip info
logging level tun info
logging level ggsn info
logging level sgsn notice
logging level icmp6 notice
logging level lglobal notice
logging level llapd notice
logging level linp notice
logging level lmux notice
logging level lmi notice
logging level lmib notice
logging level lsms notice
logging level lctrl notice
logging level lgtp info
logging level lstats notice
logging level lgsup notice
logging level loap notice
logging level lss7 notice
logging level lsccp notice
logging level lsua notice
logging level lm3ua notice
logging level lmgcp notice
!
stats interval 5
!
line vty
no login
!
ggsn ggsn0
gtp state-dir /tmp
gtp bind-ip 127.0.0.2
apn internet
gtpu-mode kernel-gtp
tun-device tun4
type-support v4
ip prefix dynamic 172.16.222.0/24
ip dns 0 8.8.8.8
ip dns 1 8.8.4.4
ip ifconfig 172.16.222.0/24
no shutdown
default-apn internet
no shutdown ggsn

View File

@@ -0,0 +1,73 @@
!
! OpenGGSN (0.94.1-adac) configuration saved from vty
!!
!
log stderr
logging filter all 1
logging color 1
logging print category 0
logging timestamp 0
logging level ip info
logging level tun info
logging level ggsn info
logging level sgsn notice
logging level icmp6 notice
logging level lglobal notice
logging level llapd notice
logging level linp notice
logging level lmux notice
logging level lmi notice
logging level lmib notice
logging level lsms notice
logging level lctrl notice
logging level lgtp info
logging level lstats notice
logging level lgsup notice
logging level loap notice
logging level lss7 notice
logging level lsccp notice
logging level lsua notice
logging level lm3ua notice
logging level lmgcp notice
!
stats interval 5
!
line vty
no login
!
ggsn ggsn0
gtp state-dir /tmp
gtp bind-ip 127.0.0.2
apn internet
gtpu-mode tun
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
apn inet6
gtpu-mode tun
tun-device tun6
type-support v6
ipv6 prefix dynamic 2001:780:44:2000:0:0:0:0/56
ipv6 dns 0 2001:4860:4860::8888
ipv6 dns 1 2001:4860:4860::8844
ipv6 ifconfig 2001:780:44:2000:0:0:0:0/56
no shutdown
apn inet46
gtpu-mode tun
tun-device tun46
type-support v4v6
ip prefix dynamic 172.16.46.0/24
ip dns 0 8.8.8.8
ip dns 1 8.8.4.4
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
ipv6 ifconfig 2001:780:44:2100:0:0:0:0/56
no shutdown
default-apn internet
no shutdown ggsn

24
doc/manuals/Makefile.am Normal file
View File

@@ -0,0 +1,24 @@
EXTRA_DIST = osmoggsn-usermanual.adoc \
osmoggsn-usermanual-docinfo.xml \
osmoggsn-vty-reference.xml \
regen_doc.sh \
chapters \
vty
if BUILD_MANUALS
ASCIIDOC = osmoggsn-usermanual.adoc
ASCIIDOC_DEPS = $(srcdir)/chapters/*.adoc
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
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
endif

View File

@@ -0,0 +1,335 @@
== Configuring OsmoGGSN
All configuration of OsmoGGSN is performed using the VTY. For more
general information on the VTY interface, see <<vty>>.
=== Configuring a virtual GGSN instance
OsmoGGSN can run multiple GGSN instances inside one program/process.
Each GGSN instance binds to its own transport-layer GTP IP address and
has its own set of APNs and associated IP address pools + tun/gtp
devices.
In most usage cases, yo will only have a single GGSN instance inside
your configuration file, like in below example:
.Example: Single GGSN configuration section
----
ggsn ggsn0
gtp state-dir /tmp
gtp bind-ip 127.0.0.6
apn internet
gtpu-mode tun
tun-device tun4
type-support v4
ip prefix dynamic 176.16.222.0/24
ip dns 0 192.168.100.1
ip dns 1 8.8.8.8
ip ifconfig 176.16.222.0/24
no shutdown
----
==== Creating/Editing a GGSN instance
Creating/Editing a GGSN instance can be done by the following sequence
of VTY commands:
----
OsmoGGSN> enable <1>
OsmoGGSN# configure terminal <2>
OsmoGGSN(config)# ggsn ggsn0 <3>
OsmoGGSN(config-ggsn)# <4>
----
<1> Change into privileged mode
<2> Enter the interactive configuration mode
<3> Create or edit the GGSN instance `ggsn0`. The name can be any ASCII
string, its significance is only to the local user.
<4> Your prompt is now in the `ggsn` config node, where you can
configure the properties of this GGSN instance.
NOTE:: After creating a new GGSN instance, it is in `shutdown` mode. See
<<unshutdown_apn>> to take it out of shutdown, but make sure to configure it fully
before taking it out of shutdown.
==== Configuring a GGSN instance
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 bind-ip 127.0.0.6 <2>
----
<1> Store the GSN restart state in the specified directory
<2> Bind the GGSN instance to the specified local IPv4 address
There are some further configuration statements that can be used at the
GGSN node, some examples are given below. For a full list, see the
_OsmoGGSN VTY reference manual_ <<vty-ref-osmoggsn>>.
----
OsmoGGSN(config-ggsn)# default-apn foobar <1>
----
<1> Configure a default APN to be used if the user-requested APN is not
found. The named APN must previously be configured
==== Deleting a GGSN instance
A GGSN instance can be removed like this
.Example: Deleting a GGSN instance
----
OsmoGGSN> enable <1>
OsmoGGSN# configure terminal <2>
OsmoGGSN(config)# no ggsn ggsn0 <3>
----
<1> Change into privileged mode
<2> Enter the interactive configuration mode
<3> Delete the GGSN instance
==== Taking a GGSN instance out of shutdown
.Example: Taking a GGSN instance out of shutdown
----
OsmoGGSN> enable <1>
OsmoGGSN# configure terminal <2>
OsmoGGSN(config)# ggsn ggsn0 <3>
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`
<4> Take the GGSN instance out of shutdown
==== Shutting a GGSN instance down
If you would like to take a GGSN instance out of service, you can
put it into shutdown mode. This will make the entire GGSN unavailable
to user traffic and permit you to e.g. reconfigure it before taking it
out of shutdown again.
.Example: Shutting down a GGSN instance
----
OsmoGGSN> enable <1>
OsmoGGSN# configure terminal <2>
OsmoGGSN(config)# ggsn ggsn0 <3>
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`
<4> Shut down the GGSN instance
=== Configuring an Access Point Name
An Access Point Name (APN) represents a connection to an external packet
data network, such as the public Internet or private corporate networsk.
APNs are selected by terminals (MS/UE) when establishing PDP contexts.
Each OsmoGGSN GGSN instance can have any number of APNs configured.
Each APN is identified by a string name.
==== Creating/Editing an APN
.Example: Creating a new APN
----
OsmoGGSN> enable <1>
OsmoGGSN# configure terminal <2>
OsmoGGSN(config)# ggsn ggsn0 <3>
OsmoGGSN(config-ggsn)# apn internet <4>
OsmoGGSN(config-ggsn-apn)# <5>
----
<1> Change into privileged mode
<2> Enter the interactive configuration mode
<3> Enter the config node of the GGSN instance `ggsn0`
<4> Create or Edit an APN called `internet`
<5> Your prompt is now in the `ggsn` config node, where you can
configure the properties of this GGSN instance.
NOTE:: The newly-create APN is created in `shutdown` mode. See <<unshutdown_apn>> to take it
out of shutdown.
==== Configuring an APN
.Example: Configuring an APN
----
OsmoGGSN(config-ggsn-apn)# gtpu-mode tun <1>
OsmoGGSN(config-ggsn-apn)# type-support v4 <2>
OsmoGGSN(config-ggsn-apn)# ip prefix dynamic 176.16.222.0/24 <3>
OsmoGGSN(config-ggsn-apn)# ip dns 0 192.168.100.1 <4>
OsmoGGSN(config-ggsn-apn)# ip dns 1 8.8.8.8 <5>
OsmoGGSN(config-ggsn-apn)# ip ifconfig 176.16.222.0/24 <6>
----
<1> Use the userspace GTP-U handling using a TUN device
<2> Support (only) IPv4 Addresses
<3> Specify the pool of dynamic IPv4 addresses to be allocated to PDP
contexts
<4> Specify the primary DNS server to be provided using IPCP/PCO
<5> Specify the secondary DNS server to be provided using IPCP/PCO
<6> Request OsmoGGSN to configure the `tun4` device network/netmask
NOTE:: If you use the optional `ip ifconfig` command to set the network
device address/mask, OsmoGGSN must run with root or `CAP_NET_ADMIN`
support. It might be better to configure related tun devices at system
startup and run OsmoGGSN as non-privileged user. See <<ggsn_no_root>> for more
details.
==== Deleting an APN
An APN configuration can be removed like this
.Example: Deleting an APN
----
OsmoGGSN> enable <1>
OsmoGGSN# configure terminal <2>
OsmoGGSN(config)# ggsn ggsn0 <3>
OsmoGGSN(config-ggsn)# no apn internet <4>
----
<1> Change into privileged mode
<2> Enter the interactive configuration mode
<3> Enter the config node of the GGSN instance `ggsn0`
<4> Delete the APN `internet`
[[unshutdown_apn]]
==== Taking an APN out of shutdown
In order to bring a deactived APN in `shutdown` state into active
operation, use the `no shutdown` command at the APN node as explained in
the following example:
.Example: Taking an APN out of shutdown
----
OsmoGGSN> enable <1>
OsmoGGSN# configure terminal <2>
OsmoGGSN(config)# ggsn ggsn0 <3>
OsmoGGSN(config-ggsn)# apn internet <4>
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`
<5> Take the APN out of shutdown
==== Shutting an APN down
If you would like to take an APN instance out of service, you can
put it into shutdown mode. This will make the APN unavailable
to user traffic and permit you to e.g. reconfigure it before taking it
out of shutdown again.
.Example: Shutting down an APN
----
OsmoGGSN> enable <1>
OsmoGGSN# configure terminal <2>
OsmoGGSN(config)# ggsn ggsn0 <3>
OsmoGGSN(config-ggsn)# apn internet <4>
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`
<5> Shut down the APN
[[ggsn_no_root]]
=== Configuring for running without root privileges
It's possible to run OsmoGGSN without root privileges if the tun devices are already configured.
The interface creation + configuration must then happen before osmo-ggsn starting up. This can be
achieved by means such as
* a custom shell script run as root before starting osmo-ggsn (e.g. as init script)
* systemd .netdev and .network files, if your system is using systemd-networkd (see `networkctl status`).
==== Manual TUN device creation / configuration
If you chose to go for custom shell/init scripts, you may use the `ip` program which is the standard
tool for network interface configuration on Linux, part of the `iproute2` package. In order to
create a tun device, you must call it like this:
.Example: iproute2 command to create a tun device
----
# ip tuntap add dev apn0 mode tun user username group groupname
----
Where _username_ and _groupname_ correspond to the User and Group that will have ownership over the
device, i.e. the privileges which you intend to run osmo-ggsn under, and _apn0_ will be the
name of the network device created. After creating the interface, you can configure its addresses
using standard means like `ip addr add` or your distribution-specific utilities/tools
to match the `ip prefix dynamic` config item, and activate the link, for example:
----
# ip addr add 192.168.7.1/24 dev apn0
# ip link set apn0 up
----
==== systemd based TUN device creation+configuration
If you want to have systemd take care of creating and configuring a tun device for you,
you can use the below example config files.
.Example: device config via systemd-networkd using apn0.netdev
----
[NetDev]
Name=apn0 <1>
Kind=tun
[Tun]
User=username <2>
Group=username <3>
----
<1> The network interface name of the newly-created device
<2> The username under which you will run OsmoGGSN
<3> The group name under which you will run OsmoGGSN
.Example: network settings via systemd-networkd using ggsn.network
----
[Match]
Name=apn0 <1>
[Network]
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
<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
inbound IP access to your GPRS-attached devices.
==== Config Changes
With the tun device pre-configured in one of the ways outlined above, the main
changes in your osmo-ggsn.cfg file are:
* remove `ip ifconfig` directive,
* make sure that `no shutdown` is present in the `apn` section as well as
`no shutdown ggsn` in the `ggsn` section.
.Example: using externally configured tun device `apn0` as non-root
----
ggsn ggsn0
gtp state-dir /tmp
gtp bind-ip 127.0.0.6
apn internet
gtpu-mode tun
tun-device apn0
type-support v4
ip prefix dynamic 192.168.7.0/24
ip dns 0 192.168.100.1
ip dns 1 8.8.8.8
no shutdown
default-apn internet
no shutdown ggsn
----

View File

@@ -0,0 +1,145 @@
[[chapter_introduction]]
== Overview
[[intro_overview]]
=== About OsmoGGSN
OsmoGGSN is a Free / Open Source Software implementation of the GPRS
GGSN (Gateway GPRS support node) element in side the packet switched
core network of 2G and 3G cellular networks.
The GGSN function is the tunnel endpoint on the core network side,
from where the external (IP) packet data network
=== Software Components
==== GTP Implementation (libgtp)
The OsmoGGSN source code includes a shared library implementation of
the GTP protocol used on the GGSN-SGSN interface. This library
and associated header files are installed system-wide and are
available to other programs/applications.
In fact, libgtp is what the OsmoSGSN also uses for its use of GTP.
==== sgsnemu
In order to test OsmoGGSN without running a SGSN and other elements
of a cellular network, there is a small command-line utility called
*sgsnemu* which is able to simulate the customary operations of a SGSN
towards the GGSN, such as a PDP Context Activation.
*sgsnemu* can even be used for testing against other GGSNs, as the GTP
protocol is standardized across implementations.
==== osmo-ggsn
*osmo-ggsn* is the actual name of the OsmoGGSN executable program. It
implements the GGSN functionality. All parameters are set using the
configuration file, by default located in *./osmo-ggsn.cfg*
==== systemd service file
In *contrib/osmo-ggsn.service* you can find a sample service file for
OsmoGGSN which can be used with systemd.
==== init script
In *contrib/osmo-ggsn.init* you can find a sample init script to be used
on systems with classic init process.
=== Limitations
OsmoGGSN supports both GTP0 (GSM 09.60) and GTP1 (3GPP 29.060). In the
following tables the support of each individual message type is
detailed. The numbers before each feature indicates the relevant
section in the standard.
==== GSM 09.60 (GTPv0)
[options="header",cols="50%,15%,15%,15%,5%"]
|===
| Feature | gtplib | osmo-ggsn | sgsnemu | notes
5+<|*7.4 Path Management Messages*
|7.4.1 Echo Request |Supported |Supported |Supported |
|7.4.2 Echo Response |Supported |Supported |Supported |
|7.4.3 Version Not Supported |Supported |Supported |Supported |
5+<| *7.5 Tunnel Management Messages*
|7.5.1 Create PDP Context Request|Supported |Supported |Supported |
|7.5.2 Create PDP Context Response|Supported |Supported |Supported |
|7.5.3 Update PDP Context Request|Supported |Supported |Not |
|7.5.4 Update PDP Context Response|Supported |Supported |Not |
|7.5.5 Delete PDP Context Request|Supported |Supported |Supported |
|7.5.6 Delete PDP Context Response|Supported |Supported |Supported |
|7.5.7 Create AA PDP Context Request|Unsupported |Unsupported |Unsupported |
|7.5.8 Create AA PDP Response|Unsupported |Unsupported |Unsupported |
|7.5.9 Delete AA PDP Context Request|Unsupported |Unsupported |Unsupported |
|7.5.10 Delete AA PDP Context Response|Unsupported |Unsupported |Unsupported |
|7.5.11 Error Indication |Supported |Supported |Supported |
|7.5.12 PDU Notification Request|Unsupported |Unsupported |Unsupported |
|7.5.13 PDU Notification Response|Unsupported |Unsupported |Unsupported |
|7.5.14 PDU Notification Reject Request|Unsupported |Unsupported |Unsupported |
|7.5.15 PDU Notification Reject Response|Unsupported |Unsupported |Unsupported |
5+<| *7.6 Location Management Messages*
|7.6.1 Send Routeing Information for GPRS Request|Unsupported |Unsupported |Not applicable |
|7.6.2 Send Routeing Information for GPRS Response|Unsupported |Unsupported |Not applicable |
|7.6.3 Failure Report Request|Unsupported |Unsupported |Not applicable |
|7.6.3 Failure Report Response|Unsupported |Unsupported |Not applicable |
|7.6.5 Note MS GPRS Present Request|Unsupported |Unsupported |Not applicable|
|7.6.6 Note MS GPRS Present Response|Unsupported |Unsupported |Not applicable|
5+<| *7.5 Mobility Management Messages*
|7.5.1 Identification Request|Unsupported |Not applicable|Not applicable|
|7.5.2 Identification Response|Unsupported |Not applicable|Not applicable |
|7.5.3 SGSN Context Request|Unsupported |Not applicable|Not applicable|
|7.5.4 SGSN Context Response|Unsupported |Not applicable|Not applicable|
|7.5.5 SGSN Context Acknowledge|Unsupported |Not applicable|Not applicable|
|===
==== 3GPP 29.060 (GTPv1)
[options="header",cols="50%,15%,15%,15%,5%"]
|===
|Feature |gtplib |osmo-ggsn |sgsnemu |notes
5+<|*7.2 Path Management Messages*
|7.2.1 Echo Request |Supported |Supported |Supported |
|7.2.2 Echo Response |Supported |Supported |Supported |
|7.2.3 Version Not Supported|Supported |Supported |Supported |
|7.2.4 Extension Headers Notification|Supported |Supported |Supported |
5+<|*7.3 Tunnel Management Messages*
|7.3.1 Create PDP Context Request|Supported |Supported |Supported |1
|7.3.2 Create PDP Context Response|Supported |Supported |Supported |
|7.3.3 Update PDP Context Request|Supported |Supported |Not applicable|1
|7.3.4 Update PDP Context Response|Supported |Supported |Not applicable|
|7.3.5 Delete PDP Context Request|Supported |Supported |Supported |
|7.3.6 Delete PDP Context Response|Supported |Supported |Supported |
|7.3.7 Error Indication |Supported |Supported |Supported |
|7.3.8 PDU Notification Request|Unsupported |Unsupported |Unsupported |
|7.3.9 PDU Notification Response|Unsupported |Unsupported |Unsupported |
|7.3.10 PDU Notification Reject Request|Unsupported |Unsupported |Unsupported |
|7.3.10 PDU Notification Reject Response|Unsupported |Unsupported |Unsupported |
5+<|*7.4 Location Management Messages*
|7.4.1 Send Routeing Information for GPRS Request|Unsupported |Unsupported |Not applicable |
|7.4.2 Send Routeing Information for GPRS Response|Unsupported |Unsupported |Not applicable |
|7.4.3 Failure Report Request|Unsupported |Unsupported |Not applicable|
|7.4.3 Failure Report Response|Unsupported |Unsupported |Not applicable|
|7.4.5 Note MS GPRS Present Request|Unsupported |Unsupported |Not applicable|
|7.4.6 Note MS GPRS Present Response|Unsupported |Unsupported |Not applicable|
5+<|*7.5 Mobility Management Messages*
|7.5.1 Identification Request|Unsupported |Not applicable|Not applicable|
|7.5.2 Identification Response|Unsupported |Not applicable |Not applicable|
|7.5.3 SGSN Context Request|Unsupported |Not applicable|Not applicable|
|7.5.4 SGSN Context Response|Unsupported |Not applicable |Not applicable|
|7.5.5 SGSN Context Acknowledge|Unsupported |Not applicable|Not applicable|
|7.5.6 Forward Relocation Request|Unsupported |Not applicable|Not applicable|
|7.5.7 Forward Relocation Response|Unsupported |Not applicable|Not applicable|
|7.5.8 Forward Relocation Complete|Unsupported |Not applicable|Not applicable|
|7.5.9 Relocation Cancel Request|Unsupported |Not applicable|Not applicable|
|7.5.10 Relocation Cancel Response|Unsupported |Not applicable|Not applicable|
|7.5.11 Forward Relocation Complete |Unsupported |Not applicable |Not applicable |
|7.5.12 Forward SRNS Context Acknowledge|Unsupported |Not applicable|Not applicable|
|7.5.13 Forward SRNS Context|Unsupported |Not applicable|Not applicable|
|===
Notes
1) The "Secondary PDP Context Activation Procedure" is not supported.

View File

@@ -0,0 +1,126 @@
== Running OsmoGGSN
The OsmoGGSN executable (`osmo-ggsn`) offers the following command-line
arguments:
=== SYNOPSIS
*osmo-ggsn* [-h|-V] [-D] [-c 'CONFIGFILE']
=== OPTIONS
*-h, --help*::
Print a short help message about the supported options
*-V, --version*::
Print the compile-time version number of the program
*-D, --daemonize*::
Fork the process as a daemon into background.
*-c, --config-file 'CONFIGFILE'*::
Specify the file and path name of the configuration file to be
used. If none is specified, use `osmo-ggsn.cfg` in the current
working directory.
=== Routing
Operating the OpenGGSN tun device naturally creates a network setup with
multiple interfaces. Consider:
* Typical Linux setups prevent forwarding of packets between separate
interfaces by default. To let subscribers reach the internet uplink from the
tun device, it may be required to enable IP forwarding.
* Having a locally defined address range assigned to the tun device requires
either sensible routing for this address range, or that masquerading is
enabled to allow your single uplink IP address to "proxy" for the tun.
These are decisions to be made on a network administration level.
In a trivial case where you have a single box serving GPRS to few subscribers
on an arbitrary IP address range not known in the larger network, the easiest
way to enable GPRS uplink would be to enable IP forwarding and masquerading.
To manually enable IPv4 forwarding and masquerading ad-hoc, you can do:
----
sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
iptables -t nat -A POSTROUTING -o '*' -j MASQUERADE
----
(You may want to replace `*` with the network device name, like `-o eth0`)
There are various ways to enable these settings persistently, please refer to
your distribution's documentation -- e.g. look for @net.ipv4.ip_forward=1@ in
@/etc/sysctl.d/@, and https://wiki.debian.org/iptables for masquerading.
=== Multiple instances
Running multiple instances of `osmo-ggsn` is possible if all GGSN instances
are binding to different local IP addresse and all other interfaces (VTY,
OML) are separated using the appropriate configuration options. The IP based
interfaces are binding to local host by default. In order to separate the
processes, the user has to bind those services to specific but different
IP addresses.
The VTY and the control interface can be bound to IP addresses from the loopback
address range.
.Example: Binding VTY and control interface to a specific ip-address
----
line vty
bind 127.0.0.2
ctrl
bind 127.0.0.2
----
Also make sure to place each instance's GTP bind on a separate IP address (GTP
uses a port number that is fixed in the GTP specifications, so it will not be
possible to pick differing ports on the same IP address), like:
----
ggsn ggsn0
gtp bind-ip 127.0.0.2
----
=== GTP-U kernel module
WARNING: As of writing, the kernel module does not support IPv6.
OsmoGGSN has support to use the Linux kernel GTP-U tunnel driver to accelerate
the data/user plane while still implementing the control plane (GTP-C) in
userspace in OsmoGGSN. The kernel module is included in Linux 4.7.0 and higher.
Notably the Debian GNU/Linux distribution has it enabled by default.
In order to use this feature, make sure that your Linux kernel was configured
to support it (`CONFIG_GTP=m` or `=y`). Furthermore, `osmo-ggsn` must have been
built with `./configure` argument `--enable-gtp-linux` (which requires libgtpnl
to be installed).
Load the kernel module with:
----
$ sudo modprobe gtp
----
Then start OsmoGGSN with a configuration file that uses `gtpu-mode kernel-gtp`.
A full example configuration is in `osmo-ggsn-kernel-gtp.cfg`.
----
$ sudo osmo-ggsn -c /usr/share/doc/osmo-ggsn/examples/osmo-ggsn-kernel-gtp.cfg
----
.Example: APN with kernel-gtp
----
ggsn ggsn0
gtp state-dir /tmp
gtp bind-ip 127.0.0.2
apn internet
gtpu-mode kernel-gtp
tun-device tun4
type-support v4
ip prefix dynamic 172.16.222.0/24
ip dns 0 8.8.8.8
ip dns 1 8.8.4.4
ip ifconfig 172.16.222.0/24
no shutdown
----

View File

@@ -0,0 +1,46 @@
<revhistory>
<revision>
<revnumber>1</revnumber>
<date>August 2017</date>
<authorinitials>HW</authorinitials>
<revremark>
Initial version.
</revremark>
</revision>
</revhistory>
<authorgroup>
<author>
<firstname>Harald</firstname>
<surname>Welte</surname>
<email>hwelte@sysmocom.de</email>
<authorinitials>HW</authorinitials>
<affiliation>
<shortaffil>sysmocom</shortaffil>
<orgname>sysmocom - s.f.m.c. GmbH</orgname>
<jobtitle>Managing Director</jobtitle>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2013-2017</year>
<holder>sysmocom - s.f.m.c. GmbH</holder>
</copyright>
<legalnotice>
<para>
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License,
Version 1.3 or any later version published by the Free Software
Foundation; with no Invariant Sections, no Front-Cover Texts,
and no Back-Cover Texts. A copy of the license is included in
the section entitled "GNU Free Documentation License".
</para>
<para>
The Asciidoc source code of this manual can be found at
<ulink url="http://git.osmocom.org/osmo-gsm-manuals/">
http://git.osmocom.org/osmo-gsm-manuals/
</ulink>
</para>
</legalnotice>

View File

@@ -0,0 +1,31 @@
OsmoGGSN User Manual
====================
Harald Welte <hwelte@sysmocom.de>
include::./common/chapters/preface.adoc[]
include::{srcdir}/chapters/overview.adoc[]
include::{srcdir}/chapters/running.adoc[]
//include::{srcdir}/chapters/control.adoc[]
include::./common/chapters/vty.adoc[]
include::./common/chapters/logging.adoc[]
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[]
include::./common/chapters/glossary.adoc[]
include::./common/chapters/gfdl.adoc[]

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
ex:ts=2:sw=42sts=2:et
-*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML 5.0//EN"
"http://docbook.org/xml/5.0/dtd/docbook.dtd" [
<!ENTITY chapter-vty SYSTEM "./common/chapters/vty.xml" >
<!ENTITY sections-vty SYSTEM "generated/docbook_vty.xml" >
]>
<book>
<info>
<revhistory>
<revision>
<revnumber>v1</revnumber>
<date>06th September 2017</date>
<authorinitials>hw</authorinitials>
<revremark>Initial version as of OsmoGGSN v1.0.0</revremark>
</revision>
</revhistory>
<title>OsmoGGSN VTY Reference</title>
<copyright>
<year>2017</year>
</copyright>
<legalnotice>
<para>This work is copyright by <orgname>sysmocom - s.f.m.c. GmbH</orgname>. All rights reserved.
</para>
</legalnotice>
</info>
<!-- Main chapters-->
&chapter-vty;
</book>

17
doc/manuals/regen_doc.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/sh -x
if [ -z "$DOCKER_PLAYGROUND" ]; then
echo "You need to set DOCKER_PLAYGROUND"
exit 1
fi
SCRIPT=$(realpath "$0")
MANUAL_DIR=$(dirname "$SCRIPT")
COMMIT=${COMMIT:-$(git log -1 --format=format:%H)}
cd "$DOCKER_PLAYGROUND/scripts" || exit 1
OSMO_GGSN_BRANCH=$COMMIT ./regen_doc.sh osmo-ggsn 4260 \
"$MANUAL_DIR/chapters/counters_generated.adoc" \
"$MANUAL_DIR/vty/ggsn_vty_reference.xml"

View File

@@ -0,0 +1,30 @@
<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'>
<node id='config-line'>
<child_of nodeid='config' />
<name>Telnet/VTY Configuration Node</name>
<description>
Configure parameters of the Telnet/VTY Interface, such as to which IP address it should bind/listen to.
</description>
</node>
<node id='config-ctrl'>
<child_of nodeid='config' />
<name>CTRL Configuration Node</name>
<description>
Configure parameters of the CTRL Interface, such as to which IP address it should bind/listen to.
</description>
</node>
<node id='config-ggsn'>
<child_of nodeid='config' />
<name>GGSN Instance Configuration Node</name>
<description>
Configure an Instance of a (virtual) GGSN
</description>
</node>
<node id='config-ggsn-apn'>
<child_of nodeid='config-ggsn' />
<name>APN Configuration Node</name>
<description>
Configure an Access Point Name (APN) inside a GGSN Instance
</description>
</node>
</vtydoc>

View File

@@ -1,5 +1,5 @@
.\" * OpenGGSN - Gateway GPRS Support Node
.\" * OsmoGGSN - Gateway GPRS Support Node
.\" * Copyright (C) 2002, 2003 Mondru AB.
.\" *
.\" * The contents of this file may be used under the terms of the GNU
@@ -12,57 +12,37 @@
.\" *
.\" * Contributor(s):
.\" *
.\" Manual page for ggsn
.\" Manual page for osmo-ggsn
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
.\" IP indented paragraph
.\" TP hanging label
.TH ggsn 8 "July 2003"
.TH osmo-ggsn 8 "August 2017"
.SH NAME
ggsn \- Gateway GPRS Support Node.
osmo-ggsn \- Gateway GPRS Support Node.
.SH SYNOPSIS
.B ggsn
.B osmo-ggsn
\-\-help
.B ggsn
.B osmo-ggsn
\-\-version
.B ggsn
.B osmo-ggsn
[
.BI \-\-fg
.BI \-\-help
] [
.BI \-\-debug
.BI \-\-daemonize
] [
.BI \-\-conf " file"
.BI \-\-config-file " file"
] [
.BI \-\-pidfile " file"
] [
.BI \-\-statedir " file"
] [
.BI \-\-listen " host"
] [
.BI \-\-net " net"
] [
.BI \-\-ipup " script"
] [
.BI \-\-ipdown " script"
] [
.BI \-\-dynip " net"
] [
.BI \-\-statip " net"
] [
.BI \-\-pcodns1 " host"
] [
.BI \-\-pcodns2 " host"
] [
.BI \-\-timelimit " seconds"
.BI \-\-version
]
.SH DESCRIPTION
.B ggsn
.B osmo-ggsn
is part of the
.B OpenGGSN
.B OsmoGGSN
project, and implements a Gateway GPRS Support Node. It is used by
mobile operators as the interface between the Internet and the rest of
the mobile network infrastructure.
@@ -82,14 +62,14 @@ over IP.
The other interface can be thought of as the uplink interface, and
interfaces the GGSN to an external data network. Gi is most often an
interface to the Internet.
.B ggsn
.B osmo-ggsn
uses the
.B TUN/TAP driver
for the Gi interface. A tun network interface is established when the
.B ggsn
.B osmo-ggsn
is started.
.B ggsn
.B osmo-ggsn
will accept incoming connections from mobile stations through the
radio access network and the SGSN. When a connection request is
received the ggsn will allocate a dynamic IP address for the mobile
@@ -99,7 +79,7 @@ the SGSN. Runtime errors are reported using the Osmocom logging
framework.
Typically
.B ggsn
.B osmo-ggsn
will be deployed with two Ethernet interfaces. One for the Gn/Gp
interface, and one for the Gi interface. Policy routing and firewall
rules should be used in order to separate Gi traffic from Gn/Gp
@@ -115,104 +95,35 @@ Print help and exit.
Print version and exit.
.TP
.BI --fg
Run in foreground (default = off)
.BI --daemonize
Run in background as a daemon (default = off)
.TP
.BI --debug
Run in debug mode (default = off)
.TP
.BI --conf " file"
.BI --config-file " file"
Read configuration
.I file
(default = /etc/ggsn.conf) where each line corresponds to one command
line option, but with the leading '--' removed. Command line options
override the options given in the configuration file.
.TP
.BI --pidfile " file"
Filename of process id
.I file
(default = /var/run/ggsn.pid)
.TP
.BI --statedir " path"
.I path
to directory of nonvolatile data (default = /var/lib/ggsn/)
.TP
.BI --listen " host"
Local interface IP address to use for the Gn/Gp interface. This option
must be specified. For security issues it is not possible to use
INADDR_ANY.
.TP
.BI --net " net"
Network address of the Gi interface (default = 192.168.0.0/24). The
network address is set during initialisation when
.B ggsn
establishes a tun device for the Gi interface.
.TP
.BI --ipup " script"
Script executed after the Gi tun network interface has been brought
up. Executed with the following parameters: <devicename> <ip address>
.TP
.BI --ipdown " script"
Script executed after the Gi tun network interface has been taken
down. Executed with the following parameters: <devicename> <ip
address>
.TP
.BI --dynip " net"
Dynamic IP address pool. Specifies a pool of dynamic IP addresses. If
this option is omitted the network address specified by the
.BI --net
option is used for dynamic IP address allocation.
.TP
.BI --pcodns1 " host"
PCO DNS Server 1 (default = 0.0.0.0). PCO stands for Protocol
Configuration options, and is part of the GPRS protocols. It is used
to inform the mobile station about the DNS address to use for host
name resolution.
.TP
.BI --pcodns2 " host"
PCO DNS Server 2 (default = 0.0.0.0). PCO stands for Protocol
Configuration options, and is part of the GPRS protocols. It is used
to inform the mobile station about the DNS address to use for host
name resolution.
.TP
.BI --timelimit " seconds"
Exit
.b ggsn
after \fIseconds\fP. Used for debugging.
(default = ./openggsn.cfg)
.SH FILES
.I /etc/ggsn.conf
.I ./osmo-ggsn.cfg
.RS
The configuration file for
.B ggsn.
.B osmo-ggsn.
.RE
.I /var/run/ggsn.pid
.I /var/run/osmo-ggsn.pid
.RS
Process ID file.
.RE
.I /var/lib/ggsn
.I /var/lib/osmo-ggsn
.RS
Directory holding nonvolatile data.
.RE
.SH BUGS
Report all bugs to the OpenGGSN bug tracking list at
.I http://sourceforge.net/projects/ggsn/
Report all bugs to the OsmoGGSN bug tracking list at
.I https://osmocom.org/projects/openggsn
.B ggsn
.B osmo-ggsn
has very limited management support. Currently both SNMP as well as
billing mechanisms are missing.
@@ -224,13 +135,13 @@ billing mechanisms are missing.
.LP
Besides the long options documented in this man page
.B ggsn
.B osmo-ggsn
also accepts a number of short options with the same functionality. Use
.B ggsn --help
.B osmo-ggsn --help
for a full list of all the available options.
The TUN/TAP driver is required for proper operation of
.B ggsn.
.B osmo-ggsn.
For linux kernels later than 2.4.7 the TUN/TAP driver is included in the kernel, but typically needs to be loaded manually with
.B modprobe tun.
For automatic loading the line
@@ -241,7 +152,7 @@ For other platforms see
.I http://vtun.sourceforge.net/tun/
for information on how to install and configure the tun driver.
.B ggsn
.B osmo-ggsn
uses the GPRS Tunneling Protocol (GTP) as specified by the Third
Generation Partnership Project (3GPP). 3GPP protocols specifications
can be found at
@@ -250,6 +161,7 @@ can be found at
.SH COPYRIGHT
Copyright (C) 2002, 2003 by Mondru AB.
Copyright (C) 2017 Harald Welte
The contents of this file may be used under the terms of the GNU
General Public License Version 2, provided that the above copyright
@@ -258,3 +170,4 @@ substantial portions of the software.
.SH AUTHORS
Jens Jakobsen <jj@openggsn.org>
Harald Welte <laforge@gnumonks.org>

View File

@@ -1,5 +1,5 @@
.\" * OpenGGSN - Gateway GPRS Support Node
.\" * OsmoGGSN - Gateway GPRS Support Node
.\" * Copyright (C) 2002, 2003 Mondru AB.
.\" *
.\" * The contents of this file may be used under the terms of the GNU
@@ -90,7 +90,7 @@ sgsnemu \- Serving GPRS Support Node Emulator
.SH DESCRIPTION
.B sgsnemu
is part of the
.B OpenGGSN
.B OsmoGGSN
project, and implements a Serving GPRS Support Node (SGSN)
emulator. It can be used for testing Gateway GPRS Support Nodes
(GGSNs), GPRS core networks as well as GPRS roaming connections.
@@ -329,7 +329,7 @@ indicates infinite.
.TP
.BI --pingquiet
Do not print information for each packet received (default = off). Is
quite usefull for high pingrates.
quite useful for high pingrates.
.SH FILES
@@ -348,8 +348,8 @@ Directory holding nonvolatile data.
.RE
.SH BUGS
Report all bugs to the OpenGGSN bug tracking list at
.I http://sourceforge.net/projects/sgsnemu/
Report all bugs to the OsmoGGSN bug tracking list at
.I http://osmocom.org/projects/openggsn/issues
.SH "SEE ALSO"

View File

@@ -1,92 +0,0 @@
##############################################################################
#
# Sample ggsn configuration file
#
##############################################################################
# TAG: fg
# Include this flag if process is to run in the foreground
#
#fg
# TAG: debug
# Include this flag to include debug information.
#debug
# TAG: conf
# Configuration file to use. This file is the configuration file,
# so changing this parameter in the configuration file does not make
# sense. Use it on the command line instead.
# TAG: pidfile
# File to store information about the process id of the program.
# The program must have write access to this file/directory.
#pidfile /var/run/ggsn.pid
# TAG: statedir
# Directory to use for nonvolatile storage.
# The program must have write access to this directory.
#statedir /var/lib/ggsn/
# TAG: listen
# Specifies the local IP address to listen to
#listen 10.0.0.240
# TAG: net
# IP network address of external packet data network
# Used to set up network interface.
#net 192.168.0.0/24
# TAG: ipup
# Script executed after network interface has been brought up.
# Executed with the following parameters: <devicename> <ip address>
#ipup /etc/ggsn/ip-up
# TAG: ipdown
# Script executed after network interface has been taken down.
# Executed with the following parameters: <devicename> <ip address>
#ipdown /etc/ggsn/ip-down
# TAG: dynip
# Dynamic IP address pool.
# Used for allocation of dynamic IP address when address is not given
# by HLR.
# If this option is not given then the net option is used as a substitute.
#dynip 192.168.0.0/24
# TAG: statip
# Use of this tag is currently UNSUPPORTED
# Static IP address pool.
# Used for allocation of static IP address by means of HLR.
#statip 192.168.1.0/24
# TAG: pcodns1
# Protocol configuration option domain name system server 1.
#pcodns1 0.0.0.0
# TAG: pcodns2
# Protocol configuration option domain name system server 2.
#pcodns2 0.0.0.0
# TAG: timelimit
# Exit after timelimit seconds.
# Setting timelimit to zero will cause the program not to exit.
#timelimit 0
# TAG: apn
# Use of this tag is EXPERIMENTAL
# Access point name to connect to when run in client mode.
#apn internet
# TAG: qos
# Use of this tag is EXPERIMENTAL
# Requested Quality of Service used when run in client mode.
# 3 bytes corresponding to ????
#qos 0x0b921f

View File

@@ -1,10 +1,15 @@
bin_PROGRAMS = ggsn
bin_PROGRAMS = osmo-ggsn
AM_LDFLAGS = @EXEC_LDFLAGS@
AM_CFLAGS = -O2 -D_GNU_SOURCE -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
AM_CFLAGS = -O2 -D_GNU_SOURCE -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS)
ggsn_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS)
ggsn_DEPENDENCIES = ../gtp/libgtp.la ../lib/libmisc.a
ggsn_SOURCES = ggsn.c cmdline.c cmdline.h
osmo_ggsn_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBOSMOVTY_LIBS)
if ENABLE_GTP_KERNEL
AM_CFLAGS += -DGTP_KERNEL $(LIBGTPNL_CFLAGS)
osmo_ggsn_LDADD += $(LIBGTPNL_LIBS)
endif
osmo_ggsn_DEPENDENCIES = ../gtp/libgtp.la ../lib/libmisc.a
osmo_ggsn_SOURCES = ggsn_main.c ggsn_vty.c ggsn.c ggsn.h sgsn.c sgsn.h pco.c pco.h

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +0,0 @@
# OpenGGSN - 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.
#
# Use "gengetopt --conf-parser < cmdline.ggo"
# to generate cmdline.c and cmdline.h
option "fg" f "Run in foreground" flag off
option "debug" d "Run in debug mode" flag off
option "conf" c "Read configuration file" string default="/etc/ggsn.conf" no
option "pidfile" - "Filename of process id file" string default="/var/run/ggsn.pid" no
option "statedir" - "Directory of nonvolatile data" string default="/var/lib/ggsn/" no
option "listen" l "Local interface" string no
option "net" n "Network" string default="192.168.0.0/24" no
option "ipup" - "Script to run after link-up" string no
option "ipdown" - "Script to run after link-down" string no
option "dynip" - "Dynamic IP address pool" string no
option "statip" - "Static IP address pool" string no
option "pcodns1" - "PCO DNS Server 1" string default="0.0.0.0" no
option "pcodns2" - "PCO DNS Server 2" string default="0.0.0.0" no
option "timelimit" - "Exit after timelimit seconds" int default="0" no
option "apn" a "Access point name" string default="internet" no
option "qos" q "Requested quality of service" int default="0x0b921f" no
option "logfile" - "Logfile for errors" string no
option "loglevel" - "Global log ldevel" string default="error" no

View File

@@ -1,272 +0,0 @@
/** @file cmdline.h
* @brief The header file for the command line option parser
* generated by GNU Gengetopt version 2.22.6
* http://www.gnu.org/software/gengetopt.
* DO NOT modify this file, since it can be overwritten
* @author GNU Gengetopt by Lorenzo Bettini */
#ifndef CMDLINE_H
#define CMDLINE_H
/* If we use autoconf. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h> /* for FILE */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef CMDLINE_PARSER_PACKAGE
/** @brief the program name (used for printing errors) */
#define CMDLINE_PARSER_PACKAGE PACKAGE
#endif
#ifndef CMDLINE_PARSER_PACKAGE_NAME
/** @brief the complete program name (used for help and version) */
#ifdef PACKAGE_NAME
#define CMDLINE_PARSER_PACKAGE_NAME PACKAGE_NAME
#else
#define CMDLINE_PARSER_PACKAGE_NAME PACKAGE
#endif
#endif
#ifndef CMDLINE_PARSER_VERSION
/** @brief the program version */
#define CMDLINE_PARSER_VERSION VERSION
#endif
/** @brief Where the command line options are stored */
struct gengetopt_args_info
{
const char *help_help; /**< @brief Print help and exit help description. */
const char *version_help; /**< @brief Print version and exit help description. */
int fg_flag; /**< @brief Run in foreground (default=off). */
const char *fg_help; /**< @brief Run in foreground help description. */
int debug_flag; /**< @brief Run in debug mode (default=off). */
const char *debug_help; /**< @brief Run in debug mode help description. */
char * conf_arg; /**< @brief Read configuration file (default='/etc/ggsn.conf'). */
char * conf_orig; /**< @brief Read configuration file original value given at command line. */
const char *conf_help; /**< @brief Read configuration file help description. */
char * pidfile_arg; /**< @brief Filename of process id file (default='/var/run/ggsn.pid'). */
char * pidfile_orig; /**< @brief Filename of process id file original value given at command line. */
const char *pidfile_help; /**< @brief Filename of process id file help description. */
char * statedir_arg; /**< @brief Directory of nonvolatile data (default='/var/lib/ggsn/'). */
char * statedir_orig; /**< @brief Directory of nonvolatile data original value given at command line. */
const char *statedir_help; /**< @brief Directory of nonvolatile data help description. */
char * listen_arg; /**< @brief Local interface. */
char * listen_orig; /**< @brief Local interface original value given at command line. */
const char *listen_help; /**< @brief Local interface help description. */
char * net_arg; /**< @brief Network (default='192.168.0.0/24'). */
char * net_orig; /**< @brief Network original value given at command line. */
const char *net_help; /**< @brief Network help description. */
char * ipup_arg; /**< @brief Script to run after link-up. */
char * ipup_orig; /**< @brief Script to run after link-up original value given at command line. */
const char *ipup_help; /**< @brief Script to run after link-up help description. */
char * ipdown_arg; /**< @brief Script to run after link-down. */
char * ipdown_orig; /**< @brief Script to run after link-down original value given at command line. */
const char *ipdown_help; /**< @brief Script to run after link-down help description. */
char * dynip_arg; /**< @brief Dynamic IP address pool. */
char * dynip_orig; /**< @brief Dynamic IP address pool original value given at command line. */
const char *dynip_help; /**< @brief Dynamic IP address pool help description. */
char * statip_arg; /**< @brief Static IP address pool. */
char * statip_orig; /**< @brief Static IP address pool original value given at command line. */
const char *statip_help; /**< @brief Static IP address pool help description. */
char * pcodns1_arg; /**< @brief PCO DNS Server 1 (default='0.0.0.0'). */
char * pcodns1_orig; /**< @brief PCO DNS Server 1 original value given at command line. */
const char *pcodns1_help; /**< @brief PCO DNS Server 1 help description. */
char * pcodns2_arg; /**< @brief PCO DNS Server 2 (default='0.0.0.0'). */
char * pcodns2_orig; /**< @brief PCO DNS Server 2 original value given at command line. */
const char *pcodns2_help; /**< @brief PCO DNS Server 2 help description. */
int timelimit_arg; /**< @brief Exit after timelimit seconds (default='0'). */
char * timelimit_orig; /**< @brief Exit after timelimit seconds original value given at command line. */
const char *timelimit_help; /**< @brief Exit after timelimit seconds help description. */
char * apn_arg; /**< @brief Access point name (default='internet'). */
char * apn_orig; /**< @brief Access point name original value given at command line. */
const char *apn_help; /**< @brief Access point name help description. */
int qos_arg; /**< @brief Requested quality of service (default='0x0b921f'). */
char * qos_orig; /**< @brief Requested quality of service original value given at command line. */
const char *qos_help; /**< @brief Requested quality of service help description. */
char * logfile_arg; /**< @brief Logfile for errors. */
char * logfile_orig; /**< @brief Logfile for errors original value given at command line. */
const char *logfile_help; /**< @brief Logfile for errors help description. */
char * loglevel_arg; /**< @brief Global log ldevel (default='error'). */
char * loglevel_orig; /**< @brief Global log ldevel original value given at command line. */
const char *loglevel_help; /**< @brief Global log ldevel help description. */
unsigned int help_given ; /**< @brief Whether help was given. */
unsigned int version_given ; /**< @brief Whether version was given. */
unsigned int fg_given ; /**< @brief Whether fg was given. */
unsigned int debug_given ; /**< @brief Whether debug was given. */
unsigned int conf_given ; /**< @brief Whether conf was given. */
unsigned int pidfile_given ; /**< @brief Whether pidfile was given. */
unsigned int statedir_given ; /**< @brief Whether statedir was given. */
unsigned int listen_given ; /**< @brief Whether listen was given. */
unsigned int net_given ; /**< @brief Whether net was given. */
unsigned int ipup_given ; /**< @brief Whether ipup was given. */
unsigned int ipdown_given ; /**< @brief Whether ipdown was given. */
unsigned int dynip_given ; /**< @brief Whether dynip was given. */
unsigned int statip_given ; /**< @brief Whether statip was given. */
unsigned int pcodns1_given ; /**< @brief Whether pcodns1 was given. */
unsigned int pcodns2_given ; /**< @brief Whether pcodns2 was given. */
unsigned int timelimit_given ; /**< @brief Whether timelimit was given. */
unsigned int apn_given ; /**< @brief Whether apn was given. */
unsigned int qos_given ; /**< @brief Whether qos was given. */
unsigned int logfile_given ; /**< @brief Whether logfile was given. */
unsigned int loglevel_given ; /**< @brief Whether loglevel was given. */
} ;
/** @brief The additional parameters to pass to parser functions */
struct cmdline_parser_params
{
int override; /**< @brief whether to override possibly already present options (default 0) */
int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
int check_required; /**< @brief whether to check that all required options were provided (default 1) */
int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
} ;
/** @brief the purpose string of the program */
extern const char *gengetopt_args_info_purpose;
/** @brief the usage string of the program */
extern const char *gengetopt_args_info_usage;
/** @brief the description string of the program */
extern const char *gengetopt_args_info_description;
/** @brief all the lines making the help output */
extern const char *gengetopt_args_info_help[];
/**
* The command line parser
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser (int argc, char **argv,
struct gengetopt_args_info *args_info);
/**
* The command line parser (version with additional parameters - deprecated)
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @param override whether to override possibly already present options
* @param initialize whether to initialize the option structure my_args_info
* @param check_required whether to check that all required options were provided
* @return 0 if everything went fine, NON 0 if an error took place
* @deprecated use cmdline_parser_ext() instead
*/
int cmdline_parser2 (int argc, char **argv,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
/**
* The command line parser (version with additional parameters)
* @param argc the number of command line options
* @param argv the command line options
* @param args_info the structure where option information will be stored
* @param params additional parameters for the parser
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_ext (int argc, char **argv,
struct gengetopt_args_info *args_info,
struct cmdline_parser_params *params);
/**
* Save the contents of the option struct into an already open FILE stream.
* @param outfile the stream where to dump options
* @param args_info the option struct to dump
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_dump(FILE *outfile,
struct gengetopt_args_info *args_info);
/**
* Save the contents of the option struct into a (text) file.
* This file can be read by the config file parser (if generated by gengetopt)
* @param filename the file where to save
* @param args_info the option struct to save
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_file_save(const char *filename,
struct gengetopt_args_info *args_info);
/**
* Print the help
*/
void cmdline_parser_print_help(void);
/**
* Print the version
*/
void cmdline_parser_print_version(void);
/**
* Initializes all the fields a cmdline_parser_params structure
* to their default values
* @param params the structure to initialize
*/
void cmdline_parser_params_init(struct cmdline_parser_params *params);
/**
* Allocates dynamically a cmdline_parser_params structure and initializes
* all its fields to their default values
* @return the created and initialized cmdline_parser_params structure
*/
struct cmdline_parser_params *cmdline_parser_params_create(void);
/**
* Initializes the passed gengetopt_args_info structure's fields
* (also set default values for options that have a default)
* @param args_info the structure to initialize
*/
void cmdline_parser_init (struct gengetopt_args_info *args_info);
/**
* Deallocates the string fields of the gengetopt_args_info structure
* (but does not deallocate the structure itself)
* @param args_info the structure to deallocate
*/
void cmdline_parser_free (struct gengetopt_args_info *args_info);
/**
* The config file parser (deprecated version)
* @param filename the name of the config file
* @param args_info the structure where option information will be stored
* @param override whether to override possibly already present options
* @param initialize whether to initialize the option structure my_args_info
* @param check_required whether to check that all required options were provided
* @return 0 if everything went fine, NON 0 if an error took place
* @deprecated use cmdline_parser_config_file() instead
*/
int cmdline_parser_configfile (const char *filename,
struct gengetopt_args_info *args_info,
int override, int initialize, int check_required);
/**
* The config file parser
* @param filename the name of the config file
* @param args_info the structure where option information will be stored
* @param params additional parameters for the parser
* @return 0 if everything went fine, NON 0 if an error took place
*/
int cmdline_parser_config_file (const char *filename,
struct gengetopt_args_info *args_info,
struct cmdline_parser_params *params);
/**
* Checks that all the required options were specified
* @param args_info the structure to check
* @param prog_name the name of the program that will be used to print
* possible errors
* @return
*/
int cmdline_parser_required (struct gengetopt_args_info *args_info,
const char *prog_name);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* CMDLINE_H */

File diff suppressed because it is too large Load Diff

169
ggsn/ggsn.h Normal file
View File

@@ -0,0 +1,169 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include <osmocom/ctrl/control_if.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"
#define APN_TYPE_IPv4 0x01 /* v4-only */
#define APN_TYPE_IPv6 0x02 /* v6-only */
#define APN_TYPE_IPv4v6 0x04 /* v4v6 dual-stack */
struct ggsn_ctx;
struct apn_ctx_ip {
struct {
struct in46_prefix ifconfig_prefix;
struct in46_prefix ll_prefix;
struct in46_prefix static_prefix;
struct in46_prefix dynamic_prefix;
/* v4 DNS server names */
struct in46_addr dns[2];
} cfg;
/* v4 address pool */
struct ippool_t *pool;
};
struct apn_name {
struct llist_head list;
char *name;
};
enum apn_gtpu_mode {
APN_GTPU_MODE_TUN = 0, /* default */
APN_GTPU_MODE_KERNEL_GTP,
};
struct apn_ctx {
/* list of APNs inside GGSN */
struct llist_head list;
/* back-pointer to GGSN */
struct ggsn_ctx *ggsn;
bool started;
struct {
/* Primary name */
char *name;
/* Description string */
char *description;
/* List of secondary APN names */
struct llist_head name_list;
/* types supported address types on this APN */
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) */
bool shutdown;
/* transmit G-PDU sequeence numbers (true) or not (false) */
bool tx_gpdu_seq;
} cfg;
/* corresponding tun device */
struct {
struct {
/* name of the network device */
char *dev_name;
/* ip-up and ip-down script names/paths */
char *ipup_script;
char *ipdown_script;
} cfg;
struct tun_t *tun;
struct osmo_fd fd;
} tun;
/* ipv6 link-local address */
struct in6_addr v6_lladdr;
struct apn_ctx_ip v4;
struct apn_ctx_ip v6;
};
struct pdp_priv_t {
struct pdp_t *lib; /* pointer to libgtp associated pdp_t instance */
struct sgsn_peer *sgsn;
struct apn_ctx *apn;
struct llist_head entry; /* to be included into sgsn_peer */
/* struct ggsn_ctx can be reached through lib->gsn->priv, or through sgsn->ggsn */
};
struct ggsn_ctx {
/* global list of GGSNs */
struct llist_head list;
/* list of APNs in this GGSN */
struct llist_head apn_list;
/* list of SGSN peers (struct sgsn_peer) in this GGSN. TODO: hash table with key <ip+port>? */
struct llist_head sgsn_list;
bool started;
struct {
char *name;
/* Description string */
char *description;
/* an APN that shall be used as default for any non-matching APN */
struct apn_ctx *default_apn;
/* ADdress to which we listen for GTP */
struct in46_addr listen_addr;
/* Local GTP-C address advertised in GTP */
struct in46_addr gtpc_addr;
/* Local GTP-U address advertised in GTP */
struct in46_addr gtpu_addr;
/* directory for state file */
char *state_dir;
/* Time between Echo requests on each SGSN */
unsigned int echo_interval;
/* administratively shut-down (true) or not (false) */
bool shutdown;
} cfg;
/* The libgtp (G)GSN instance, i.e. what listens to GTP */
struct gsn_t *gsn;
/* osmo-fd for gsn */
struct osmo_fd gtp_fd0;
struct osmo_fd gtp_fd1c;
struct osmo_fd gtp_fd1u;
};
/* ggsn_vty.c */
extern struct llist_head g_ggsn_list;
extern struct vty_app_info g_vty_info;
extern int ggsn_vty_init(void);
struct ggsn_ctx *ggsn_find(const char *name);
struct ggsn_ctx *ggsn_find_or_create(void *ctx, const char *name);
struct apn_ctx *ggsn_find_apn(struct ggsn_ctx *ggsn, const char *name);
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;
/* ggsn.c */
extern int ggsn_start(struct ggsn_ctx *ggsn);
extern int ggsn_stop(struct ggsn_ctx *ggsn);
extern int apn_start(struct apn_ctx *apn);
extern int apn_stop(struct apn_ctx *apn);
void ggsn_close_one_pdp(struct pdp_t *pdp);
#define LOGPAPN(level, apn, fmt, args...) \
LOGP(DGGSN, level, "APN(%s): " fmt, (apn)->cfg.name, ## args)
#define LOGPGGSN(level, ggsn, fmt, args...) \
LOGP(DGGSN, level, "GGSN(%s): " fmt, (ggsn)->cfg.name, ## args)
#define LOGPPDP(level, pdp, fmt, args...) LOGPDPX(DGGSN, level, pdp, fmt, ## args)

256
ggsn/ggsn_main.c Normal file
View File

@@ -0,0 +1,256 @@
/*
* OsmoGGSN - Gateway GPRS Support Node
* Copyright (C) 2002, 2003, 2004 Mondru AB.
* Copyright (C) 2017-2019 by Harald Welte <laforge@gnumonks.org>
* Copyright (C) 2019 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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.
*
*/
#include "../config.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <getopt.h>
#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <osmocom/core/application.h>
#include <osmocom/core/select.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/utils.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/ctrl/control_vty.h>
#include <osmocom/ctrl/ports.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/stats.h>
#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"
void *tall_ggsn_ctx;
static int end = 0;
static int daemonize = 0;
struct ctrl_handle *g_ctrlh;
struct ul255_t qos;
struct ul255_t apn;
static char *config_file = "osmo-ggsn.cfg";
/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
static void signal_handler(int s)
{
LOGP(DGGSN, LOGL_NOTICE, "signal %d received\n", s);
switch (s) {
case SIGINT:
case SIGTERM:
LOGP(DGGSN, LOGL_NOTICE, "SIGINT received, shutting down\n");
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);
break;
case SIGUSR2:
talloc_report_full(tall_vty_ctx, stderr);
break;
default:
break;
}
}
static void print_usage()
{
printf("Usage: osmo-ggsn [-h] [-D] [-c configfile] [-V]\n");
}
static void print_help()
{
printf( " Some useful help...\n"
" -h --help This help text\n"
" -D --daemonize Fork the process into a background daemon\n"
" -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 }
};
c = getopt_long(argc, argv, "hdc:V", long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
handle_long_options(argv[0], long_option);
break;
case 'h':
print_usage();
print_help();
exit(0);
case 'D':
daemonize = 1;
break;
case 'c':
config_file = optarg;
break;
case 'V':
print_version(1);
exit(0);
break;
}
}
}
int main(int argc, char **argv)
{
struct ggsn_ctx *ggsn;
int rc;
tall_ggsn_ctx = talloc_named_const(NULL, 0, "OsmoGGSN");
msgb_talloc_ctx_init(tall_ggsn_ctx, 0);
g_vty_info.tall_ctx = tall_ggsn_ctx;
/* Handle keyboard interrupt SIGINT */
signal(SIGINT, &signal_handler);
signal(SIGTERM, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
osmo_init_ignore_signals();
osmo_init_logging2(tall_ggsn_ctx, &log_info);
osmo_stats_init(tall_ggsn_ctx);
vty_init(&g_vty_info);
logging_vty_add_cmds();
osmo_talloc_vty_add_cmds();
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);
rate_ctr_init(tall_ggsn_ctx);
rc = vty_read_config_file(config_file, NULL);
if (rc < 0) {
fprintf(stderr, "Failed to open config file: '%s'\n", config_file);
exit(2);
}
rc = telnet_init_dynif(tall_ggsn_ctx, NULL, vty_get_bind_addr(), 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);
if (!g_ctrlh) {
LOGP(DGGSN, LOGL_ERROR, "Failed to create CTRL interface.\n");
exit(1);
}
if (daemonize) {
rc = osmo_daemonize();
if (rc < 0) {
perror("Error during daemonize");
exit(1);
}
}
#if 0
/* qos */
qos.l = 3;
qos.v[2] = (args_info.qos_arg) & 0xff;
qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;
#endif
/* Main select loop */
while (!end) {
osmo_select_main(0);
}
llist_for_each_entry(ggsn, &g_ggsn_list, list)
ggsn_stop(ggsn);
return 0;
}

1198
ggsn/ggsn_vty.c Normal file

File diff suppressed because it is too large Load Diff

252
ggsn/pco.c Normal file
View File

@@ -0,0 +1,252 @@
/*
* PCO parsing related code
* Copyright (C) 2002, 2003, 2004 Mondru AB.
* Copyright (C) 2017-2019 by Harald Welte <laforge@gnumonks.org>
* Copyright (C) 2019 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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.
*
*/
#include <unistd.h>
#include <string.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
#include "../lib/util.h"
#include "pco.h"
#include "ggsn.h"
/* determine if IPCP contains given option */
static const uint8_t *ipcp_contains_option(const struct ipcp_hdr *ipcp, size_t ipcp_len,
enum ipcp_options opt, size_t opt_minlen)
{
const uint8_t *cur_opt = ipcp->options;
/* iterate over Options and check if protocol contained */
while (cur_opt + sizeof(struct ipcp_option_hdr) <= (uint8_t*)ipcp + ipcp_len) {
const struct ipcp_option_hdr *cur_opt_hdr = (const struct ipcp_option_hdr *)cur_opt;
/* length value includes 2 bytes type/length */
if (cur_opt_hdr->len < sizeof(struct ipcp_option_hdr))
return NULL;
if (cur_opt_hdr->type == opt &&
cur_opt_hdr->len >= sizeof(struct ipcp_option_hdr) + opt_minlen)
return cur_opt;
cur_opt += cur_opt_hdr->len;
}
return NULL;
}
static const char *pap_welcome = "Welcome to OsmoGGSN " PACKAGE_VERSION;
/* Handle PAP protocol according to RFC 1334 */
static void process_pco_element_pap(const struct pco_element *pco_in, struct msgb *resp,
const struct apn_ctx *apn, struct pdp_t *pdp)
{
const struct pap_element *pap_in = (const struct pap_element *) pco_in->data;
uint16_t pap_in_len;
uint8_t peer_id_len;
const uint8_t *peer_id;
unsigned int pap_welcome_len;
uint8_t pap_out_size;
struct pap_element *pap_out;
if (pco_in->length < sizeof(struct pap_element))
goto ret_broken;
pap_in_len = osmo_load16be(&pap_in->len);
if (pco_in->length < pap_in_len)
goto ret_broken;
/* "pco_in->length > pap_in_len" is allowed: RFC1334 2.2 states:
"Octets outside the range of the Length field should be treated as
Data Link Layer padding and should be ignored on reception."
*/
switch (pap_in->code) {
case PAP_CODE_AUTH_REQ:
if (pap_in_len < sizeof(struct pap_element) + 1)
goto ret_broken_auth;
peer_id_len = pap_in->data[0];
if (pap_in_len < sizeof(struct pap_element) + 1 + peer_id_len)
goto ret_broken_auth;
peer_id = &pap_in->data[1];
LOGPPDP(LOGL_DEBUG, pdp, "PCO PAP PeerId = %s, ACKing\n",
osmo_quote_str((const char *)peer_id, peer_id_len));
/* Password-Length + Password following here, but we don't care */
/* Prepare response, we ACK all of them: */
pap_welcome_len = strlen(pap_welcome);
/* +1: Length field of pap_welcome Message */
pap_out_size = sizeof(struct pap_element) + 1 + pap_welcome_len;
pap_out = alloca(pap_out_size);
pap_out->code = PAP_CODE_AUTH_ACK;
pap_out->id = pap_in->id;
pap_out->len = htons(pap_out_size);
pap_out->data[0] = pap_welcome_len;
memcpy(pap_out->data+1, pap_welcome, pap_welcome_len);
msgb_t16lv_put(resp, PCO_P_PAP, pap_out_size, (uint8_t *) pap_out);
break;
case PAP_CODE_AUTH_ACK:
case PAP_CODE_AUTH_NAK:
default:
LOGPPDP(LOGL_NOTICE, pdp, "Unsupported PAP PCO Code %u, ignoring\n", pap_in->code);
break;
}
return;
ret_broken_auth:
LOGPPDP(LOGL_NOTICE, pdp, "Invalid PAP AuthenticateReq: %s, ignoring\n",
osmo_hexdump_nospc((const uint8_t *)pco_in, pco_in->length));
return;
ret_broken:
LOGPPDP(LOGL_NOTICE, pdp, "Invalid PAP PCO Length: %s, ignoring\n",
osmo_hexdump_nospc((const uint8_t *)pco_in, pco_in->length));
}
static void process_pco_element_ipcp(const struct pco_element *pco_elem, struct msgb *resp,
const struct apn_ctx *apn, struct pdp_t *pdp)
{
struct ippoolm_t *peer_v4 = pdp_get_peer_ipv(pdp, false);
const struct in46_addr *dns1 = &apn->v4.cfg.dns[0];
const struct in46_addr *dns2 = &apn->v4.cfg.dns[1];
uint8_t *start = resp->tail;
const struct ipcp_hdr *ipcp;
uint16_t ipcp_len;
uint8_t *len1, *len2;
unsigned int len_appended;
ptrdiff_t consumed;
size_t remain;
if (!peer_v4) {
LOGPPDP(LOGL_ERROR, pdp, "IPCP but no IPv4 type ?!?\n");
return;
}
ipcp = (const struct ipcp_hdr *)pco_elem->data;
consumed = (pco_elem->data - &pdp->pco_req.v[0]);
remain = sizeof(pdp->pco_req.v) - consumed;
ipcp_len = osmo_load16be(&ipcp->len);
if (remain < 0 || remain < ipcp_len) {
LOGPPDP(LOGL_ERROR, pdp, "Malformed IPCP, ignoring\n");
return;
}
/* Three byte T16L header */
msgb_put_u16(resp, 0x8021); /* IPCP */
len1 = msgb_put(resp, 1); /* Length of contents: delay */
msgb_put_u8(resp, 0x02); /* ACK */
msgb_put_u8(resp, ipcp->id); /* ID: Needs to match request */
msgb_put_u8(resp, 0x00); /* Length MSB */
len2 = msgb_put(resp, 1); /* Length LSB: delay */
if (dns1->len == 4 && ipcp_contains_option(ipcp, ipcp_len, IPCP_OPT_PRIMARY_DNS, 4)) {
msgb_put_u8(resp, 0x81); /* DNS1 Tag */
msgb_put_u8(resp, 2 + dns1->len); /* DNS1 Length, incl. TL */
msgb_put_u32(resp, ntohl(dns1->v4.s_addr));
}
if (dns2->len == 4 && ipcp_contains_option(ipcp, ipcp_len, IPCP_OPT_SECONDARY_DNS, 4)) {
msgb_put_u8(resp, 0x83); /* DNS2 Tag */
msgb_put_u8(resp, 2 + dns2->len); /* DNS2 Length, incl. TL */
msgb_put_u32(resp, ntohl(dns2->v4.s_addr));
}
/* patch in length values */
len_appended = resp->tail - start;
*len1 = len_appended - 3;
*len2 = len_appended - 3;
}
static void process_pco_element_dns_ipv6(const struct pco_element *pco_elem, struct msgb *resp,
const struct apn_ctx *apn, struct pdp_t *pdp)
{
unsigned int i;
const uint8_t *tail = resp->tail;
for (i = 0; i < ARRAY_SIZE(apn->v6.cfg.dns); i++) {
const struct in46_addr *i46a = &apn->v6.cfg.dns[i];
if (i46a->len != 16)
continue;
msgb_t16lv_put(resp, PCO_P_DNS_IPv6_ADDR, i46a->len, i46a->v6.s6_addr);
}
if (resp->tail == tail)
LOGPPDP(LOGL_NOTICE, pdp, "MS requested IPv6 DNS, but APN has none configured\n");
}
static void process_pco_element_dns_ipv4(const struct pco_element *pco_elem, struct msgb *resp,
const struct apn_ctx *apn, struct pdp_t *pdp)
{
unsigned int i;
const uint8_t *tail = resp->tail;
for (i = 0; i < ARRAY_SIZE(apn->v4.cfg.dns); i++) {
const struct in46_addr *i46a = &apn->v4.cfg.dns[i];
if (i46a->len != 4)
continue;
msgb_t16lv_put(resp, PCO_P_DNS_IPv4_ADDR, i46a->len, (uint8_t *)&i46a->v4);
}
if (resp->tail == tail)
LOGPPDP(LOGL_NOTICE, pdp, "MS requested IPv4 DNS, but APN has none configured\n");
}
static void process_pco_element(const struct pco_element *pco_elem, struct msgb *resp,
const struct apn_ctx *apn, struct pdp_t *pdp)
{
uint16_t protocol_id = osmo_load16be(&pco_elem->protocol_id);
LOGPPDP(LOGL_DEBUG, pdp, "PCO Protocol 0x%04x\n", protocol_id);
switch (protocol_id) {
case PCO_P_PAP:
process_pco_element_pap(pco_elem, resp, apn, pdp);
break;
case PCO_P_IPCP:
process_pco_element_ipcp(pco_elem, resp, apn, pdp);
break;
case PCO_P_DNS_IPv6_ADDR:
process_pco_element_dns_ipv6(pco_elem, resp, apn, pdp);
break;
case PCO_P_DNS_IPv4_ADDR:
process_pco_element_dns_ipv4(pco_elem, resp, apn, pdp);
break;
default:
LOGPPDP(LOGL_INFO, pdp, "Unknown/Unimplemented PCO Protocol 0x%04x: %s\n",
protocol_id, osmo_hexdump_nospc(pco_elem->data, pco_elem->length));
break;
}
}
/* process one PCO request from a MS/UE, putting together the proper responses */
void process_pco(const struct apn_ctx *apn, struct pdp_t *pdp)
{
struct msgb *resp = msgb_alloc(256, "PCO.resp");
const struct ul255_t *pco = &pdp->pco_req;
const struct pco_element *pco_elem;
const uint8_t *cur;
/* build the header of the PCO response */
OSMO_ASSERT(resp);
msgb_put_u8(resp, 0x80); /* ext-bit + configuration protocol byte */
/* iterate over the PCO elements in the request; call process_pco_element() for each */
for (cur = pco->v + 1, pco_elem = (const struct pco_element *) cur;
cur + sizeof(struct pco_element) <= pco->v + pco->l;
cur += pco_elem->length + sizeof(*pco_elem), pco_elem = (const struct pco_element *) cur) {
process_pco_element(pco_elem, resp, apn, pdp);
}
/* copy the PCO response msgb and copy its contents over to the PDP context */
if (msgb_length(resp) > 1) {
memcpy(pdp->pco_neg.v, msgb_data(resp), msgb_length(resp));
pdp->pco_neg.l = msgb_length(resp);
} else
pdp->pco_neg.l = 0;
msgb_free(resp);
}

81
ggsn/pco.h Normal file
View File

@@ -0,0 +1,81 @@
#pragma once
#include <stdint.h>
#include "../gtp/pdp.h"
/* 3GPP TS 24.008 10.6.5.3 */
enum pco_protocols {
PCO_P_LCP = 0xC021,
PCO_P_PAP = 0xC023,
PCO_P_CHAP = 0xC223,
PCO_P_IPCP = 0x8021,
PCO_P_PCSCF_ADDR = 0x0001,
PCO_P_IM_CN_SS_F = 0x0002,
PCO_P_DNS_IPv6_ADDR = 0x0003,
PCO_P_POLICY_CTRL_REJ = 0x0004, /* only in Network->MS */
PCO_P_MS_SUP_NETREQ_BCI = 0x0005,
/* reserved */
PCO_P_DSMIPv6_HA_ADDR = 0x0007,
PCO_P_DSMIPv6_HN_PREF = 0x0008,
PCO_P_DSMIPv6_v4_HA_ADDR= 0x0009,
PCO_P_IP_ADDR_VIA_NAS = 0x000a, /* only MS->Network */
PCO_P_IPv4_ADDR_VIA_DHCP= 0x000b, /* only MS->Netowrk */
PCO_P_PCSCF_IPv4_ADDR = 0x000c,
PCO_P_DNS_IPv4_ADDR = 0x000d,
PCO_P_MSISDN = 0x000e,
PCO_P_IFOM_SUPPORT = 0x000f,
PCO_P_IPv4_LINK_MTU = 0x0010,
PCO_P_MS_SUPP_LOC_A_TFT = 0x0011,
PCO_P_PCSCF_RESEL_SUP = 0x0012, /* only MS->Network */
PCO_P_NBIFOM_REQ = 0x0013,
PCO_P_NBIFOM_MODE = 0x0014,
PCO_P_NONIP_LINK_MTU = 0x0015,
PCO_P_APN_RATE_CTRL_SUP = 0x0016,
PCO_P_PS_DATA_OFF_UE = 0x0017,
PCO_P_REL_DATA_SVC = 0x0018,
};
struct pco_element {
uint16_t protocol_id; /* network byte order */
uint8_t length; /* length of data below */
uint8_t data[0];
} __attribute__((packed));
/* RFC 1332 */
enum ipcp_options {
IPCP_OPT_IPADDR = 3,
IPCP_OPT_PRIMARY_DNS = 129,
IPCP_OPT_SECONDARY_DNS = 131,
};
struct ipcp_option_hdr {
uint8_t type;
uint8_t len;
uint8_t data[0];
} __attribute__ ((packed));
struct ipcp_hdr {
uint8_t code;
uint8_t id;
uint16_t len;
uint8_t options[0];
} __attribute__ ((packed));
/* RFC 1334, section 3.2. Packet Format */
struct pap_element {
uint8_t code;
uint8_t id;
uint16_t len; /* length including header */
uint8_t data[0];
} __attribute__((packed));
enum pap_code {
PAP_CODE_AUTH_REQ = 1,
PAP_CODE_AUTH_ACK = 2,
PAP_CODE_AUTH_NAK = 3,
};
struct apn_ctx;
void process_pco(const struct apn_ctx *apn, struct pdp_t *pdp);

168
ggsn/sgsn.c Normal file
View File

@@ -0,0 +1,168 @@
#include "sgsn.h"
#include "ggsn.h"
static bool sgsn_peer_attempt_free(struct sgsn_peer *sgsn)
{
/* We have to be careful here, since if all pdp ctx for that sgsn were
deactivated in-between we sent the Echo Req and receivied the timeout
indication, the sgsn (cbp) may be already gone. We need to add some
counter reference of echo requets in flight and only free sgsn
structures when it goes to zero decreased for all Echo Resp. We do it
this way because currently in libgtp there's no understanding of "gsn
peer" for which messages are grouped and hence we cannot request
libgtp to drop all queued messages for a specific peer. */
if (sgsn->tx_msgs_queued) {
LOGSGSN(LOGL_INFO, sgsn, "Delaying delete, still %u echo messages queued\n",
sgsn->tx_msgs_queued);
return false;
}
llist_del(&sgsn->entry);
LOGSGSN(LOGL_INFO, sgsn, "Deleting SGSN\n");
talloc_free(sgsn);
return true;
}
static void sgsn_peer_echo_req(struct sgsn_peer *sgsn)
{
struct ggsn_ctx *ggsn = sgsn->ggsn;
LOGSGSN(LOGL_INFO, sgsn, "Tx Echo Request\n");
gtp_echo_req(ggsn->gsn, sgsn->gtp_version, sgsn, &sgsn->addr);
sgsn->tx_msgs_queued++;
}
void sgsn_peer_echo_resp(struct sgsn_peer *sgsn, bool timeout)
{
if (timeout) {
LOGSGSN(LOGL_NOTICE, sgsn, "Rx Echo Request timed out!\n");
sgsn_peer_drop_all_pdp(sgsn);
} else {
LOGSGSN(LOGL_INFO, sgsn, "Rx Echo Response\n");
}
/* We decrement it here after dropping all pdps to make sure sgsn was
not freed upon last pdp ctx deleted and is still alive now */
sgsn->tx_msgs_queued--;
if (llist_empty(&sgsn->pdp_list))
sgsn_peer_attempt_free(sgsn);
}
void sgsn_echo_timer_start(struct sgsn_peer *sgsn)
{
if (sgsn->ggsn->cfg.echo_interval == 0)
return;
sgsn_peer_echo_req(sgsn);
osmo_timer_schedule(&sgsn->echo_timer, sgsn->ggsn->cfg.echo_interval, 0);
}
void sgsn_echo_timer_stop(struct sgsn_peer *sgsn)
{
osmo_timer_del(&sgsn->echo_timer);
}
static void sgsn_echo_timer_cb(void *data)
{
struct sgsn_peer *sgsn = (struct sgsn_peer *) data;
sgsn_echo_timer_start(sgsn);
}
struct sgsn_peer *sgsn_peer_allocate(struct ggsn_ctx *ggsn, struct in_addr *ia, unsigned int gtp_version)
{
struct sgsn_peer *sgsn;
sgsn = talloc_zero_size(ggsn, sizeof(struct sgsn_peer));
sgsn->ggsn = ggsn;
sgsn->addr = *ia;
sgsn->gtp_version = gtp_version;
sgsn->remote_restart_ctr = -1;
INIT_LLIST_HEAD(&sgsn->pdp_list);
INIT_LLIST_HEAD(&sgsn->entry);
osmo_timer_setup(&sgsn->echo_timer, sgsn_echo_timer_cb, sgsn);
LOGSGSN(LOGL_INFO, sgsn, "Discovered\n");
return sgsn;
}
void sgsn_peer_add_pdp_priv(struct sgsn_peer *sgsn, struct pdp_priv_t *pdp_priv)
{
bool was_empty = llist_empty(&sgsn->pdp_list);
pdp_priv->sgsn = sgsn;
llist_add(&pdp_priv->entry, &sgsn->pdp_list);
if (was_empty)
sgsn_echo_timer_start(sgsn);
}
void sgsn_peer_remove_pdp_priv(struct pdp_priv_t* pdp_priv)
{
struct sgsn_peer *sgsn = pdp_priv->sgsn;
llist_del(&pdp_priv->entry);
if (sgsn && llist_empty(&sgsn->pdp_list)) {
/* No PDP contexts associated to this SGSN, no need to keep it */
sgsn_echo_timer_stop(sgsn);
/* sgsn may not be freed if there are some messages still queued
in libgtp which could return a pointer to it */
sgsn_peer_attempt_free(sgsn);
}
pdp_priv->sgsn = NULL;
}
/* High-level function to be called in case a GGSN has disappeared or
* otherwise lost state (recovery procedure). It will detach all related pdp ctx
* from a ggsn and communicate deact to MS. Optionally (!NULL), one pdp ctx can
* be kept alive to allow handling later message which contained the Recovery IE. */
static unsigned int sgsn_peer_drop_all_pdp_except(struct sgsn_peer *sgsn, struct pdp_priv_t *except)
{
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));
struct pdp_priv_t *pdp, *pdp2;
llist_for_each_entry_safe(pdp, pdp2, &sgsn->pdp_list, entry) {
if (pdp == except)
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;
}
}
LOGP(DGGSN, LOGL_INFO, "SGSN(%s) Dropped %u PDP contexts\n", buf, num);
return num;
}
unsigned int sgsn_peer_drop_all_pdp(struct sgsn_peer *sgsn)
{
return sgsn_peer_drop_all_pdp_except(sgsn, NULL);
}
int sgsn_peer_handle_recovery(struct sgsn_peer *sgsn, struct pdp_t *pdp, uint8_t recovery)
{
struct pdp_priv_t *pdp_priv = NULL;
if (sgsn->remote_restart_ctr == -1) {
/* First received ECHO RESPONSE, note the restart ctr */
sgsn->remote_restart_ctr = recovery;
} else if (sgsn->remote_restart_ctr != recovery) {
/* counter has changed (SGSN restart): release all PDP */
LOGSGSN(LOGL_NOTICE, sgsn, "SGSN recovery (%u->%u) pdp=%p, "
"releasing all%s PDP contexts\n",
sgsn->remote_restart_ctr, recovery, pdp, pdp ? " other" : "");
sgsn->remote_restart_ctr = recovery;
if (pdp)
pdp_priv = pdp->priv;
sgsn_peer_drop_all_pdp_except(sgsn, pdp_priv);
}
return 0;
}

46
ggsn/sgsn.h Normal file
View File

@@ -0,0 +1,46 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
#include "../gtp/pdp.h"
struct ggsn_ctx;
struct pdp_priv_t;
struct sgsn_peer {
struct llist_head entry; /* to be included into ggsn_ctx */
struct ggsn_ctx *ggsn; /* backpointer to ggsn_ctx */
struct in_addr addr; /* Addr of the sgsn peer */
unsigned int gtp_version; /* GTP version */
int remote_restart_ctr; /* Last received Restart Ctr from sgsn peer, -1 == unknown */
/* list of pdp contexts associated with this sgsn */
struct llist_head pdp_list;
/* Sends echo request towards SGSN on expiration. Echo Resp is received
through cb_recovery2(), and echo Req timeout through
cb_conf(GTP_ECHO_REQ, EOF, NULL, cbp); */
struct osmo_timer_list echo_timer;
/* Number of GTP messages in libgtp transmit queue */
unsigned int tx_msgs_queued;
};
struct sgsn_peer *sgsn_peer_allocate(struct ggsn_ctx *ggsn, struct in_addr *ia, unsigned int gtp_version);
void sgsn_peer_add_pdp_priv(struct sgsn_peer *sgsn, struct pdp_priv_t *pdp_priv);
void sgsn_peer_remove_pdp_priv(struct pdp_priv_t *pdp_priv);
void sgsn_echo_timer_start(struct sgsn_peer *sgsn);
void sgsn_echo_timer_stop(struct sgsn_peer *sgsn);
void sgsn_peer_echo_resp(struct sgsn_peer *sgsn, bool timeout);
unsigned int sgsn_peer_drop_all_pdp(struct sgsn_peer *sgsn);
int sgsn_peer_handle_recovery(struct sgsn_peer *sgsn, struct pdp_t *pdp, uint8_t recovery);
#define LOGSGSN(level, sgsn, fmt, args...) { \
char _buf[INET_ADDRSTRLEN]; \
LOGP(DGGSN, level, "SGSN(%s): " fmt, inet_ntop(AF_INET, &sgsn->addr, _buf, sizeof(_buf)), ## args); \
} while (0)

151
git-version-gen Executable file
View File

@@ -0,0 +1,151 @@
#!/bin/sh
# Print a version string.
scriptversion=2010-01-28.01
# Copyright (C) 2007-2010 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
# It may be run two ways:
# - from a git repository in which the "git describe" command below
# produces useful output (thus requiring at least one signed tag)
# - from a non-git-repo directory containing a .tarball-version file, which
# presumes this script is invoked like "./git-version-gen .tarball-version".
# In order to use intra-version strings in your project, you will need two
# separate generated version string files:
#
# .tarball-version - present only in a distribution tarball, and not in
# a checked-out repository. Created with contents that were learned at
# the last time autoconf was run, and used by git-version-gen. Must not
# be present in either $(srcdir) or $(builddir) for git-version-gen to
# give accurate answers during normal development with a checked out tree,
# but must be present in a tarball when there is no version control system.
# Therefore, it cannot be used in any dependencies. GNUmakefile has
# hooks to force a reconfigure at distribution time to get the value
# correct, without penalizing normal development with extra reconfigures.
#
# .version - present in a checked-out repository and in a distribution
# tarball. Usable in dependencies, particularly for files that don't
# want to depend on config.h but do want to track version changes.
# Delete this file prior to any autoconf run where you want to rebuild
# files to pick up a version string change; and leave it stale to
# minimize rebuild time after unrelated changes to configure sources.
#
# It is probably wise to add these two files to .gitignore, so that you
# don't accidentally commit either generated file.
#
# Use the following line in your configure.ac, so that $(VERSION) will
# automatically be up-to-date each time configure is run (and note that
# since configure.ac no longer includes a version string, Makefile rules
# should not depend on configure.ac for version updates).
#
# AC_INIT([GNU project],
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
# [bug-project@example])
#
# Then use the following lines in your Makefile.am, so that .version
# will be present for dependencies, and so that .tarball-version will
# exist in distribution tarballs.
#
# BUILT_SOURCES = $(top_srcdir)/.version
# $(top_srcdir)/.version:
# echo $(VERSION) > $@-t && mv $@-t $@
# dist-hook:
# echo $(VERSION) > $(distdir)/.tarball-version
case $# in
1) ;;
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
esac
tarball_version_file=$1
nl='
'
# First see if there is a tarball-only version file.
# then try "git describe", then default.
if test -f $tarball_version_file
then
v=`cat $tarball_version_file` || exit 1
case $v in
*$nl*) v= ;; # reject multi-line output
[0-9]*) ;;
*) v= ;;
esac
test -z "$v" \
&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
fi
if test -n "$v"
then
: # use $v
elif
v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
|| git describe --abbrev=4 HEAD 2>/dev/null` \
&& case $v in
[0-9]*) ;;
v[0-9]*) ;;
*) (exit 1) ;;
esac
then
# Is this a new git that lists number of commits since the last
# tag or the previous older version that did not?
# Newer: v6.10-77-g0f8faeb
# Older: v6.10-g0f8faeb
case $v in
*-*-*) : git describe is okay three part flavor ;;
*-*)
: git describe is older two part flavor
# Recreate the number of commits and rewrite such that the
# result is the same as if we were using the newer version
# of git describe.
vtag=`echo "$v" | sed 's/-.*//'`
numcommits=`git rev-list "$vtag"..HEAD | wc -l`
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
;;
esac
# Change the first '-' to a '.', so version-comparing tools work properly.
# Remove the "g" in git describe's output string, to save a byte.
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
else
v=UNKNOWN
fi
v=`echo "$v" |sed 's/^v//'`
# Don't declare a version "dirty" merely because a time stamp has changed.
git status > /dev/null 2>&1
dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
case "$dirty" in
'') ;;
*) # Append the suffix only if there isn't one already.
case $v in
*-dirty) ;;
*) v="$v-dirty" ;;
esac ;;
esac
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
echo "$v" | tr -d '\012'
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

View File

@@ -1,12 +1,15 @@
# This is _NOT_ the library release version, it's an API version.
# Please read chapter "Library interface versions" of the libtool documentation
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
# If major=current-age is increased, remember to update the dh_strip line in debian/rules!
LIBVERSION=8:0:2
lib_LTLIBRARIES = libgtp.la
include_HEADERS = gtp.h pdp.h
include_HEADERS = gtp.h pdp.h gtpie.h
AM_CFLAGS = -O2 -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
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)

1823
gtp/gtp.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,24 @@
/*
* OpenGGSN - Gateway GPRS Support Node
/*
* 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 _GTP_H
#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
@@ -79,12 +86,17 @@
#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 */
/* 242-254 For future use. */
#define GTP_GPDU 255 /* G-PDU */
extern const struct value_string gtp_type_names[];
static inline const char *gtp_type_name(uint8_t val)
{ return get_value_string(gtp_type_names, val); }
/* GTP information element cause codes from 29.060 v3.9.0 7.7 */
/* */
#define GTPCAUSE_REQ_IMSI 0 /* Request IMSI */
@@ -133,8 +145,9 @@
struct ul66_t;
struct ul16_t;
struct pdp_t;
/* GTP 0 header.
/* GTP 0 header.
* Explanation to some of the fields:
* SNDCP NPDU Number flag = 0 except for inter SGSN handover situations
* SNDCP N-PDU LCC Number 0 = 0xff except for inter SGSN handover situations
@@ -161,6 +174,13 @@ struct gtp0_header { /* Descriptions from 3GPP 09.60 */
uint64_t tid; /* 13 Tunnel ID */
} __attribute__((packed)); /* 20 */
#define GTP1HDR_F_NPDU 0x01
#define GTP1HDR_F_SEQ 0x02
#define GTP1HDR_F_EXT 0x04
#define GTP1HDR_F_GTP1 0x10
#define GTPHDR_F_VER(n) ((n) << 5)
#define GTPHDR_F_GET_VER(flags) ((flags)>>5)
struct gtp1_header_short { /* Descriptions from 3GPP 29060 */
uint8_t flags; /* 01 bitfield, with typical values */
/* 001..... Version: 1 */
@@ -216,13 +236,13 @@ union gtp_packet {
* Information storage for each gsn instance
*
* Normally each instance of the application corresponds to
* one instance of a gsn.
*
* 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.
*************************************************************/
@@ -244,18 +264,26 @@ struct gsn_t {
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 */
@@ -291,8 +319,9 @@ extern int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
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);
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);
@@ -309,11 +338,19 @@ extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, struct in_addr *inetaddr);
extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, int teardown);
void *cbp, int teardown)
OSMO_DEPRECATED("Use gtp_delete_context_req2() instead, to avoid freeing pdp ctx before reply");
extern int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, int teardown);
extern int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *pack, unsigned len);
extern int gtp_ran_info_relay_req(struct gsn_t *gsn, const struct sockaddr_in *peer,
const uint8_t *ran_container, size_t ran_container_len,
const uint8_t *rim_route_addr, size_t rim_route_addr_len,
uint8_t rim_route_addr_discr);
extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
int (*cb_data_ind) (struct pdp_t * pdp,
void *pack, unsigned len));
@@ -322,8 +359,8 @@ 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);
extern int gtp_retranstimeout(struct gsn_t *gsn, struct timeval *timeout);
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 *
@@ -337,14 +374,29 @@ extern int gtp_set_cb_unsup_ind(struct gsn_t *gsn,
extern int gtp_set_cb_extheader_ind(struct gsn_t *gsn,
int (*cb) (struct sockaddr_in * peer));
extern int gtp_set_cb_ran_info_relay_ind(struct gsn_t *gsn,
int (*cb) (struct sockaddr_in * peer, union gtpie_member **ie));
extern int gtp_set_cb_conf(struct gsn_t *gsn,
int (*cb) (int type, int cause, struct pdp_t * pdp,
void *cbp));
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,
@@ -399,5 +451,7 @@ extern int ipv42eua(struct ul66_t *eua, struct in_addr *src);
extern int eua2ipv4(struct in_addr *dst, struct ul66_t *eua);
extern int gsna2in_addr(struct in_addr *dst, struct ul16_t *gsna);
extern int in_addr2gsna(struct ul16_t *gsna, struct in_addr *src);
extern const char *imsi_gtp2str(const uint64_t *imsi);
extern uint64_t gtp_imsi_str2gtp(const char *str);
#endif /* !_GTP_H */

View File

@@ -1,17 +1,17 @@
/*
* OpenGGSN - Gateway GPRS Support Node
/*
* 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
@@ -39,8 +39,16 @@
#include "gtpie.h"
/*! Encode a TLV type Information Element.
* \param[inout] p Pointer to output packet to which IE is appended
* \param[inout] length Up to which byte length is \a p used/filled
* \param[in] size Total size of \a p in bytes
* \param[in] t Tag / Information Element Identifier
* \param[in] l Length of value \a v in bytes
* \param[in] v Pointer to input value
* \returns 0 on success, 1 on error */
int gtpie_tlv(void *p, unsigned int *length, unsigned int size, uint8_t t,
int l, void *v)
int l, const void *v)
{
if ((*length + 3 + l) >= size)
return 1;
@@ -51,8 +59,16 @@ int gtpie_tlv(void *p, unsigned int *length, unsigned int size, uint8_t t,
return 0;
}
/*! Encode a TV0 (Tag + value) type Information Element.
* \param[inout] p Pointer to output packet to which IE is appended
* \param[inout] length Up to which byte length is \a p used/filled
* \param[in] size Total size of \a p in bytes
* \param[in] t Tag / Information Element Identifier
* \param[in] l Length of value \a v in bytes
* \param[in] v Pointer to input value
* \returns 0 on success, 1 on error */
int gtpie_tv0(void *p, unsigned int *length, unsigned int size, uint8_t t,
int l, uint8_t * v)
int l, const uint8_t * v)
{
if ((*length + 1 + l) >= size)
return 1;
@@ -62,6 +78,13 @@ int gtpie_tv0(void *p, unsigned int *length, unsigned int size, uint8_t t,
return 0;
}
/*! Encode a TV1 (Tag + 8bit value) type Information Element.
* \param[inout] p Pointer to output packet to which IE is appended
* \param[inout] length Up to which byte length is \a p used/filled
* \param[in] size Total size of \a p in bytes
* \param[in] t Tag / Information Element Identifier
* \param[in] v Input value
* \returns 0 on success, 1 on error */
int gtpie_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t,
uint8_t v)
{
@@ -73,6 +96,13 @@ int gtpie_tv1(void *p, unsigned int *length, unsigned int size, uint8_t t,
return 0;
}
/*! Encode a TV2 (Tag + 16bit value) type Information Element.
* \param[inout] p Pointer to output packet to which IE is appended
* \param[inout] length Up to which byte length is \a p used/filled
* \param[in] size Total size of \a p in bytes
* \param[in] t Tag / Information Element Identifier
* \param[in] v Input value
* \returns 0 on success, 1 on error */
int gtpie_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t,
uint16_t v)
{
@@ -84,6 +114,13 @@ int gtpie_tv2(void *p, unsigned int *length, unsigned int size, uint8_t t,
return 0;
}
/*! Encode a TV4 (Tag + 32bit value) type Information Element.
* \param[inout] p Pointer to output packet to which IE is appended
* \param[inout] length Up to which byte length is \a p used/filled
* \param[in] size Total size of \a p in bytes
* \param[in] t Tag / Information Element Identifier
* \param[in] v Input value
* \returns 0 on success, 1 on error */
int gtpie_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t,
uint32_t v)
{
@@ -95,6 +132,13 @@ int gtpie_tv4(void *p, unsigned int *length, unsigned int size, uint8_t t,
return 0;
}
/*! Encode a TV8 (Tag + 64bit value) type Information Element.
* \param[inout] p Pointer to output packet to which IE is appended
* \param[inout] length Up to which byte length is \a p used/filled
* \param[in] size Total size of \a p in bytes
* \param[in] t Tag / Information Element Identifier
* \param[in] v Input value
* \returns 0 on success, 1 on error */
int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t,
uint64_t v)
{
@@ -106,6 +150,11 @@ int gtpie_tv8(void *p, unsigned int *length, unsigned int size, uint8_t t,
return 0;
}
/*! Obtain a GTP IE for a given tag/IEI from a list/array.
* \param[in] ie Array of GTPIE
* \param[in] type Tag/IEI for which we're looking
* \param[in] instance Instance (number of occurence) of this IEI
* \returns index into \a ie on success; -1 if not found */
int gtpie_getie(union gtpie_member *ie[], int type, int instance)
{
int j;
@@ -118,6 +167,11 @@ int gtpie_getie(union gtpie_member *ie[], int type, int instance)
return -1;
}
/*! Determine if IE for a given tag/IEI exists in a list/array.
* \param[in] ie Array of GTPIE
* \param[in] type Tag/IEI for which we're looking
* \param[in] instance Instance (number of occurence) of this IEI
* \returns 1 if IEI instance present in \a ie; 0 if not */
int gtpie_exist(union gtpie_member *ie[], int type, int instance)
{
int j;
@@ -130,6 +184,14 @@ int gtpie_exist(union gtpie_member *ie[], int type, int instance)
return 0;
}
/*! Obtain Value of TLV-type IE for a given tag/IEI from a list/array.
* \param[in] ie Array of GTPIE
* \param[in] type Tag/IEI for which we're looking
* \param[in] instance Instance (number of occurence) of this IEI
* \param[out] length Length of IE
* \param[inout] dst Caller-allocated buffer where to store value
* \param[in] size Size of \a dst in bytes
* \returns 0 on sucess; EOF in case value is larger than \a size */
int gtpie_gettlv(union gtpie_member *ie[], int type, int instance,
unsigned int *length, void *dst, unsigned int size)
{
@@ -145,6 +207,13 @@ int gtpie_gettlv(union gtpie_member *ie[], int type, int instance,
return 0;
}
/*! Obtain Value of TV0-type IE for a given tag/IEI from a list/array.
* \param[in] ie Array of GTPIE
* \param[in] type Tag/IEI for which we're looking
* \param[in] instance Instance (number of occurence) of this IEI
* \param[inout] dst Caller-allocated buffer where to store value
* \param[in] size Size of value in bytes
* \returns 0 on sucess; EOF in case IE not found */
int gtpie_gettv0(union gtpie_member *ie[], int type, int instance,
void *dst, unsigned int size)
{
@@ -157,6 +226,12 @@ int gtpie_gettv0(union gtpie_member *ie[], int type, int instance,
return 0;
}
/*! Obtain Value of TV1-type IE for a given tag/IEI from a list/array.
* \param[in] ie Array of GTPIE
* \param[in] type Tag/IEI for which we're looking
* \param[in] instance Instance (number of occurence) of this IEI
* \param[inout] dst Caller-allocated buffer where to store value
* \returns 0 on sucess; EOF in case IE not found */
int gtpie_gettv1(union gtpie_member *ie[], int type, int instance,
uint8_t * dst)
{
@@ -169,6 +244,12 @@ int gtpie_gettv1(union gtpie_member *ie[], int type, int instance,
return 0;
}
/*! Obtain Value of TV2-type IE for a given tag/IEI from a list/array.
* \param[in] ie Array of GTPIE
* \param[in] type Tag/IEI for which we're looking
* \param[in] instance Instance (number of occurence) of this IEI
* \param[inout] dst Caller-allocated buffer where to store value
* \returns 0 on sucess; EOF in case IE not found */
int gtpie_gettv2(union gtpie_member *ie[], int type, int instance,
uint16_t * dst)
{
@@ -181,6 +262,12 @@ int gtpie_gettv2(union gtpie_member *ie[], int type, int instance,
return 0;
}
/*! Obtain Value of TV4-type IE for a given tag/IEI from a list/array.
* \param[in] ie Array of GTPIE
* \param[in] type Tag/IEI for which we're looking
* \param[in] instance Instance (number of occurence) of this IEI
* \param[inout] dst Caller-allocated buffer where to store value
* \returns 0 on sucess; EOF in case IE not found */
int gtpie_gettv4(union gtpie_member *ie[], int type, int instance,
uint32_t * dst)
{
@@ -193,6 +280,12 @@ int gtpie_gettv4(union gtpie_member *ie[], int type, int instance,
return 0;
}
/*! Obtain Value of TV8-type IE for a given tag/IEI from a list/array.
* \param[in] ie Array of GTPIE
* \param[in] type Tag/IEI for which we're looking
* \param[in] instance Instance (number of occurence) of this IEI
* \param[inout] dst Caller-allocated buffer where to store value
* \returns 0 on sucess; EOF in case IE not found */
int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
uint64_t * dst)
{
@@ -205,13 +298,19 @@ int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
return 0;
}
int gtpie_decaps(union gtpie_member *ie[], int version, void *pack,
/*! Parse an incoming GTP packet into its Information Elements.
* \param[out] ie Caller-allocated Array of GTPIE
* \param[in] version GTP protocol version
* \param[in] pack Pointer to raw GTP packet (payload part)
* \param[in] len Length of \a pack in bytes
* \returns 0 on sucess; EOF in case IE not found */
int gtpie_decaps(union gtpie_member *ie[], int version, const void *pack,
unsigned len)
{
int i;
int j = 0;
unsigned char *p;
unsigned char *end;
const unsigned char *p;
const unsigned char *end;
end = (unsigned char *)pack + len;
p = pack;
@@ -243,6 +342,7 @@ int gtpie_decaps(union gtpie_member *ie[], int version, void *pack,
case GTPIE_RP_SMS:
case GTPIE_RP:
case GTPIE_MS_NOT_REACH:
case GTPIE_BCM:
if (j < GTPIE_SIZE) {
ie[j] = (union gtpie_member *)p;
if (GTPIE_DEBUG)
@@ -390,11 +490,76 @@ int gtpie_decaps(union gtpie_member *ie[], int version, void *pack,
case GTPIE_RAB_SETUP:
case GTPIE_TRIGGER_ID:
case GTPIE_OMC_ID:
case GTPIE_CHARGING_ADDR:
case GTPIE_RAN_T_CONTAIN:
case GTPIE_PDP_CTX_PRIO:
case GTPIE_ADDL_RAB_S_I:
case GTPIE_SGSN_NUMBER:
case GTPIE_COMMON_FLAGS:
case GTPIE_APN_RESTR:
case GTPIE_R_PRIO_LCS:
case GTPIE_RAT_TYPE:
case GTPIE_USER_LOC:
case GTPIE_MS_TZ:
case GTPIE_IMEI_SV:
case GTPIE_CML_CHG_I_CT:
case GTPIE_MBMS_UE_CTX:
case GTPIE_TMGI:
case GTPIE_RIM_ROUT_ADDR:
case GTPIE_MBMS_PCO:
case GTPIE_MBMS_SA:
case GTPIE_SRNC_PDCP_CTX:
case GTPIE_ADDL_TRACE:
case GTPIE_HOP_CTR:
case GTPIE_SEL_PLMN_ID:
case GTPIE_MBMS_SESS_ID:
case GTPIE_MBMS_2_3G_IND:
case GTPIE_ENH_NSAPI:
case GTPIE_MBMS_SESS_DUR:
case GTPIE_A_MBMS_TRAC_I:
case GTPIE_MBMS_S_REP_N:
case GTPIE_MBMS_TTDT:
case GTPIE_PS_HO_REQ_CTX:
case GTPIE_BSS_CONTAINER:
case GTPIE_CELL_ID:
case GTPIE_PDU_NUMBERS:
case GTPIE_BSSGP_CAUSE:
case GTPIE_RQD_MBMS_BCAP:
case GTPIE_RIM_RA_DISCR:
case GTPIE_L_SETUP_PFCS:
case GTPIE_PS_HO_XID_PAR:
case GTPIE_MS_CHG_REP_A:
case GTPIE_DIR_TUN_FLAGS:
case GTPIE_CORREL_ID:
case GTPIE_MBMS_FLOWI:
case GTPIE_MBMS_MC_DIST:
case GTPIE_MBMS_DIST_ACK:
case GTPIE_R_IRAT_HO_INF:
case GTPIE_RFSP_IDX:
case GTPIE_FQDN:
case GTPIE_E_ALL_PRIO_1:
case GTPIE_E_ALL_PRIO_2:
case GTPIE_E_CMN_FLAGS:
case GTPIE_U_CSG_INFO:
case GTPIE_CSG_I_REP_ACT:
case GTPIE_CSG_ID:
case GTPIE_CSG_MEMB_IND:
case GTPIE_AMBR:
case GTPIE_UE_NET_CAPA:
case GTPIE_UE_AMBR:
case GTPIE_APN_AMBR_NS:
case GTPIE_GGSN_BACKOFF:
case GTPIE_S_PRIO_IND:
case GTPIE_S_PRIO_IND_NS:
case GTPIE_H_BR_16MBPS_F:
case GTPIE_A_MMCTX_SRVCC:
case GTPIE_A_FLAGS_SRVCC:
case GTPIE_STN_SR:
case GTPIE_C_MSISDN:
case GTPIE_E_RANAP_CAUSE:
case GTPIE_ENODEB_ID:
case GTPIE_SEL_MODE_NS:
case GTPIE_ULI_TIMESTAMP:
case GTPIE_CHARGING_ADDR:
case GTPIE_PRIVATE:
if (j < GTPIE_SIZE) {
ie[j] = (union gtpie_member *)p;
@@ -429,12 +594,16 @@ int gtpie_decaps(union gtpie_member *ie[], int version, void *pack,
}
}
/*! Encode GTP packet payload from Array of Information Elements.
* \param[out] ie Input Array of GTPIE
* \param[out] pack Pointer to caller-allocated buffer for raw GTP packet (GTPIE_MAX length)
* \param[out] len Encoded length of \a pack in bytes
* \returns 0 on sucess; 2 for out-of-space */
int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
{
int i;
unsigned char *p;
unsigned char *end;
union gtpie_member *m;
int iesize;
p = pack;
@@ -445,7 +614,6 @@ int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
if (ie[i] != 0) {
if (GTPIE_DEBUG)
printf("gtpie_encaps. Type %d\n", i);
m = (union gtpie_member *)p;
switch (i) {
case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
case GTPIE_REORDER:
@@ -459,6 +627,7 @@ int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
case GTPIE_RP_SMS:
case GTPIE_RP:
case GTPIE_MS_NOT_REACH:
case GTPIE_BCM:
iesize = 2;
break;
case GTPIE_FL_DI: /* TV GTPIE types with value length 2 */
@@ -483,11 +652,13 @@ int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
iesize = 6;
break;
case GTPIE_RAI: /* TV GTPIE types with value length 6 */
iesize = 7;
break;
case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
iesize = 8;
break;
case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
case GTPIE_RAI:
iesize = 9;
break;
case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
@@ -511,6 +682,75 @@ int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
case GTPIE_RAB_SETUP:
case GTPIE_TRIGGER_ID:
case GTPIE_OMC_ID:
case GTPIE_RAN_T_CONTAIN:
case GTPIE_PDP_CTX_PRIO:
case GTPIE_ADDL_RAB_S_I:
case GTPIE_SGSN_NUMBER:
case GTPIE_COMMON_FLAGS:
case GTPIE_APN_RESTR:
case GTPIE_R_PRIO_LCS:
case GTPIE_RAT_TYPE:
case GTPIE_USER_LOC:
case GTPIE_MS_TZ:
case GTPIE_IMEI_SV:
case GTPIE_CML_CHG_I_CT:
case GTPIE_MBMS_UE_CTX:
case GTPIE_TMGI:
case GTPIE_RIM_ROUT_ADDR:
case GTPIE_MBMS_PCO:
case GTPIE_MBMS_SA:
case GTPIE_SRNC_PDCP_CTX:
case GTPIE_ADDL_TRACE:
case GTPIE_HOP_CTR:
case GTPIE_SEL_PLMN_ID:
case GTPIE_MBMS_SESS_ID:
case GTPIE_MBMS_2_3G_IND:
case GTPIE_ENH_NSAPI:
case GTPIE_MBMS_SESS_DUR:
case GTPIE_A_MBMS_TRAC_I:
case GTPIE_MBMS_S_REP_N:
case GTPIE_MBMS_TTDT:
case GTPIE_PS_HO_REQ_CTX:
case GTPIE_BSS_CONTAINER:
case GTPIE_CELL_ID:
case GTPIE_PDU_NUMBERS:
case GTPIE_BSSGP_CAUSE:
case GTPIE_RQD_MBMS_BCAP:
case GTPIE_RIM_RA_DISCR:
case GTPIE_L_SETUP_PFCS:
case GTPIE_PS_HO_XID_PAR:
case GTPIE_MS_CHG_REP_A:
case GTPIE_DIR_TUN_FLAGS:
case GTPIE_CORREL_ID:
case GTPIE_MBMS_FLOWI:
case GTPIE_MBMS_MC_DIST:
case GTPIE_MBMS_DIST_ACK:
case GTPIE_R_IRAT_HO_INF:
case GTPIE_RFSP_IDX:
case GTPIE_FQDN:
case GTPIE_E_ALL_PRIO_1:
case GTPIE_E_ALL_PRIO_2:
case GTPIE_E_CMN_FLAGS:
case GTPIE_U_CSG_INFO:
case GTPIE_CSG_I_REP_ACT:
case GTPIE_CSG_ID:
case GTPIE_CSG_MEMB_IND:
case GTPIE_AMBR:
case GTPIE_UE_NET_CAPA:
case GTPIE_UE_AMBR:
case GTPIE_APN_AMBR_NS:
case GTPIE_GGSN_BACKOFF:
case GTPIE_S_PRIO_IND:
case GTPIE_S_PRIO_IND_NS:
case GTPIE_H_BR_16MBPS_F:
case GTPIE_A_MMCTX_SRVCC:
case GTPIE_A_FLAGS_SRVCC:
case GTPIE_STN_SR:
case GTPIE_C_MSISDN:
case GTPIE_E_RANAP_CAUSE:
case GTPIE_ENODEB_ID:
case GTPIE_SEL_MODE_NS:
case GTPIE_ULI_TIMESTAMP:
case GTPIE_CHARGING_ADDR:
case GTPIE_PRIVATE:
iesize = 3 + hton16(ie[i]->tlv.l);
@@ -528,13 +768,18 @@ int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len)
return 0;
}
/*! Encode GTP packet payload from Array of Information Elements.
* \param[out] ie Input Array of GTPIE
* \param[in] size Size of ?
* \param[out] pack Pointer to caller-allocated buffer for raw GTP packet (GTPIE_MAX length)
* \param[out] len Encoded length of \a pack in bytes
* \returns 0 on sucess; 2 for out-of-space */
int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
void *pack, unsigned *len)
{
unsigned int i, j;
unsigned char *p;
unsigned char *end;
union gtpie_member *m;
int iesize;
p = pack;
@@ -548,7 +793,6 @@ int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
printf
("gtpie_encaps. Number %d, Type %d\n",
i, ie[i].t);
m = (union gtpie_member *)p;
switch (ie[i].t) {
case GTPIE_CAUSE: /* TV GTPIE types with value length 1 */
case GTPIE_REORDER:
@@ -562,6 +806,7 @@ int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
case GTPIE_RP_SMS:
case GTPIE_RP:
case GTPIE_MS_NOT_REACH:
case GTPIE_BCM:
iesize = 2;
break;
case GTPIE_PFI: /* TV GTPIE types with value length 2 */
@@ -578,16 +823,19 @@ int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
case GTPIE_P_TMSI:
case GTPIE_TEI_DI:
case GTPIE_TEI_C:
case GTPIE_CHARGING_ID:
iesize = 5;
break;
case GTPIE_TEI_DII: /* TV GTPIE types with value length 5 */
iesize = 6;
break;
case GTPIE_RAI: /* TV GTPIE types with value length 6 */
iesize = 7;
break;
case GTPIE_RAB_CONTEXT: /* TV GTPIE types with value length 7 */
iesize = 8;
break;
case GTPIE_IMSI: /* TV GTPIE types with value length 8 */
case GTPIE_RAI:
iesize = 9;
break;
case GTPIE_AUTH_TRIPLET: /* TV GTPIE types with value length 28 */
@@ -596,8 +844,7 @@ int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
case GTPIE_EXT_HEADER_T: /* GTP extension header */
iesize = 2 + hton8(ie[i].ext.l);
break;
case GTPIE_CHARGING_ID: /* TLV GTPIE types with length length 2 */
case GTPIE_EUA:
case GTPIE_EUA: /* TLV GTPIE types with length length 2 */
case GTPIE_MM_CONTEXT:
case GTPIE_PDP_CONTEXT:
case GTPIE_APN:
@@ -612,6 +859,75 @@ int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
case GTPIE_RAB_SETUP:
case GTPIE_TRIGGER_ID:
case GTPIE_OMC_ID:
case GTPIE_RAN_T_CONTAIN:
case GTPIE_PDP_CTX_PRIO:
case GTPIE_ADDL_RAB_S_I:
case GTPIE_SGSN_NUMBER:
case GTPIE_COMMON_FLAGS:
case GTPIE_APN_RESTR:
case GTPIE_R_PRIO_LCS:
case GTPIE_RAT_TYPE:
case GTPIE_USER_LOC:
case GTPIE_MS_TZ:
case GTPIE_IMEI_SV:
case GTPIE_CML_CHG_I_CT:
case GTPIE_MBMS_UE_CTX:
case GTPIE_TMGI:
case GTPIE_RIM_ROUT_ADDR:
case GTPIE_MBMS_PCO:
case GTPIE_MBMS_SA:
case GTPIE_SRNC_PDCP_CTX:
case GTPIE_ADDL_TRACE:
case GTPIE_HOP_CTR:
case GTPIE_SEL_PLMN_ID:
case GTPIE_MBMS_SESS_ID:
case GTPIE_MBMS_2_3G_IND:
case GTPIE_ENH_NSAPI:
case GTPIE_MBMS_SESS_DUR:
case GTPIE_A_MBMS_TRAC_I:
case GTPIE_MBMS_S_REP_N:
case GTPIE_MBMS_TTDT:
case GTPIE_PS_HO_REQ_CTX:
case GTPIE_BSS_CONTAINER:
case GTPIE_CELL_ID:
case GTPIE_PDU_NUMBERS:
case GTPIE_BSSGP_CAUSE:
case GTPIE_RQD_MBMS_BCAP:
case GTPIE_RIM_RA_DISCR:
case GTPIE_L_SETUP_PFCS:
case GTPIE_PS_HO_XID_PAR:
case GTPIE_MS_CHG_REP_A:
case GTPIE_DIR_TUN_FLAGS:
case GTPIE_CORREL_ID:
case GTPIE_MBMS_FLOWI:
case GTPIE_MBMS_MC_DIST:
case GTPIE_MBMS_DIST_ACK:
case GTPIE_R_IRAT_HO_INF:
case GTPIE_RFSP_IDX:
case GTPIE_FQDN:
case GTPIE_E_ALL_PRIO_1:
case GTPIE_E_ALL_PRIO_2:
case GTPIE_E_CMN_FLAGS:
case GTPIE_U_CSG_INFO:
case GTPIE_CSG_I_REP_ACT:
case GTPIE_CSG_ID:
case GTPIE_CSG_MEMB_IND:
case GTPIE_AMBR:
case GTPIE_UE_NET_CAPA:
case GTPIE_UE_AMBR:
case GTPIE_APN_AMBR_NS:
case GTPIE_GGSN_BACKOFF:
case GTPIE_S_PRIO_IND:
case GTPIE_S_PRIO_IND_NS:
case GTPIE_H_BR_16MBPS_F:
case GTPIE_A_MMCTX_SRVCC:
case GTPIE_A_FLAGS_SRVCC:
case GTPIE_STN_SR:
case GTPIE_C_MSISDN:
case GTPIE_E_RANAP_CAUSE:
case GTPIE_ENODEB_ID:
case GTPIE_SEL_MODE_NS:
case GTPIE_ULI_TIMESTAMP:
case GTPIE_CHARGING_ADDR:
case GTPIE_PRIVATE:
iesize = 3 + hton16(ie[i].tlv.l);

View File

@@ -1,5 +1,5 @@
/*
* OpenGGSN - Gateway GPRS Support Node
* 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
@@ -12,6 +12,8 @@
#ifndef _GTPIE_H
#define _GTPIE_H
#include <arpa/inet.h>
/* Macroes for conversion between host and network byte order */
#define hton8(x) (x)
#define ntoh8(x) (x)
@@ -48,7 +50,7 @@ static __inline uint64_t hton64(uint64_t q)
#define GTPIE_DEBUG 0 /* Print debug information */
/* GTP Information elements from 29.060 v3.9.0 7.7 Information Elements */
/* GTP Information elements from 29.060 v11.8.0 7.7 Information Elements */
/* Also covers version 0. Note that version 0 6: QOS Profile was superceded *
* by 135: QOS Profile in version 1 */
@@ -84,7 +86,7 @@ static __inline uint64_t hton64(uint64_t q)
#define GTPIE_TRACE_TYPE 28 /* Trace Type 2 */
#define GTPIE_MS_NOT_REACH 29 /* MS Not Reachable Reason 1 */
/* 30-116 UNUSED */
/* 117-126 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */
/* 117-126 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15 / 32.295) */
#define GTPIE_CHARGING_ID 127 /* Charging ID 4 */
#define GTPIE_EUA 128 /* End User Address */
#define GTPIE_MM_CONTEXT 129 /* MM Context */
@@ -102,13 +104,81 @@ static __inline uint64_t hton64(uint64_t q)
#define GTPIE_EXT_HEADER_T 141 /* Extension Header Type List */
#define GTPIE_TRIGGER_ID 142 /* Trigger Id */
#define GTPIE_OMC_ID 143 /* OMC Identity */
#define GTPIE_RAN_T_CONTAIN 144 /* RAN Transparent Container */
#define GTPIE_PDP_CTX_PRIO 145 /* PDP Context Prioritization */
#define GTPIE_ADDL_RAB_S_I 146 /* Additional RAB Setup Information */
#define GTPIE_SGSN_NUMBER 147 /* SGSN Number */
#define GTPIE_COMMON_FLAGS 148 /* Common Flags */
#define GTPIE_APN_RESTR 149 /* APN Restriction */
#define GTPIE_R_PRIO_LCS 150 /* Radio Priority LCS */
#define GTPIE_RAT_TYPE 151 /* Radio Access Technology Type */
#define GTPIE_USER_LOC 152 /* User Location Information */
#define GTPIE_MS_TZ 153 /* MS Time Zone */
#define GTPIE_IMEI_SV 154 /* IMEI Software Version */
/* 239-250 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */
#define GTPIE_CML_CHG_I_CT 155 /* CAMEL Charging Information Container */
#define GTPIE_MBMS_UE_CTX 156 /* MSMS UE Context */
#define GTPIE_TMGI 157 /* Temporary Mobile Group Identity (TMGI) */
#define GTPIE_RIM_ROUT_ADDR 158 /* RIM Routing Address */
#define GTPIE_MBMS_PCO 159 /* MBMS Protocol Configuratin Options */
#define GTPIE_MBMS_SA 160 /* MBMS Service Area */
#define GTPIE_SRNC_PDCP_CTX 161 /* Source RNC PDCP Context Info */
#define GTPIE_ADDL_TRACE 162 /* Additional Trace Info */
#define GTPIE_HOP_CTR 163 /* Hop Counter */
#define GTPIE_SEL_PLMN_ID 164 /* Selected PLMN ID */
#define GTPIE_MBMS_SESS_ID 165 /* MBMS Session Identifier */
#define GTPIE_MBMS_2_3G_IND 166 /* MBMS 2G/3G Indicator */
#define GTPIE_ENH_NSAPI 167 /* Enhanced NSAPI */
#define GTPIE_MBMS_SESS_DUR 168 /* MBMS Session Duration */
#define GTPIE_A_MBMS_TRAC_I 169 /* Additional MBMS Trace Info */
#define GTPIE_MBMS_S_REP_N 170 /* MBMS Session Repetition Number */
#define GTPIE_MBMS_TTDT 171 /* MBMS Time To Data Transfer */
#define GTPIE_PS_HO_REQ_CTX 172 /* PS Handover Request Context */
#define GTPIE_BSS_CONTAINER 173 /* BSS Container */
#define GTPIE_CELL_ID 174 /* Cell Identification */
#define GTPIE_PDU_NUMBERS 175 /* PDU Numbers */
#define GTPIE_BSSGP_CAUSE 176 /* BSSGP Cause */
#define GTPIE_RQD_MBMS_BCAP 177 /* Required MBMS Bearer Capabilities */
#define GTPIE_RIM_RA_DISCR 178 /* RIM Routing Address Discriminator */
#define GTPIE_L_SETUP_PFCS 179 /* List of set-up PFCs */
#define GTPIE_PS_HO_XID_PAR 180 /* PS Handover XID Parameters */
#define GTPIE_MS_CHG_REP_A 181 /* MS Info Change Reporting Action */
#define GTPIE_DIR_TUN_FLAGS 182 /* Direct Tunnel Flags */
#define GTPIE_CORREL_ID 183 /* Correlation-ID */
#define GTPIE_BCM 184 /* Bearer control mode */
#define GTPIE_MBMS_FLOWI 185 /* MBMS Flow Identifier */
#define GTPIE_MBMS_MC_DIST 186 /* MBMS IP Multicast Distribution */
#define GTPIE_MBMS_DIST_ACK 187 /* MBMS Distribution Acknowledgement */
#define GTPIE_R_IRAT_HO_INF 188 /* Reliable INTER RAT HANDOVER INFO */
#define GTPIE_RFSP_IDX 189 /* RFSP Index */
#define GTPIE_FQDN 190 /* FQDN */
#define GTPIE_E_ALL_PRIO_1 191 /* Evolvd Allocation/Retention Priority I */
#define GTPIE_E_ALL_PRIO_2 192 /* Evolvd Allocation/Retention Priority II */
#define GTPIE_E_CMN_FLAGS 193 /* Extended Common Flags */
#define GTPIE_U_CSG_INFO 194 /* User CSG Information (UCI) */
#define GTPIE_CSG_I_REP_ACT 195 /* CSG Information Reporting Action */
#define GTPIE_CSG_ID 196 /* CSG ID */
#define GTPIE_CSG_MEMB_IND 197 /* CSG Membership Indication (CMI) */
#define GTPIE_AMBR 198 /* Aggregate Maximum Bit Rate (AMBR) */
#define GTPIE_UE_NET_CAPA 199 /* UE Network Capability */
#define GTPIE_UE_AMBR 200 /* UE-AMBR */
#define GTPIE_APN_AMBR_NS 201 /* APN-AMBR with NSAPI */
#define GTPIE_GGSN_BACKOFF 202 /* GGSN Back-Off Time */
#define GTPIE_S_PRIO_IND 203 /* Signalling Priority Indication */
#define GTPIE_S_PRIO_IND_NS 204 /* Signalling Priority Indication with NSAPI */
#define GTPIE_H_BR_16MBPS_F 205 /* Higher Bitrates than 16 Mbps flag */
/* 206: Reserved */
#define GTPIE_A_MMCTX_SRVCC 207 /* Additional MM context for SRVCC */
#define GTPIE_A_FLAGS_SRVCC 208 /* Additional flags fro SRVC */
#define GTPIE_STN_SR 209 /* STN-SR */
#define GTPIE_C_MSISDN 210 /* C-MSISDN */
#define GTPIE_E_RANAP_CAUSE 211 /* Extended RANAP Cause */
#define GTPIE_ENODEB_ID 212 /* eNodeB ID */
#define GTPIE_SEL_MODE_NS 213 /* Selection Mode with NSAPI */
#define GTPIE_ULI_TIMESTAMP 214 /* ULI Timestamp */
/* 215-238 Spare. For future use */
/* 239-250 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15 / 32.295) */
#define GTPIE_CHARGING_ADDR 251 /* Charging Gateway Address */
/* 252-254 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15) */
/* 252-254 Reserved for the GPRS charging protocol (see GTP' in GSM 12.15 / 32.295) */
#define GTPIE_PRIVATE 255 /* Private Extension */
/* GTP information element structs in network order */
@@ -220,9 +290,9 @@ struct tlv2 {
} __attribute__ ((packed));
extern int gtpie_tlv(void *p, unsigned int *length, unsigned int size,
uint8_t t, int l, void *v);
uint8_t t, int l, const void *v);
extern int gtpie_tv0(void *p, unsigned int *length, unsigned int size,
uint8_t t, int l, uint8_t * v);
uint8_t t, int l, const uint8_t * v);
extern int gtpie_tv1(void *p, unsigned int *length, unsigned int size,
uint8_t t, uint8_t v);
extern int gtpie_tv2(void *p, unsigned int *length, unsigned int size,
@@ -247,7 +317,7 @@ extern int gtpie_gettv8(union gtpie_member *ie[], int type, int instance,
uint64_t * dst);
extern int gtpie_decaps(union gtpie_member *ie[], int version,
void *pack, unsigned len);
const void *pack, unsigned len);
extern int gtpie_encaps(union gtpie_member *ie[], void *pack, unsigned *len);
extern int gtpie_encaps2(union gtpie_member ie[], unsigned int size,
void *pack, unsigned *len);

244
gtp/pdp.c
View File

@@ -1,16 +1,17 @@
/*
* OpenGGSN - Gateway GPRS Support Node
/*
* OsmoGGSN - Gateway GPRS Support Node
* Copyright (C) 2002, 2003, 2004 Mondru AB.
*
* Copyright (C) 2017 Harald Welte <laforge@gnumonks.org>
*
* 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.
*
*
*/
/*
* pdp.c:
* pdp.c:
*
*/
@@ -26,32 +27,27 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <inttypes.h>
#include "pdp.h"
#include "gtp.h"
#include "lookupa.h"
/* ***********************************************************
* Global variables TODO: most should be moved to gsn_t
*************************************************************/
static struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
static struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
/* struct pdp_t* haship[PDP_MAX]; Hash table for IP and network interface */
#include "queue.h"
/* ***********************************************************
* Functions related to PDP storage
*
* Lifecycle
* For a GGSN pdp context life begins with the reception of a
* For a GGSN pdp context life begins with the reception of a
* create pdp context request. It normally ends with the reception
* of a delete pdp context request, but will also end with the
* reception of an error indication message.
* reception of an error indication message.
* Provisions should probably be made for terminating pdp contexts
* based on either idle timeout, or by sending downlink probe
* based on either idle timeout, or by sending downlink probe
* messages (ping?) to see if the MS is still responding.
*
*
* For an SGSN pdp context life begins with the application just
* before sending off a create pdp context request. It normally
* ends when a delete pdp context response message is received
* ends when a delete pdp context response message is received
* from the GGSN, but should also end when with the reception of
* an error indication message.
*
@@ -61,15 +57,15 @@ static struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
* Downlink packets received in the GGSN are identified only by their
* network interface together with their destination IP address (Two
* network interfaces can use the same private IP address). Each IMSI
* (mobile station) can have several PDP contexts using the same IP
* (mobile station) can have several PDP contexts using the same IP
* address. In this case the traffic flow template (TFT) is used to
* determine the correct PDP context for a particular IMSI. Also it
* determine the correct PDP context for a particular IMSI. Also it
* should be possible for each PDP context to use several IP adresses
* For fixed wireless access a mobile station might need a full class
* C network. Even in the case of several IP adresses the PDP context
* should be determined on the basis of the network IP address.
* Thus we need a hash table based on network interface + IP address.
*
*
* Uplink packets are for GTP0 identified by their IMSI and NSAPI, which
* is collectively called the tunnel identifier. There is also a 16 bit
* flow label that can be used for identification of uplink packets. This
@@ -82,7 +78,7 @@ static struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
* Thus we need a hash table based on TID (IMSI and NSAPI). The TEID will
* be used for directly addressing the PDP context.
* pdp_newpdp
* pdp_newpdp
* Gives you a pdp context with no hash references In some way
* this should have a limited lifetime.
*
@@ -109,11 +105,16 @@ static struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
*
*************************************************************/
int pdp_init()
static struct gsn_t *g_gsn;
int pdp_init(struct gsn_t *gsn)
{
memset(&pdpa, 0, sizeof(pdpa));
memset(&hashtid, 0, sizeof(hashtid));
/* memset(&haship, 0, sizeof(haship)); */
if (!g_gsn) {
g_gsn = gsn;
} else {
LOGP(DLGTP, LOGL_FATAL, "This interface is depreacted and doesn't support multiple GGSN!");
return -1;
}
return 0;
}
@@ -121,6 +122,13 @@ int pdp_init()
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old)
{
return gtp_pdp_newpdp(g_gsn, pdp, imsi, nsapi, pdp_old);
}
int gtp_pdp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old)
{
struct pdp_t *pdpa = gsn->pdpa;
int n;
for (n = 0; n < PDP_MAX; n++) { /* TODO: Need to do better than linear search */
if (pdpa[n].inuse == 0) {
@@ -130,6 +138,7 @@ int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
else
memset(*pdp, 0, sizeof(struct pdp_t));
(*pdp)->inuse = 1;
(*pdp)->gsn = gsn;
(*pdp)->imsi = imsi;
(*pdp)->nsapi = nsapi;
(*pdp)->fllc = (uint16_t) n + 1;
@@ -146,7 +155,9 @@ int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
1].secondary_tei[(*pdp)->nsapi & 0x0f] =
(*pdp)->teid_own;
}
/* Default: Generate G-PDU sequence numbers on Tx */
(*pdp)->tx_gpdu_seq = true;
INIT_LLIST_HEAD(&(*pdp)->qmsg_list_req);
return 0;
}
}
@@ -155,6 +166,18 @@ int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
int pdp_freepdp(struct pdp_t *pdp)
{
struct qmsg_t *qmsg, *qmsg2;
struct pdp_t *pdpa = pdp->gsn->pdpa;
int rc;
/* Remove all enqueued messages belonging to this pdp from req tx transmit
queue. queue_freemsg will call llist_del(). */
llist_for_each_entry_safe(qmsg, qmsg2, &pdp->qmsg_list_req, entry) {
if ((rc = queue_freemsg(pdp->gsn->queue_req, qmsg)))
LOGP(DLGTP, LOGL_ERROR,
"Failed freeing qmsg from qmsg_list_req during pdp_freepdp()! %d\n", rc);
}
pdp_tiddel(pdp);
/* Remove any references in primary context */
@@ -169,12 +192,20 @@ int pdp_freepdp(struct pdp_t *pdp)
int pdp_getpdp(struct pdp_t **pdp)
{
*pdp = &pdpa[0];
*pdp = &g_gsn->pdpa[0];
return 0;
}
int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl)
{
return gtp_pdp_getgtp0(g_gsn, pdp, fl);
}
int gtp_pdp_getgtp0(struct gsn_t *gsn, struct pdp_t **pdp, uint16_t fl)
{
struct pdp_t *pdpa = gsn->pdpa;
if ((fl > PDP_MAX) || (fl < 1)) {
return EOF; /* Not found */
} else {
@@ -189,6 +220,13 @@ int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl)
int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei)
{
return gtp_pdp_getgtp1(g_gsn, pdp, tei);
}
int gtp_pdp_getgtp1(struct gsn_t *gsn, struct pdp_t **pdp, uint32_t tei)
{
struct pdp_t *pdpa = gsn->pdpa;
if ((tei > PDP_MAX) || (tei < 1)) {
return EOF; /* Not found */
} else {
@@ -201,6 +239,30 @@ int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei)
}
}
/* get a PDP based on the *peer* address + TEI-Data. Used for matching inbound Error Ind */
int pdp_getgtp1_peer_d(struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn)
{
return gtp_pdp_getgtp1_peer_d(g_gsn, pdp, peer, teid_gn);
}
int gtp_pdp_getgtp1_peer_d(struct gsn_t *gsn, struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn)
{
struct pdp_t *pdpa = gsn->pdpa;
unsigned int i;
/* this is O(n) but we don't have (nor want) another hash... */
for (i = 0; i < PDP_MAX; i++) {
struct pdp_t *candidate = &pdpa[i];
if (candidate->inuse && candidate->teid_gn == teid_gn &&
candidate->gsnru.l == sizeof(peer->sin_addr) &&
!memcmp(&peer->sin_addr, candidate->gsnru.v, sizeof(peer->sin_addr))) {
*pdp = &pdpa[i];
return 0;
}
}
return EOF;
}
int pdp_tidhash(uint64_t tid)
{
return (lookup(&tid, sizeof(tid), 0) % PDP_MAX);
@@ -208,10 +270,11 @@ int pdp_tidhash(uint64_t tid)
int pdp_tidset(struct pdp_t *pdp, uint64_t tid)
{
struct pdp_t **hashtid = pdp->gsn->hashtid;
int hash = pdp_tidhash(tid);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
DEBUGP(DLGTP, "Begin pdp_tidset tid = %llx\n", tid);
DEBUGP(DLGTP, "Begin pdp_tidset tid = %"PRIx64"\n", tid);
pdp->tidnext = NULL;
pdp->tid = tid;
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext)
@@ -226,10 +289,11 @@ int pdp_tidset(struct pdp_t *pdp, uint64_t tid)
int pdp_tiddel(struct pdp_t *pdp)
{
struct pdp_t **hashtid = pdp->gsn->hashtid;
int hash = pdp_tidhash(pdp->tid);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
DEBUGP(DLGTP, "Begin pdp_tiddel tid = %llx\n", pdp->tid);
DEBUGP(DLGTP, "Begin pdp_tiddel tid = %"PRIx64"\n", pdp->tid);
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
if (pdp2 == pdp) {
if (!pdp_prev)
@@ -247,9 +311,15 @@ int pdp_tiddel(struct pdp_t *pdp)
int pdp_tidget(struct pdp_t **pdp, uint64_t tid)
{
return gtp_pdp_tidget(g_gsn, pdp, tid);
}
int gtp_pdp_tidget(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t tid)
{
struct pdp_t **hashtid = gsn->hashtid;
int hash = pdp_tidhash(tid);
struct pdp_t *pdp2;
DEBUGP(DLGTP, "Begin pdp_tidget tid = %llx\n", tid);
DEBUGP(DLGTP, "Begin pdp_tidget tid = %"PRIx64"\n", tid);
for (pdp2 = hashtid[hash]; pdp2; pdp2 = pdp2->tidnext) {
if (pdp2->tid == tid) {
*pdp = pdp2;
@@ -263,102 +333,17 @@ int pdp_tidget(struct pdp_t **pdp, uint64_t tid)
int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi)
{
return pdp_tidget(pdp,
(imsi & 0x0fffffffffffffffull) +
((uint64_t) nsapi << 60));
return gtp_pdp_getimsi(g_gsn, pdp, imsi, nsapi);
}
/*
int pdp_iphash(void* ipif, struct ul66_t *eua) {
/#printf("IPhash %ld\n", lookup(eua->v, eua->l, ipif) % PDP_MAX);#/
return (lookup(eua->v, eua->l, ipif) % PDP_MAX);
}
int pdp_ipset(struct pdp_t *pdp, void* ipif, struct ul66_t *eua) {
int hash;
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
if (PDP_DEBUG) printf("Begin pdp_ipset %d %d %2x%2x%2x%2x\n",
(unsigned) ipif, eua->l,
eua->v[2], eua->v[3],
eua->v[4], eua->v[5]);
pdp->ipnext = NULL;
pdp->ipif = ipif;
pdp->eua.l = eua->l;
memcpy(pdp->eua.v, eua->v, eua->l);
hash = pdp_iphash(pdp->ipif, &pdp->eua);
for (pdp2 = haship[hash]; pdp2; pdp2 = pdp2->ipnext)
pdp_prev = pdp2;
if (!pdp_prev)
haship[hash] = pdp;
else
pdp_prev->ipnext = pdp;
if (PDP_DEBUG) printf("End pdp_ipset\n");
return 0;
int gtp_pdp_getimsi(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi)
{
return gtp_pdp_tidget(gsn, pdp, pdp_gettid(imsi, nsapi));
}
int pdp_ipdel(struct pdp_t *pdp) {
int hash = pdp_iphash(pdp->ipif, &pdp->eua);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
if (PDP_DEBUG) printf("Begin pdp_ipdel\n");
for (pdp2 = haship[hash]; pdp2; pdp2 = pdp2->ipnext) {
if (pdp2 == pdp) {
if (!pdp_prev)
haship[hash] = pdp2->ipnext;
else
pdp_prev->ipnext = pdp2->ipnext;
if (PDP_DEBUG) printf("End pdp_ipdel: PDP found\n");
return 0;
}
pdp_prev = pdp2;
}
if (PDP_DEBUG) printf("End pdp_ipdel: PDP not found\n");
return EOF; /# End of linked list and not found #/
}
int pdp_ipget(struct pdp_t **pdp, void* ipif, struct ul66_t *eua) {
int hash = pdp_iphash(ipif, eua);
struct pdp_t *pdp2;
/#printf("Begin pdp_ipget %d %d %2x%2x%2x%2x\n", (unsigned)ipif, eua->l,
eua->v[2],eua->v[3],eua->v[4],eua->v[5]);#/
for (pdp2 = haship[hash]; pdp2; pdp2 = pdp2->ipnext) {
if ((pdp2->ipif == ipif) && (pdp2->eua.l == eua->l) &&
(memcmp(&pdp2->eua.v, &eua->v, eua->l) == 0)) {
*pdp = pdp2;
/#printf("End pdp_ipget. Found\n");#/
return 0;
}
}
if (PDP_DEBUG) printf("End pdp_ipget Notfound %d %d %2x%2x%2x%2x\n",
(unsigned)ipif, eua->l, eua->v[2],eua->v[3],eua->v[4],eua->v[5]);
return EOF; /# End of linked list and not found #/
}
*/
/* Various conversion functions */
int pdp_ntoeua(struct in_addr *src, struct ul66_t *eua)
{
eua->l = 6;
eua->v[0] = 0xf1; /* IETF */
eua->v[1] = 0x21; /* IPv4 */
memcpy(&eua->v[2], src, 4); /* Copy a 4 byte address */
return 0;
}
int pdp_euaton(struct ul66_t *eua, struct in_addr *dst)
{
if ((eua->l != 6) || (eua->v[0] != 0xf1) || (eua->v[1] != 0x21)) {
return EOF;
}
memcpy(dst, &eua->v[2], 4); /* Copy a 4 byte address */
return 0;
}
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi)
{
return (imsi & 0x0fffffffffffffffull) + ((uint64_t) nsapi << 60);
@@ -370,13 +355,16 @@ void pdp_set_imsi_nsapi(struct pdp_t *pdp, uint64_t teid)
pdp->nsapi = (teid & 0xf000000000000000ull) >> 60;
}
int ulcpy(void *dst, void *src, size_t size)
/* Count amount of secondary PDP contexts linked to this primary PDP context
* (itself included). Must be called on a primary PDP context. */
unsigned int pdp_count_secondary(const struct pdp_t *pdp)
{
if (((struct ul255_t *)src)->l <= size) {
((struct ul255_t *)dst)->l = ((struct ul255_t *)src)->l;
memcpy(((struct ul255_t *)dst)->v, ((struct ul255_t *)src)->v,
((struct ul255_t *)dst)->l);
return 0;
} else
return EOF;
unsigned int n;
unsigned int count = 0;
OSMO_ASSERT(!pdp->secondary);
for (n = 0; n < PDP_MAXNSAPI; n++)
if (pdp->secondary_tei[n])
count++;
return count;
}

View File

@@ -1,20 +1,37 @@
/*
* OpenGGSN - Gateway GPRS Support Node
/*
* OsmoGGSN - Gateway GPRS Support Node
* Copyright (C) 2002, 2003 Mondru AB.
*
* Copyright (C) 2017 Harald Welte <laforge@gnumonks.org>
*
* 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 _PDP_H
#define _PDP_H
#include <stdbool.h>
#include <netinet/in.h>
#include <osmocom/core/defs.h>
#include <osmocom/core/linuxlist.h>
struct gsn_t;
#define LOGPDPX(ss, level, pdp, fmt, args...) \
LOGP(ss, level, "PDP(%s:%u): " fmt, imsi_gtp2str(&(pdp)->imsi), (pdp)->nsapi, ## args)
#define PDP_MAX 1024 /* Max number of PDP contexts */
#define PDP_MAXNSAPI 16 /* Max number of NSAPI */
#define PDP_EUA_ORG_IETF 0xF1
#define PDP_EUA_TYPE_v4 0x21
#define PDP_EUA_TYPE_v6 0x57
#define PDP_EUA_TYPE_v4v6 0x8D
/* GTP Information elements from 29.060 v3.9.0 7.7 Information Elements */
/* Also covers version 0. Note that version 0 6: QOS Profile was superceded *
* by 135: QOS Profile in version 1 */
@@ -59,16 +76,16 @@ struct ul255_t {
* and 09.60.
* 31 * 4 + 15 structs + = 120 + 15 structs ~ 2k / context
* Structs: IP address 16+4 bytes (6), APN 255 bytes (2)
* QOS: 255 bytes (3), msisdn 16 bytes (1),
* QOS: 255 bytes (3), msisdn 16 bytes (1),
*
* TODO: We need to consider who manages the pdp_t hash tables
* Is it gtp_lib, or is it the application?
* I suppose that it will be gtp_lib.
* I suppose that it will be gtp_lib.
* SGSN will ask gtplib for new pdp_t. Fill out the fields,
* and pass it on to gtp_create_pdp_req.
* GGSN will receive gtp_create_pdp_ind, create new pdp_t and
* send responce to SGSN.
* SGSN will receive response and gtplib will find the
* SGSN will receive response and gtplib will find the
* original pdp_t corresponding to the request. This will be
* passed on to the application.
* Eventually the SGSN will close the connection, and the
@@ -76,10 +93,10 @@ struct ul255_t {
* This means that gtplib need to have functions to
* allocate, free, sort and find pdp_t
* (newpdp, freepdp, getpdp)
* Hash tables: TID, IMSI, IP etc.)
* Hash tables: TID, IMSI, IP etc.)
*
*
* Secondary PDP Context Activation Procedure
* Secondary PDP Context Activation Procedure
*
* With GTP version 1 it is possible to establish multiple PDP
* contexts with the same IP address. With this scheme the first
@@ -109,7 +126,7 @@ struct pdp_t {
/* Parameters shared by all PDP context belonging to the same MS */
void *ipif; /* IP network interface */
void *peer; /* Pointer to peer protocol */
void *peer[2]; /* Pointer to peer protocol */
void *asap; /* Application specific service access point */
uint64_t imsi; /* International Mobile Subscriber Identity. */
@@ -221,37 +238,43 @@ struct pdp_t {
/* to be used by libgtp callers/users (to attach their own private state) */
void *priv;
struct gsn_t *gsn; /* Back pointer to GSN where this pdp ctx belongs to */
bool tx_gpdu_seq; /* Transmit (true) or suppress G-PDU sequence numbers */
struct llist_head qmsg_list_req; /* list of req qmsg_t in retrans queue belonging this pdp ctx */
};
/* functions related to pdp_t management */
int pdp_init();
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old);
int gtp_pdp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi,
uint8_t nsapi, struct pdp_t *pdp_old);
int pdp_freepdp(struct pdp_t *pdp);
int pdp_getpdp(struct pdp_t **pdp);
int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl);
int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei);
int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi);
int gtp_pdp_getgtp0(struct gsn_t *gsn, struct pdp_t **pdp, uint16_t fl);
int gtp_pdp_getgtp1(struct gsn_t *gsn, struct pdp_t **pdp, uint32_t tei);
int gtp_pdp_getgtp1_peer_d(struct gsn_t *gsn, struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn);
int gtp_pdp_getimsi(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi);
int gtp_pdp_tidget(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t tid);
int pdp_tidhash(uint64_t tid);
int pdp_tidset(struct pdp_t *pdp, uint64_t tid);
int pdp_tiddel(struct pdp_t *pdp);
int pdp_tidget(struct pdp_t **pdp, uint64_t tid);
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi);
void pdp_set_imsi_nsapi(struct pdp_t *pdp, uint64_t teid);
/*
int pdp_iphash(void* ipif, struct ul66_t *eua);
int pdp_ipset(struct pdp_t *pdp, void* ipif, struct ul66_t *eua);
int pdp_ipdel(struct pdp_t *pdp);
int pdp_ipget(struct pdp_t **pdp, void* ipif, struct ul66_t *eua);
*/
unsigned int pdp_count_secondary(const struct pdp_t *pdp);
/* Deprecated APIs (support for only 1 GSN per process). Must be used only after first call to gtp_new() and until it is freed. */
int pdp_init(struct gsn_t *gsn); /* Use only allowed inside libgtp to keep compatiblity with deprecated APIs defined here. */
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old) OSMO_DEPRECATED("Use gtp_pdp_newpdp() instead");
int pdp_getpdp(struct pdp_t **pdp) OSMO_DEPRECATED("Use gsn_t->pdpa field instead");
int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl) OSMO_DEPRECATED("Use gtp_pdp_getgtp0() instead");
int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei) OSMO_DEPRECATED("Use gtp_pdp_getgtp1() instead");
int pdp_getgtp1_peer_d(struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn) OSMO_DEPRECATED("Use gtp_pdp_getgtp1_peer_d() instead");
int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi) OSMO_DEPRECATED("Use gtp_pdp_getimsi() instead");
int pdp_tidget(struct pdp_t **pdp, uint64_t tid) OSMO_DEPRECATED("Use gtp_pdp_tidget() instead");
int pdp_ntoeua(struct in_addr *src, struct ul66_t *eua);
int pdp_euaton(struct ul66_t *eua, struct in_addr *dst);
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi);
int ulcpy(void *dst, void *src, size_t size);
#endif /* !_PDP_H */

View File

@@ -1,13 +1,14 @@
/*
* OpenGGSN - Gateway GPRS Support Node
/*
* OsmoGGSN - Gateway GPRS Support Node
* Copyright (C) 2002, 2003, 2004 Mondru AB.
* Copyright (C) 2011 Harald Welte <laforge@gnumonks.org>
*
* Copyright (C) 2016 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.
*
*
*/
/*
@@ -61,7 +62,7 @@ static int queue_seqhash(struct sockaddr_in *peer, uint16_t seq)
return seq % QUEUE_HASH_SIZE;
}
/*! \brief Insert a message with given sequence number into the hash
/*! \brief Insert a message with given sequence number into the hash.
*
* This function sets the peer and the seq of the qmsg and then inserts
* the qmsg into the queue hash. To do so, it does a hashtable lookup
@@ -78,7 +79,7 @@ static int queue_seqset(struct queue_t *queue, struct qmsg_t *qmsg,
if (QUEUE_DEBUG)
printf("Begin queue_seqset seq = %d\n", (int)seq);
if (QUEUE_DEBUG)
printf("SIZEOF PEER %d, *PEER %d\n", sizeof(peer),
printf("SIZEOF PEER %zu, *PEER %zu\n", sizeof(peer),
sizeof(*peer));
qmsg->seq = seq;
@@ -105,8 +106,7 @@ static int queue_seqdel(struct queue_t *queue, struct qmsg_t *qmsg)
printf("Begin queue_seqdel seq = %d\n", (int)qmsg->seq);
for (qmsg2 = queue->hashseq[hash]; qmsg2; qmsg2 = qmsg2->seqnext) {
/* FIXME: this is always true !?! */
if (qmsg == qmsg) {
if (qmsg == qmsg2) {
if (!qmsg_prev)
queue->hashseq[hash] = qmsg2->seqnext;
else
@@ -121,25 +121,30 @@ static int queue_seqdel(struct queue_t *queue, struct qmsg_t *qmsg)
return EOF; /* End of linked list and not found */
}
/*! \brief Allocates and initialises new queue structure */
/*! Allocates and initialises new queue structure.
* \param[out] queue pointer where to store the allocated object. Must be freed with queue_free
* \returns zero on success, non-zero on error
*/
int queue_new(struct queue_t **queue)
{
if (QUEUE_DEBUG)
printf("queue_new\n");
*queue = calloc(1, sizeof(struct queue_t));
if (!(*queue))
return EOF;
(*queue)->next = 0;
(*queue)->first = -1;
(*queue)->last = -1;
if (QUEUE_DEBUG)
queue_print(*queue);
if (*queue)
return 0;
else
return EOF;
return 0;
}
/*! \brief Deallocates queue structure */
/*! Deallocates queue structure.
* \param[in] queue pointer previously allocated by queue_new
* \returns zero on success, non-zero on error.
*/
int queue_free(struct queue_t *queue)
{
if (QUEUE_DEBUG)
@@ -150,7 +155,13 @@ int queue_free(struct queue_t *queue)
return 0;
}
/*! \brief Add a new message to the queue */
/*! Add a new message to the queue.
* \param[in] queue pointer previously allocated by queue_new
* \param[out] qmsg first message from the queue (if succeeds)
* \param[in] peer who sent the message to add
* \param[in] seq sequence number of the message to add
* \returns zero on success, non-zero on error.
*/
int queue_newmsg(struct queue_t *queue, struct qmsg_t **qmsg,
struct sockaddr_in *peer, uint16_t seq)
{
@@ -161,6 +172,7 @@ int queue_newmsg(struct queue_t *queue, struct qmsg_t **qmsg,
} else {
*qmsg = &queue->qmsga[queue->next];
queue_seqset(queue, *qmsg, peer, seq);
INIT_LLIST_HEAD(&(*qmsg)->entry);
(*qmsg)->state = 1; /* Space taken */
(*qmsg)->this = queue->next;
(*qmsg)->next = -1; /* End of the queue */
@@ -177,7 +189,11 @@ int queue_newmsg(struct queue_t *queue, struct qmsg_t **qmsg,
}
}
/*! \brief Simply remoev a given qmsg_t from the queue
/*! Remove an element from the queue.
* \param[in] queue pointer previously allocated by queue_new
* \param[in] qmsg message to free
* \returns zero on success, non-zero on error.
*
* Internally, we first delete the entry from the queue, and then update
* up our global queue->first / queue->last pointers. Finally,
@@ -191,6 +207,8 @@ int queue_freemsg(struct queue_t *queue, struct qmsg_t *qmsg)
return EOF; /* Not in queue */
}
llist_del(&qmsg->entry);
queue_seqdel(queue, qmsg);
if (qmsg->next == -1) /* Are we the last in queue? */
@@ -211,7 +229,11 @@ int queue_freemsg(struct queue_t *queue, struct qmsg_t *qmsg)
return 0;
}
/*! \brief Move a given qmsg_t to the end of the queue ?!? */
/*! Move a given qmsg_t to the end of the queue.
* \param[in] queue pointer previously allocated by queue_new
* \param[in] qmsg message to move to the end of the queue
* \returns zero on success, non-zero on error.
*/
int queue_back(struct queue_t *queue, struct qmsg_t *qmsg)
{
if (QUEUE_DEBUG)
@@ -237,7 +259,11 @@ int queue_back(struct queue_t *queue, struct qmsg_t *qmsg)
return 0;
}
/*! \brief Get the first element in the entire queue */
/*! Get the first element in the entire queue.
* \param[in] queue pointer previously allocated by queue_new
* \param[out] qmsg first message from the queue (if succeeds)
* \returns zero on success, non-zero on error.
*/
int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg)
{
/*printf("queue_getfirst\n"); */
@@ -251,27 +277,13 @@ int queue_getfirst(struct queue_t *queue, struct qmsg_t **qmsg)
return 0;
}
/*! \brief Linear search over entire queue to get given peer + seq*/
/* FIXME: unused, dead code! */
int queue_getseqx(struct queue_t *queue, struct qmsg_t **qmsg,
struct sockaddr_in *peer, uint16_t seq)
{
int n;
if (QUEUE_DEBUG)
printf("queue_getseq, %d\n", (int)seq);
if (QUEUE_DEBUG)
queue_print(queue);
for (n = 0; n < QUEUE_SIZE; n++) {
if ((queue->qmsga[n].seq == seq) &&
(!memcmp(&queue->qmsga[n].peer, peer, sizeof(*peer)))) {
*qmsg = &queue->qmsga[n];
return 0;
}
}
return EOF; /* Not found */
}
/*! \brief Get a queue entry for a given peer + seq */
/*! Get a queue entry for a given peer + seq.
* \param[in] queue pointer previously allocated by queue_new
* \param[out] qmsg first message from the queue (if succeeds)
* \param[in] peer who sent the message to retrieve
* \param[in] seq sequence number of the message to retrive
* \returns zero on success, non-zero on error.
*/
int queue_seqget(struct queue_t *queue, struct qmsg_t **qmsg,
struct sockaddr_in *peer, uint16_t seq)
{
@@ -293,7 +305,14 @@ int queue_seqget(struct queue_t *queue, struct qmsg_t **qmsg,
return EOF; /* End of linked list and not found */
}
/*! \brief look-up a given seq/peer, return cbp + type and free entry */
/*! look-up a given seq/peer, return cbp + type and free entry.
* \param[in] queue pointer previously allocated by queue_new
* \param[in] peer who sent the message to retrieve
* \param[in] seq sequence number of the message to retrive
* \param[out] type GTP message type
* \param[out] type callback pointer of the message
* \returns zero on success, non-zero on error.
*/
int queue_freemsg_seq(struct queue_t *queue, struct sockaddr_in *peer,
uint16_t seq, uint8_t * type, void **cbp)
{

View File

@@ -1,12 +1,12 @@
/*
* OpenGGSN - Gateway GPRS Support Node
/*
* 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.
*
*
*/
/*
@@ -17,6 +17,10 @@
#ifndef _QUEUE_H
#define _QUEUE_H
#include <osmocom/core/linuxlist.h>
#include "gtp.h"
#define QUEUE_DEBUG 0 /* Print debug information */
#define QUEUE_SIZE 1024 /* Size of retransmission queue */
@@ -37,6 +41,7 @@ struct qmsg_t { /* Holder for queued packets */
int this; /* Pointer to myself */
time_t timeout; /* When do we retransmit this packet? */
int retrans; /* How many times did we retransmit this? */
struct llist_head entry; /* Listed with other qmsg_t belonging to a pdp_t->qmsg_list_req */
};
struct queue_t {

View File

@@ -1,7 +1,12 @@
noinst_LIBRARIES = libmisc.a
noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h
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
AM_CFLAGS = -O2 -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
libmisc_a_SOURCES = getopt1.c getopt.c ippool.c lookup.c tun.c debug.c
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
if ENABLE_GTP_KERNEL
AM_CFLAGS += -DGTP_KERNEL $(LIBGTPNL_CFLAGS)
libmisc_a_SOURCES += gtp-kernel.c
endif

211
lib/checksum.c Normal file
View File

@@ -0,0 +1,211 @@
/*
*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* IP/TCP/UDP checksumming routines
*
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Tom May, <ftom@netcom.com>
* Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
* Lots of code moved from tcp.c and ip.c; see those files
* for more names.
*
* 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
* Fixed some nasty bugs, causing some horrible crashes.
* A: At some points, the sum (%0) was used as
* length-counter instead of the length counter
* (%1). Thanks to Roman Hodek for pointing this out.
* B: GCC seems to mess up if one uses too many
* data-registers to hold input values and one tries to
* specify d0 and d1 as scratch registers. Letting gcc
* choose these registers itself solves the problem.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
kills, so most of the assembly has to go. */
#if defined(__FreeBSD__)
#define _KERNEL /* needed on FreeBSD 10.x for s6_addr32 */
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/endian.h>
#endif
#include "checksum.h"
#include <arpa/inet.h>
static inline unsigned short from32to16(unsigned int x)
{
/* add up 16-bit and 16-bit for 16+c bit */
x = (x & 0xffff) + (x >> 16);
/* add up carry.. */
x = (x & 0xffff) + (x >> 16);
return x;
}
static unsigned int do_csum(const unsigned char *buff, int len)
{
int odd;
unsigned int result = 0;
if (len <= 0)
goto out;
odd = 1 & (unsigned long) buff;
if (odd) {
#if BYTE_ORDER == LITTLE_ENDIAN
result += (*buff << 8);
#else
result = *buff;
#endif
len--;
buff++;
}
if (len >= 2) {
if (2 & (unsigned long) buff) {
result += *(unsigned short *) buff;
len -= 2;
buff += 2;
}
if (len >= 4) {
const unsigned char *end = buff + ((unsigned)len & ~3);
unsigned int carry = 0;
do {
unsigned int w = *(unsigned int *) buff;
buff += 4;
result += carry;
result += w;
carry = (w > result);
} while (buff < end);
result += carry;
result = (result & 0xffff) + (result >> 16);
}
if (len & 2) {
result += *(unsigned short *) buff;
buff += 2;
}
}
if (len & 1)
#if BYTE_ORDER == LITTLE_ENDIAN
result += *buff;
#else
result += (*buff << 8);
#endif
result = from32to16(result);
if (odd)
result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
out:
return result;
}
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
uint16_t ip_fast_csum(const void *iph, unsigned int ihl)
{
return (uint16_t)~do_csum(iph, ihl*4);
}
/*
* computes the checksum of a memory block at buff, length len,
* and adds in "sum" (32-bit)
*
* returns a 32-bit number suitable for feeding into itself
* or csum_tcpudp_magic
*
* this function must be called with even lengths, except
* for the last fragment, which may be odd
*
* it's best to have buff aligned on a 32-bit boundary
*/
uint32_t csum_partial(const void *buff, int len, uint32_t wsum)
{
unsigned int sum = (unsigned int)wsum;
unsigned int result = do_csum(buff, len);
/* add in old sum, and carry.. */
result += sum;
if (sum > result)
result += 1;
return (uint32_t)result;
}
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
uint16_t ip_compute_csum(const void *buff, int len)
{
return (uint16_t)~do_csum(buff, len);
}
uint16_t csum_ipv6_magic(const struct in6_addr *saddr,
const struct in6_addr *daddr,
uint32_t len, uint8_t proto, uint32_t csum)
{
int carry;
uint32_t ulen;
uint32_t uproto;
uint32_t sum = (uint32_t)csum;
sum += (uint32_t)saddr->s6_addr32[0];
carry = (sum < (uint32_t)saddr->s6_addr32[0]);
sum += carry;
sum += (uint32_t)saddr->s6_addr32[1];
carry = (sum < (uint32_t)saddr->s6_addr32[1]);
sum += carry;
sum += (uint32_t)saddr->s6_addr32[2];
carry = (sum < (uint32_t)saddr->s6_addr32[2]);
sum += carry;
sum += (uint32_t)saddr->s6_addr32[3];
carry = (sum < (uint32_t)saddr->s6_addr32[3]);
sum += carry;
sum += (uint32_t)daddr->s6_addr32[0];
carry = (sum < (uint32_t)daddr->s6_addr32[0]);
sum += carry;
sum += (uint32_t)daddr->s6_addr32[1];
carry = (sum < (uint32_t)daddr->s6_addr32[1]);
sum += carry;
sum += (uint32_t)daddr->s6_addr32[2];
carry = (sum < (uint32_t)daddr->s6_addr32[2]);
sum += carry;
sum += (uint32_t)daddr->s6_addr32[3];
carry = (sum < (uint32_t)daddr->s6_addr32[3]);
sum += carry;
ulen = (uint32_t)htonl((uint32_t) len);
sum += ulen;
carry = (sum < ulen);
sum += carry;
uproto = (uint32_t)htonl(proto);
sum += uproto;
carry = (sum < uproto);
sum += carry;
return csum_fold((uint32_t)sum);
}
/* fold a partial checksum */
uint16_t csum_fold(uint32_t csum)
{
uint32_t sum = (uint32_t)csum;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
return (uint16_t)~sum;
}

13
lib/checksum.h Normal file
View File

@@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
#include <netinet/in.h>
uint16_t ip_fast_csum(const void *iph, unsigned int ihl);
uint32_t csum_partial(const void *buff, int len, uint32_t wsum);
uint16_t ip_compute_csum(const void *buff, int len);
uint16_t csum_ipv6_magic(const struct in6_addr *saddr,
const struct in6_addr *daddr,
uint32_t len, uint8_t proto, uint32_t csum);
uint16_t csum_fold(uint32_t csum);

View File

@@ -24,6 +24,11 @@ static const struct log_info_cat default_categories[] = {
[DSGSN] = {
.name = "DSGSN",
.description = "SGSN Emulator",
.enabled = 1, .loglevel = LOGL_INFO,
},
[DICMP6] = {
.name = "DICMP6",
.description = "ICMPv6",
.enabled = 1, .loglevel = LOGL_NOTICE,
},
};

164
lib/gtp-kernel.c Normal file
View File

@@ -0,0 +1,164 @@
#ifdef __linux__
#define _GNU_SOURCE 1 /* strdup() prototype, broken arpa/inet.h */
#endif
#include "../config.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <libgtpnl/gtp.h>
#include <libgtpnl/gtpnl.h>
#include <errno.h>
#include <time.h>
#include "../lib/tun.h"
#include "../lib/syserr.h"
#include "../lib/util.h"
#include "../lib/ippool.h"
#include "../gtp/pdp.h"
#include "../gtp/gtp.h"
#include "gtp-kernel.h"
static void pdp_debug(const char *prefix, const char *devname, struct pdp_t *pdp)
{
char buf4[INET_ADDRSTRLEN], buf6[INET6_ADDRSTRLEN];
struct ippoolm_t *peer;
struct in_addr ia;
buf4[0] = '\0';
if ((peer = pdp_get_peer_ipv(pdp, false)))
in46a_ntop(&peer->addr, buf4, sizeof(buf4));
buf6[0] = '\0';
if ((peer = pdp_get_peer_ipv(pdp, true)))
in46a_ntop(&peer->addr, buf6, sizeof(buf6));
gsna2in_addr(&ia, &pdp->gsnrc);
LOGPDPX(DGGSN, LOGL_DEBUG, pdp, "%s %s v%u TEID %"PRIx64" EUA=(%s,%s) SGSN=%s\n", prefix,
devname, pdp->version,
pdp->version == 0 ? pdp_gettid(pdp->imsi, pdp->nsapi) : pdp->teid_gn,
buf4, buf6, inet_ntoa(ia));
}
static struct {
int genl_id;
struct mnl_socket *nl;
} gtp_nl;
static int gtp_kernel_init_once(void)
{
/* only initialize once */
if (gtp_nl.nl)
return 0;
gtp_nl.nl = genl_socket_open();
if (gtp_nl.nl == NULL) {
LOGP(DGGSN, LOGL_ERROR, "cannot create genetlink socket\n");
return -1;
}
gtp_nl.genl_id = genl_lookup_family(gtp_nl.nl, "gtp");
if (gtp_nl.genl_id < 0) {
LOGP(DGGSN, LOGL_ERROR, "cannot lookup GTP genetlink ID\n");
genl_socket_close(gtp_nl.nl);
gtp_nl.nl = NULL;
return -1;
}
LOGP(DGGSN, LOGL_NOTICE, "Initialized GTP kernel mode (genl ID is %d)\n", gtp_nl.genl_id);
return 0;
}
int gtp_kernel_create(int dest_ns, const char *devname, int fd0, int fd1u)
{
if (gtp_kernel_init_once() < 0)
return -1;
return gtp_dev_create(dest_ns, devname, fd0, fd1u);
}
int gtp_kernel_create_sgsn(int dest_ns, const char *devname, int fd0, int fd1u)
{
if (gtp_kernel_init_once() < 0)
return -1;
return gtp_dev_create_sgsn(dest_ns, devname, fd0, fd1u);
}
void gtp_kernel_stop(const char *devname)
{
gtp_dev_destroy(devname);
}
int gtp_kernel_tunnel_add(struct pdp_t *pdp, const char *devname)
{
struct in_addr ms, sgsn;
struct gtp_tunnel *t;
int ret;
pdp_debug(__func__, devname, pdp);
t = gtp_tunnel_alloc();
if (t == NULL)
return -1;
memcpy(&ms, &pdp->eua.v[2], sizeof(struct in_addr));
memcpy(&sgsn, &pdp->gsnrc.v[0], sizeof(struct in_addr));
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);
}
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)
{
struct gtp_tunnel *t;
int ret;
pdp_debug(__func__, devname, pdp);
t = gtp_tunnel_alloc();
if (t == NULL)
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);
}
ret = gtp_del_tunnel(gtp_nl.genl_id, gtp_nl.nl, t);
gtp_tunnel_free(t);
return ret;
}

38
lib/gtp-kernel.h Normal file
View File

@@ -0,0 +1,38 @@
#ifndef _GTP_KERNEL_H_
#define _GTP_KERNEL_H_
struct gengetopt_args_info;
extern int debug;
extern char *ipup;
#ifdef GTP_KERNEL
int gtp_kernel_create(int dest_ns, const char *devname, int fd0, int fd1u);
int gtp_kernel_create_sgsn(int dest_ns, const char *devname, int fd0, int fd1u);
void gtp_kernel_stop(const char *devname);
int gtp_kernel_tunnel_add(struct pdp_t *pdp, const char *devname);
int gtp_kernel_tunnel_del(struct pdp_t *pdp, const char *devname);
#else
static inline int gtp_kernel_create(int dest_ns, const char *devname, int fd0, int fd1u)
{
SYS_ERR(DGGSN, LOGL_ERROR, 0, "ggsn compiled without GTP kernel support!\n");
return -1;
}
#define gtp_kernel_create_sgsn gtp_kernel_create
static inline void gtp_kernel_stop(const char *devname) {}
static inline int gtp_kernel_tunnel_add(struct pdp_t *pdp, const char *devname)
{
return 0;
}
static inline int gtp_kernel_tunnel_del(struct pdp_t *pdp, const char *devname)
{
return 0;
}
#endif
#endif /* _GTP_KERNEL_H_ */

242
lib/icmpv6.c Normal file
View File

@@ -0,0 +1,242 @@
/* Minimal ICMPv6 code for generating router advertisements as required by
* relevant 3GPP specs for a GGSN with IPv6 PDP contexts */
/* (C) 2017 by Harald Welte <laforge@gnumonks.org>
*
* 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.
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <netinet/in.h>
#if defined(__FreeBSD__)
#include <sys/types.h> /* FreeBSD 10.x needs this before ip6.h */
#include <sys/endian.h>
#endif
#include <netinet/ip6.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/utils.h>
#include "checksum.h"
#include "../gtp/gtp.h"
#include "../gtp/pdp.h"
#include "ippool.h"
#include "syserr.h"
#include "icmpv6.h"
#include "config.h"
/* 29.061 11.2.1.3.4 IPv6 Router Configuration Variables in GGSN */
#define GGSN_MaxRtrAdvInterval 21600 /* 6 hours */
#define GGSN_MinRtrAdvInterval 16200 /* 4.5 hours */
#define GGSN_AdvValidLifetime 0xffffffff /* infinite */
#define GGSN_AdvPreferredLifetime 0xffffffff /* infinite */
/* RFC3307 link-local scope multicast address */
const struct in6_addr all_router_mcast_addr = {
.s6_addr = { 0xff,0x02,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,2 }
};
/* Prepends the ipv6 header and returns checksum content */
uint16_t icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr *saddr,
const struct in6_addr *daddr)
{
uint32_t len;
uint16_t skb_csum;
struct ip6_hdr *i6h;
/* checksum */
skb_csum = csum_partial(msgb_data(msg), msgb_length(msg), 0);
len = msgb_length(msg);
skb_csum = csum_ipv6_magic(saddr, daddr, len, IPPROTO_ICMPV6, skb_csum);
/* Push IPv6 header in front of ICMPv6 packet */
i6h = (struct ip6_hdr *) msgb_push(msg, sizeof(*i6h));
/* 4 bits version, 8 bits TC, 20 bits flow-ID */
i6h->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000);
i6h->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(len);
i6h->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_ICMPV6;
i6h->ip6_ctlun.ip6_un1.ip6_un1_hlim = 255;
i6h->ip6_src = *saddr;
i6h->ip6_dst = *daddr;
return skb_csum;
}
/*! construct a RFC4861 compliant ICMPv6 router soliciation
* \param[in] saddr Source IPv6 address for router advertisement
* \param[in] daddr Destination IPv6 address for router advertisement IPv6 header
* \param[in] prefix The single prefix to be advertised (/64 implied!)
* \returns callee-allocated message buffer containing router advertisement */
struct msgb *icmpv6_construct_rs(const struct in6_addr *saddr)
{
struct msgb *msg = msgb_alloc_headroom(512,128, "IPv6 RS");
struct icmpv6_rsol_hdr *rs;
OSMO_ASSERT(msg);
rs = (struct icmpv6_rsol_hdr *) msgb_put(msg, sizeof(*rs));
rs->hdr.type = 133; /* see RFC4861 4.1 */
rs->hdr.code = 0; /* see RFC4861 4.1 */
rs->hdr.csum = 0; /* updated below */
rs->reserved = 0; /* see RFC4861 4.1 */
rs->hdr.csum = icmpv6_prepend_ip6hdr(msg, saddr, &all_router_mcast_addr);
return msg;
}
/*! construct a 3GPP 29.061 compliant router advertisement for a given prefix
* \param[in] saddr Source IPv6 address for router advertisement
* \param[in] daddr Destination IPv6 address for router advertisement IPv6 header
* \param[in] prefix The single prefix to be advertised (/64 implied!)
* \returns callee-allocated message buffer containing router advertisement */
static struct msgb *icmpv6_construct_ra(const struct in6_addr *saddr,
const struct in6_addr *daddr,
const struct in6_addr *prefix)
{
struct msgb *msg = msgb_alloc_headroom(512,128, "IPv6 RA");
struct icmpv6_radv_hdr *ra;
struct icmpv6_opt_prefix *ra_opt_pref;
OSMO_ASSERT(msg);
ra = (struct icmpv6_radv_hdr *) msgb_put(msg, sizeof(*ra));
ra->hdr.type = 134; /* see RFC4861 4.2 */
ra->hdr.code = 0; /* see RFC4861 4.2 */
ra->hdr.csum = 0; /* updated below */
ra->cur_ho_limit = 64; /* seems reasonable? */
/* the GGSN shall leave the M-flag cleared in the Router
* Advertisement messages */
ra->m = 0;
/* The GGSN may set the O-flag if there are additional
* configuration parameters that need to be fetched by the MS */
ra->o = 0; /* no DHCPv6 */
ra->res = 0;
/* RFC4861 Default: 3 * MaxRtrAdvInterval */
ra->router_lifetime = htons(3*GGSN_MaxRtrAdvInterval);
ra->reachable_time = 0; /* Unspecified */
/* RFC4861 Section 4.6.2 */
ra_opt_pref = (struct icmpv6_opt_prefix *) msgb_put(msg, sizeof(*ra_opt_pref));
ra_opt_pref->hdr.type = 3; /* RFC4861 4.6.2 */
ra_opt_pref->hdr.len = 4; /* RFC4861 4.6.2 */
ra_opt_pref->prefix_len = 64; /* only prefix length as per 3GPP */
/* The Prefix is contained in the Prefix Information Option of
* the Router Advertisements and shall have the A-flag set
* and the L-flag cleared */
ra_opt_pref->a = 1;
ra_opt_pref->l = 0;
ra_opt_pref->res = 0;
/* The lifetime of the prefix shall be set to infinity */
ra_opt_pref->valid_lifetime = htonl(GGSN_AdvValidLifetime);
ra_opt_pref->preferred_lifetime = htonl(GGSN_AdvPreferredLifetime);
ra_opt_pref->res2 = 0;
memcpy(ra_opt_pref->prefix, prefix, sizeof(ra_opt_pref->prefix));
/* checksum */
ra->hdr.csum = icmpv6_prepend_ip6hdr(msg, saddr, daddr);
return msg;
}
/* Validate an ICMPv6 router solicitation according to RFC4861 6.1.1 */
static bool icmpv6_validate_router_solicit(const uint8_t *pack, unsigned len)
{
const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
//const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + sizeof(*ip6h));
/* Hop limit field must have 255 */
if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_hlim != 255)
return false;
/* FIXME: ICMP checksum is valid */
/* ICMP length (derived from IP length) is 8 or more octets */
if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_plen < 8)
return false;
/* FIXME: All included options have a length > 0 */
/* FIXME: If IP source is unspecified, no source link-layer addr option */
return true;
}
/* Validate an ICMPv6 router advertisement according to RFC4861 6.1.2.
Returns pointer packet header on success, NULL otherwise. */
struct icmpv6_radv_hdr *icmpv6_validate_router_adv(const uint8_t *pack, unsigned len)
{
const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + sizeof(*ip6h));
/* ICMP length (derived from IP length) is 16 or more octets */
if (len < sizeof(*ip6h) + 16)
return NULL;
if (ic6h->type != 134) /* router advertismenet type */
return NULL;
/*Routers must use their link-local address */
if (!IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src))
return NULL;
/* Hop limit field must have 255 */
if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_hlim != 255)
return NULL;
/* ICMP Code is 0 */
if (ic6h->code != 0)
return NULL;
/* ICMP length (derived from IP length) is 16 or more octets */
if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_plen < 16)
return NULL;
/* FIXME: All included options have a length > 0 */
/* FIXME: If IP source is unspecified, no source link-layer addr option */
return (struct icmpv6_radv_hdr *)ic6h;
}
/* handle incoming packets to the all-routers multicast address */
int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp,
const struct in6_addr *pdp_prefix,
const struct in6_addr *own_ll_addr,
const uint8_t *pack, unsigned len)
{
const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + sizeof(*ip6h));
struct msgb *msg;
if (len < sizeof(*ip6h)) {
LOGP(DICMP6, LOGL_NOTICE, "Packet too short: %u bytes\n", len);
return -1;
}
/* we only treat ICMPv6 here */
if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_ICMPV6) {
LOGP(DICMP6, LOGL_DEBUG, "Ignoring non-ICMP to all-routers mcast\n");
return 0;
}
if (len < sizeof(*ip6h) + sizeof(*ic6h)) {
LOGP(DICMP6, LOGL_NOTICE, "Short ICMPv6 packet: %s\n", osmo_hexdump(pack, len));
return -1;
}
switch (ic6h->type) {
case 133: /* router solicitation */
if (ic6h->code != 0) {
LOGP(DICMP6, LOGL_NOTICE, "ICMPv6 type 133 but code %d\n", ic6h->code);
return -1;
}
if (!icmpv6_validate_router_solicit(pack, len)) {
LOGP(DICMP6, LOGL_NOTICE, "Invalid Router Solicitation: %s\n",
osmo_hexdump(pack, len));
return -1;
}
/* Send router advertisement from GGSN link-local
* address to MS link-local address, including prefix
* allocated to this PDP context */
msg = icmpv6_construct_ra(own_ll_addr, &ip6h->ip6_src, pdp_prefix);
/* Send the constructed RA to the MS */
gtp_data_req(gsn, pdp, msgb_data(msg), msgb_length(msg));
msgb_free(msg);
break;
default:
LOGP(DICMP6, LOGL_DEBUG, "Unknown ICMPv6 type %u\n", ic6h->type);
break;
}
return 0;
}

100
lib/icmpv6.h Normal file
View File

@@ -0,0 +1,100 @@
#pragma once
#include <stdbool.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/endian.h>
#include "../gtp/gtp.h"
#include "../gtp/pdp.h"
#define ICMPv6_OPT_TYPE_PREFIX_INFO 0x03
#define foreach_icmpv6_opt(icmpv6_pkt, icmpv6_len, opt_hdr) \
for (opt_hdr = (struct icmpv6_opt_hdr *)(icmpv6_pkt)->options; \
(uint8_t*)(opt_hdr) + sizeof(struct icmpv6_opt_hdr) <= (((uint8_t*)(icmpv6_pkt)) + (icmpv6_len)); \
opt_hdr = (struct icmpv6_opt_hdr*)((uint8_t*)(opt_hdr) + (opt_hdr)->len) \
)
struct icmpv6_hdr {
uint8_t type;
uint8_t code;
uint16_t csum;
} __attribute__ ((packed));
struct icmpv6_echo_hdr {
struct icmpv6_hdr hdr;
uint16_t ident; /* Identifier */
uint16_t seq; /* Sequence number */
uint8_t data[0]; /* Data */
} __attribute__ ((packed));
/* RFC4861 Section 4.1 */
struct icmpv6_rsol_hdr {
struct icmpv6_hdr hdr;
uint32_t reserved;
uint8_t options[0];
} __attribute__ ((packed));
/* RFC4861 Section 4.2 */
struct icmpv6_radv_hdr {
struct icmpv6_hdr hdr;
uint8_t cur_ho_limit;
#if OSMO_IS_LITTLE_ENDIAN
uint8_t res:6,
m:1,
o:1;
#else
uint8_t m:1,
o:1,
res:6;
#endif
uint16_t router_lifetime;
uint32_t reachable_time;
uint32_t retrans_timer;
uint8_t options[0];
} __attribute__ ((packed));
/* RFC4861 Section 4.6 */
struct icmpv6_opt_hdr {
uint8_t type;
/* length in units of 8 octets, including type+len! */
uint8_t len;
uint8_t data[0];
} __attribute__ ((packed));
/* RFC4861 Section 4.6.2 */
struct icmpv6_opt_prefix {
struct icmpv6_opt_hdr hdr;
uint8_t prefix_len;
#if OSMO_IS_LITTLE_ENDIAN
uint8_t res:6,
a:1,
l:1;
#else
uint8_t l:1,
a:1,
res:6;
#endif
uint32_t valid_lifetime;
uint32_t preferred_lifetime;
uint32_t res2;
uint8_t prefix[16];
} __attribute__ ((packed));
uint16_t icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr *saddr,
const struct in6_addr *daddr);
struct msgb *icmpv6_construct_rs(const struct in6_addr *saddr);
int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp,
const struct in6_addr *pdp_prefix,
const struct in6_addr *own_ll_addr,
const uint8_t *pack, unsigned len);
struct icmpv6_radv_hdr *icmpv6_validate_router_adv(const uint8_t *pack, unsigned len);
/* RFC3307 link-local scope multicast address */
extern const struct in6_addr all_router_mcast_addr;

377
lib/in46_addr.c Normal file
View File

@@ -0,0 +1,377 @@
/*
* IPv4/v6 address functions.
* Copyright (C) 2017 by Harald Welte <laforge@gnumonks.org>
*
* 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.
*
*/
#include "../lib/in46_addr.h"
#include "../gtp/pdp.h"
#include <osmocom/core/utils.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
/*! Return the address family of given \reff in46_addr argument */
int in46a_to_af(const struct in46_addr *in)
{
switch (in->len) {
case 4:
return AF_INET;
case 8:
case 16:
return AF_INET6;
default:
OSMO_ASSERT(0);
return -1;
}
}
/*! Convert \ref in46_addr to sockaddr_storage */
int in46a_to_sas(struct sockaddr_storage *out, const struct in46_addr *in)
{
struct sockaddr_in *sin = (struct sockaddr_in *)out;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)out;
switch (in->len) {
case 4:
sin->sin_family = AF_INET;
sin->sin_addr = in->v4;
break;
case 16:
sin6->sin6_family = AF_INET6;
sin6->sin6_addr = in->v6;
break;
default:
OSMO_ASSERT(0);
return -1;
}
return 0;
}
/*! Convenience wrapper around inet_ntop() for in46_addr.
* \param[in] in the in46_addr to print
* \param[out] dst destination buffer where string representation of the address is stored
* \param[out] dst_size size dst. Usually it should be at least INET6_ADDRSTRLEN.
* \return address of dst on success, NULL on error */
const char *in46a_ntop(const struct in46_addr *in, char *dst, socklen_t dst_size)
{
int af;
if (!in || in->len == 0) {
strncpy(dst, "UNDEFINED", dst_size);
return dst;
}
af = in46a_to_af(in);
if (af < 0)
return NULL;
return inet_ntop(af, (const void *) &in->v4, dst, dst_size);
}
/* like inet_ntoa() */
const char *in46a_ntoa(const struct in46_addr *in46)
{
static char addrstr_buf[256];
if (in46a_ntop(in46, addrstr_buf, sizeof(addrstr_buf)) < 0)
return "INVALID";
else
return addrstr_buf;
}
const char *in46p_ntoa(const struct in46_prefix *in46p)
{
static char addrstr_buf[256];
snprintf(addrstr_buf, sizeof(addrstr_buf), "%s/%u", in46a_ntoa(&in46p->addr), in46p->prefixlen);
return addrstr_buf;
}
/*! Determine if two in46_addr are equal or not
* \returns 1 in case they are equal; 0 otherwise */
int in46a_equal(const struct in46_addr *a, const struct in46_addr *b)
{
if (a->len == b->len && !memcmp(&a->v6, &b->v6, a->len))
return 1;
else
return 0;
}
/*! Determine if two in46_addr prefix are equal or not
* The prefix length is determined by the shortest of the prefixes of a and b
* \returns 1 in case the common prefix are equal; 0 otherwise */
int in46a_prefix_equal(const struct in46_addr *a, const struct in46_addr *b)
{
unsigned int len;
if (a->len > b->len)
len = b->len;
else
len = a->len;
if (!memcmp(&a->v6, &b->v6, len))
return 1;
else
return 0;
}
/*! Match if IPv6 addr1 + addr2 are within same \a mask */
static int ipv6_within_mask(const struct in6_addr *addr1, const struct in6_addr *addr2,
const struct in6_addr *mask)
{
struct in6_addr masked = *addr2;
#if defined(__linux__)
masked.s6_addr32[0] &= mask->s6_addr32[0];
masked.s6_addr32[1] &= mask->s6_addr32[1];
masked.s6_addr32[2] &= mask->s6_addr32[2];
masked.s6_addr32[3] &= mask->s6_addr32[3];
#else
masked.__u6_addr.__u6_addr32[0] &= mask->__u6_addr.__u6_addr32[0];
masked.__u6_addr.__u6_addr32[1] &= mask->__u6_addr.__u6_addr32[1];
masked.__u6_addr.__u6_addr32[2] &= mask->__u6_addr.__u6_addr32[2];
masked.__u6_addr.__u6_addr32[3] &= mask->__u6_addr.__u6_addr32[3];
#endif
if (!memcmp(addr1, &masked, sizeof(struct in6_addr)))
return 1;
else
return 0;
}
/*! Create an IPv6 netmask from the given prefix length */
static void create_ipv6_netmask(struct in6_addr *netmask, int prefixlen)
{
uint32_t *p_netmask;
memset(netmask, 0, sizeof(struct in6_addr));
if (prefixlen < 0)
prefixlen = 0;
else if (128 < prefixlen)
prefixlen = 128;
#if defined(__linux__)
p_netmask = &netmask->s6_addr32[0];
#else
p_netmask = &netmask->__u6_addr.__u6_addr32[0];
#endif
while (32 < prefixlen) {
*p_netmask = 0xffffffff;
p_netmask++;
prefixlen -= 32;
}
if (prefixlen != 0) {
*p_netmask = htonl(0xFFFFFFFF << (32 - prefixlen));
}
}
/*! Determine if given \a addr is within given \a net + \a prefixlen
* Builds the netmask from \a net + \a prefixlen and matches it to \a addr
* \returns 1 in case of a match, 0 otherwise */
int in46a_within_mask(const struct in46_addr *addr, const struct in46_addr *net, size_t prefixlen)
{
struct in_addr netmask;
struct in6_addr netmask6;
if (addr->len != net->len)
return 0;
switch (addr->len) {
case 4:
netmask.s_addr = htonl(0xFFFFFFFF << (32 - prefixlen));
if ((addr->v4.s_addr & netmask.s_addr) == net->v4.s_addr)
return 1;
else
return 0;
case 16:
create_ipv6_netmask(&netmask6, prefixlen);
return ipv6_within_mask(&addr->v6, &net->v6, &netmask6);
default:
OSMO_ASSERT(0);
return 0;
}
}
static unsigned int ipv4_netmasklen(const struct in_addr *netmask)
{
uint32_t bits = netmask->s_addr;
uint8_t *b = (uint8_t*) &bits;
unsigned int i, prefix = 0;
for (i = 0; i < 4; i++) {
while (b[i] & 0x80) {
prefix++;
b[i] = b[i] << 1;
}
}
return prefix;
}
static unsigned int ipv6_netmasklen(const struct in6_addr *netmask)
{
#if defined(__linux__)
#define ADDRFIELD(i) s6_addr32[i]
#else
#define ADDRFIELD(i) __u6_addr.__u6_addr32[i]
#endif
unsigned int i, j, prefix = 0;
for (j = 0; j < 4; j++) {
uint32_t bits = netmask->ADDRFIELD(j);
uint8_t *b = (uint8_t*) &bits;
for (i = 0; i < 4; i++) {
while (b[i] & 0x80) {
prefix++;
b[i] = b[i] << 1;
}
}
}
#undef ADDRFIELD
return prefix;
}
/*! Convert netmask to prefix length representation
* \param[in] netmask in46_addr containing a netmask (consecutive list of 1-bit followed by consecutive list of 0-bit)
* \returns prefix length representation of the netmask (count of 1-bit from the start of the netmask)
*/
unsigned int in46a_netmasklen(const struct in46_addr *netmask)
{
switch (netmask->len) {
case 4:
return ipv4_netmasklen(&netmask->v4);
case 16:
return ipv6_netmasklen(&netmask->v6);
default:
OSMO_ASSERT(0);
return 0;
}
}
/*! Convert given array of in46_addr to PDP End User Address
* \param[in] src Array containing 1 or 2 in46_addr
* \param[out] eua End User Address structure to fill
* \returns 0 on success; negative on error
*
* In case size is 2, this function expects to find exactly one IPv4 and one
* IPv6 addresses in src. */
int in46a_to_eua(const struct in46_addr *src, unsigned int size, struct ul66_t *eua)
{
const struct in46_addr *src_v4, *src_v6;
if (size == 1) {
switch (src->len) {
case 4:
eua->l = 6;
eua->v[0] = PDP_EUA_ORG_IETF;
eua->v[1] = PDP_EUA_TYPE_v4;
memcpy(&eua->v[2], &src->v4, 4); /* Copy a 4 byte address */
break;
case 8:
case 16:
eua->l = 18;
eua->v[0] = PDP_EUA_ORG_IETF;
eua->v[1] = PDP_EUA_TYPE_v6;
memcpy(&eua->v[2], &src->v6, 16); /* Copy a 16 byte address */
break;
default:
OSMO_ASSERT(0);
return -1;
}
return 0;
}
if (src[0].len == src[1].len)
return -1; /* we should have a v4 and a v6 address */
src_v4 = (src[0].len == 4) ? &src[0] : &src[1];
src_v6 = (src[0].len == 4) ? &src[1] : &src[0];
eua->l = 22;
eua->v[0] = PDP_EUA_ORG_IETF;
eua->v[1] = PDP_EUA_TYPE_v4v6;
memcpy(&eua->v[2], &src_v4->v4, 4);
memcpy(&eua->v[6], &src_v6->v6, 16);
return 0;
}
/*! Convert given PDP End User Address to an array of in46_addr
* \param[in] eua End User Address structure to parse
* \param[out] dst Array containing 2 in46_addr
* \returns number of parsed addresses (1 or 2) on success; negative on error
*
* This function expects to receive an End User Address struct together with an
* array of 2 zeroed in46_addr structs. The in46_addr structs are filled in
* order, hence if the function returns 1 the parsed address will be stored in
* the first struct and the second one will be left intact. If 2 is returned, it
* is guaranteed that one of them is an IPv4 and the other one is an IPv6, but
* the order in which they are presented is not specified and must be
* discovered for instance by checking the len field of each address.
*/
int in46a_from_eua(const struct ul66_t *eua, struct in46_addr *dst)
{
if (eua->l < 2)
goto default_to_dyn_v4;
if (eua->v[0] != 0xf1)
return -1;
switch (eua->v[1]) {
case PDP_EUA_TYPE_v4:
dst->len = 4;
if (eua->l >= 6)
memcpy(&dst->v4, &eua->v[2], 4); /* Copy a 4 byte address */
else
dst->v4.s_addr = 0;
return 1;
case PDP_EUA_TYPE_v6:
dst->len = 16;
if (eua->l >= 18)
memcpy(&dst->v6, &eua->v[2], 16); /* Copy a 16 byte address */
else
memset(&dst->v6, 0, 16);
return 1;
case PDP_EUA_TYPE_v4v6:
/* 3GPP TS 29.060, section 7.7.27 */
switch (eua->l) {
case 2: /* v4 & v6 dynamic */
dst[0].v4.s_addr = 0;
memset(&dst[1].v6, 0, 16);
break;
case 6: /* v4 static, v6 dynamic */
memcpy(&dst[0].v4, &eua->v[2], 4);
memset(&dst[1].v6, 0, 16);
break;
case 18: /* v4 dynamic, v6 static */
dst[0].v4.s_addr = 0;
memcpy(&dst[1].v6, &eua->v[2], 16);
break;
case 22: /* v4 & v6 static */
memcpy(&dst[0].v4, &eua->v[2], 4);
memcpy(&dst[1].v6, &eua->v[6], 16);
break;
default:
return -1;
}
dst[0].len = 4;
dst[1].len = 16;
return 2;
default:
return -1;
}
default_to_dyn_v4:
/* assume dynamic IPv4 by default */
dst->len = 4;
dst->v4.s_addr = 0;
return 1;
}

41
lib/in46_addr.h Normal file
View File

@@ -0,0 +1,41 @@
#pragma once
#include <stdint.h>
#include <netinet/in.h>
#include "../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 */
struct in46_addr {
uint8_t len;
union {
struct in_addr v4;
struct in6_addr v6;
};
};
struct in46_prefix {
struct in46_addr addr;
uint8_t prefixlen;
};
extern int in46a_to_af(const struct in46_addr *in);
extern int in46a_to_sas(struct sockaddr_storage *out, const struct in46_addr *in);
extern const char *in46a_ntop(const struct in46_addr *in, char *dst, socklen_t dst_size);
extern const char *in46a_ntoa(const struct in46_addr *in46);
extern const char *in46p_ntoa(const struct in46_prefix *in46p);
extern int in46a_equal(const struct in46_addr *a, const struct in46_addr *b);
extern int in46a_prefix_equal(const struct in46_addr *a, const struct in46_addr *b);
extern int in46a_within_mask(const struct in46_addr *addr, const struct in46_addr *net, size_t prefixlen);
unsigned int in46a_netmasklen(const struct in46_addr *netmask);
int in46a_to_eua(const struct in46_addr *src, unsigned int size, struct ul66_t *eua);
int in46a_from_eua(const struct ul66_t *eua, struct in46_addr *dst);
static inline bool in46a_is_v6(const struct in46_addr *addr) {
return addr->len == 8 || addr->len == 16;
}
static inline bool in46a_is_v4(const struct in46_addr *addr) {
return addr->len == sizeof(struct in_addr);
}

View File

@@ -1,12 +1,13 @@
/*
* IP address pool functions.
* Copyright (C) 2003, 2004 Mondru AB.
* Copyright (C) 2017 by Harald Welte <laforge@gnumonks.org>
*
* 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.
*
*
*/
#include <sys/types.h>
@@ -16,6 +17,7 @@
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "syserr.h"
#include "ippool.h"
#include "lookup.h"
@@ -24,20 +26,21 @@ int ippool_printaddr(struct ippool_t *this)
{
unsigned int n;
printf("ippool_printaddr\n");
printf("Firstdyn %d\n", this->firstdyn - this->member);
printf("Lastdyn %d\n", this->lastdyn - this->member);
printf("Firststat %d\n", this->firststat - this->member);
printf("Laststat %d\n", this->laststat - this->member);
printf("Listsize %d\n", this->listsize);
printf("Firstdyn %td\n", this->firstdyn - this->member);
printf("Lastdyn %td\n", this->lastdyn - this->member);
printf("Firststat %td\n", this->firststat - this->member);
printf("Laststat %td\n", this->laststat - this->member);
printf("Listsize %u\n", this->listsize);
for (n = 0; n < this->listsize; n++) {
printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
char s[256];
in46a_ntop(&this->member[n].addr, s, sizeof(s));
printf("Unit %d inuse %d prev %td next %td addr %s\n",
n,
this->member[n].inuse,
this->member[n].prev - this->member,
this->member[n].next - this->member,
inet_ntoa(this->member[n].addr),
this->member[n].addr.s_addr);
s);
}
return 0;
}
@@ -49,7 +52,7 @@ int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member)
struct ippoolm_t *p_prev = NULL;
/* Insert into hash table */
hash = ippool_hash4(&member->addr) & this->hashmask;
hash = ippool_hash(&member->addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash)
p_prev = p;
if (!p_prev)
@@ -66,7 +69,7 @@ int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member)
struct ippoolm_t *p_prev = NULL;
/* Find in hash table */
hash = ippool_hash4(&member->addr) & this->hashmask;
hash = ippool_hash(&member->addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if (p == member) {
break;
@@ -88,129 +91,156 @@ int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member)
return 0;
}
unsigned long int ippool_hash4(struct in_addr *addr)
static unsigned long int ippool_hash4(struct in_addr *addr)
{
return lookup((unsigned char *)&addr->s_addr, sizeof(addr->s_addr), 0);
}
#ifndef IPPOOL_NOIP6
unsigned long int ippool_hash6(struct in6_addr *addr)
static unsigned long int ippool_hash6(struct in6_addr *addr, unsigned int len)
{
return lookup((unsigned char *)addr->u6_addr8, sizeof(addr->u6_addr8),
0);
/* TODO: Review hash spread for IPv6 */
return lookup((unsigned char *)addr->s6_addr, len, 0);
}
unsigned long int ippool_hash(struct in46_addr *addr)
{
if (addr->len == 4)
return ippool_hash4(&addr->v4);
else
return ippool_hash6(&addr->v6, addr->len);
}
#endif
/* Get IP address and mask */
int ippool_aton(struct in_addr *addr, struct in_addr *mask,
char *pool, int number)
int ippool_aton(struct in46_addr *addr, size_t *prefixlen, const char *pool_in, int number)
{
struct addrinfo *ai;
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_DGRAM,
.ai_flags = 0,
.ai_protocol = 0
};
char pool[strlen(pool_in)+1];
/* Parse only first instance of network for now */
/* Eventually "number" will indicate the token which we want to parse */
strcpy(pool, pool_in);
unsigned int a1, a2, a3, a4;
unsigned int m1, m2, m3, m4;
int c;
int m;
int masklog;
int err;
c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
&a1, &a2, &a3, &a4, &m1, &m2, &m3, &m4);
switch (c) {
case 4:
mask->s_addr = 0xffffffff;
break;
case 5:
if (m1 > 32) {
SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
return -1; /* Invalid mask */
/* Find '/' and point to first char after it */
char *prefixlen_str = strchr(pool, '/');
if (prefixlen_str) {
*prefixlen_str = '\0';
prefixlen_str++;
if (*prefixlen_str == '\0') {
SYS_ERR(DIP, LOGL_ERROR, 0, "Empty prefix length specified");
return -1;
}
mask->s_addr = htonl(0xffffffff << (32 - m1));
break;
case 8:
if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
return -1; /* Wrong mask format */
}
m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
for (masklog = 0; ((1 << masklog) < ((~m) + 1)); masklog++) ;
if (((~m) + 1) != (1 << masklog)) {
SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
return -1; /* Wrong mask format (not all ones followed by all zeros) */
}
mask->s_addr = htonl(m);
break;
default:
SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
return -1; /* Invalid mask */
}
if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Wrong IP address format");
/* convert address */
if ((err = getaddrinfo(pool, NULL, &hints, &ai))) {
SYS_ERR(DIP, LOGL_ERROR, 0, "Bad address");
return -1;
} else
addr->s_addr =
htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
}
/* Copy address, set lengths */
if (ai->ai_family == AF_INET) {
*prefixlen = 32;
addr->len = sizeof(struct in_addr);
addr->v4 = ((struct sockaddr_in*)ai->ai_addr)->sin_addr;
} else {
*prefixlen = 128;
addr->len = sizeof(struct in6_addr);
addr->v6 = ((struct sockaddr_in6*)ai->ai_addr)->sin6_addr;
}
freeaddrinfo(ai);
/* parse prefixlen */
if (prefixlen_str) {
char *e;
*prefixlen = strtol(prefixlen_str, &e, 10);
if (*e != '\0') {
SYS_ERR(DIP, LOGL_ERROR, 0, "Prefixlen is not an int");
return -1;
}
}
if (*prefixlen > (addr->len * 8)) {
SYS_ERR(DIP, LOGL_ERROR, 0, "Perfixlen too big");
return -1;
}
return 0;
}
/* Increase IPv4/IPv6 address by 1 */
void in46a_inc(struct in46_addr *addr)
{
size_t addrlen;
uint8_t *a = (uint8_t *)&addr->v6;
for (addrlen = addr->len; addrlen > 0; addrlen--) {
if (++a[addrlen-1])
break;
}
}
static bool addr_in_prefix_list(struct in46_addr *addr, struct in46_prefix *list, size_t list_size)
{
int i;
for (i = 0; i < list_size; i++) {
if (in46a_prefix_equal(addr, &list[i].addr))
return true;
}
return false;
}
/* Create new address pool */
int ippool_new(struct ippool_t **this, char *dyn, char *stat,
int allowdyn, int allowstat, int flags)
int ippool_new(struct ippool_t **this, const struct in46_prefix *dyn, const struct in46_prefix *stat,
int flags, struct in46_prefix *blacklist, size_t blacklist_size)
{
/* Parse only first instance of pool for now */
int i;
struct in_addr addr;
struct in_addr mask;
struct in_addr stataddr;
struct in_addr statmask;
unsigned int m;
struct in46_addr addr = { 0 };
size_t addrprefixlen;
struct in46_addr stataddr;
size_t stataddrprefixlen;
int listsize;
int dynsize;
unsigned int statsize;
if (!allowdyn) {
if (!dyn || dyn->addr.len == 0) {
dynsize = 0;
} else {
if (ippool_aton(&addr, &mask, dyn, 0)) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Failed to parse dynamic pool");
return -1;
}
addr = dyn->addr;
addrprefixlen = dyn->prefixlen;
/* we want to work with /64 prefixes, i.e. allocate /64 prefixes rather
* than /128 (single IPv6 addresses) */
if (addr.len == sizeof(struct in6_addr))
addr.len = 64/8;
/* Set IPPOOL_NONETWORK if IPPOOL_NOGATEWAY is set */
if (flags & IPPOOL_NOGATEWAY) {
flags |= IPPOOL_NONETWORK;
}
m = ntohl(mask.s_addr);
dynsize = ((~m) + 1);
dynsize = (1 << (addr.len*8 - addrprefixlen));
if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
dynsize--;
if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
dynsize--;
if (flags & IPPOOL_NOBROADCAST) /* Exclude broadcast address from pool */
dynsize--;
/* Exclude included blacklist addresses from pool */
for (i = 0; i < blacklist_size; i++) {
if (in46a_within_mask(&blacklist[i].addr, &addr, addrprefixlen))
dynsize--;
}
}
if (!allowstat) {
if (!stat || stat->addr.len == 0) {
statsize = 0;
stataddr.s_addr = 0;
statmask.s_addr = 0;
stataddr.len = 0;
stataddrprefixlen = 0;
} else {
if (ippool_aton(&stataddr, &statmask, stat, 0)) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Failed to parse static range");
return -1;
}
stataddr = stat->addr;
stataddrprefixlen = stat->prefixlen;
m = ntohl(statmask.s_addr);
statsize = ((~m) + 1);
statsize = (1 << (stataddr.len*8 - stataddrprefixlen));
if (statsize > IPPOOL_STATSIZE)
statsize = IPPOOL_STATSIZE;
}
@@ -223,10 +253,11 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
return -1;
}
(*this)->allowdyn = allowdyn;
(*this)->allowstat = allowstat;
(*this)->stataddr = stataddr;
(*this)->statmask = statmask;
(*this)->allowdyn = dyn ? 1 : 0;
(*this)->allowstat = stat ? 1 : 0;
if (stataddr.len > 0)
(*this)->stataddr = stataddr;
(*this)->stataddrprefixlen = stataddrprefixlen;
(*this)->listsize += listsize;
if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))) {
@@ -245,9 +276,8 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
(*this)->hashmask = (*this)->hashsize - 1;
/* Allocate hash table */
if (!
((*this)->hash =
calloc(sizeof(struct ippoolm_t), (*this)->hashsize))) {
(*this)->hash = calloc((*this)->hashsize, sizeof(struct ippoolm_t *));
if (!(*this)->hash) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Failed to allocate memory for hash members in ippool");
return -1;
@@ -255,19 +285,22 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
(*this)->firstdyn = NULL;
(*this)->lastdyn = NULL;
if (flags & IPPOOL_NONETWORK) {
in46a_inc(&addr);
}
for (i = 0; i < dynsize; i++) {
if (flags & IPPOOL_NOGATEWAY)
(*this)->member[i].addr.s_addr =
htonl(ntohl(addr.s_addr) + i + 2);
else if (flags & IPPOOL_NONETWORK)
(*this)->member[i].addr.s_addr =
htonl(ntohl(addr.s_addr) + i + 1);
else
(*this)->member[i].addr.s_addr =
htonl(ntohl(addr.s_addr) + i);
if (addr_in_prefix_list(&addr, blacklist, blacklist_size)) {
SYS_ERR(DIP, LOGL_DEBUG, 0,
"addr blacklisted from pool: %s", in46a_ntoa(&addr));
in46a_inc(&addr);
i--;
continue;
}
(*this)->member[i].addr = addr;
in46a_inc(&addr);
(*this)->member[i].inuse = 0;
(*this)->member[i].pool = *this;
/* Insert into list of unused */
(*this)->member[i].prev = (*this)->lastdyn;
@@ -285,9 +318,10 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
(*this)->firststat = NULL;
(*this)->laststat = NULL;
for (i = dynsize; i < listsize; i++) {
(*this)->member[i].addr.s_addr = 0;
struct in46_addr *i6al = &(*this)->member[i].addr;
memset(i6al, 0, sizeof(*i6al));
(*this)->member[i].inuse = 0;
(*this)->member[i].pool = *this;
/* Insert into list of unused */
(*this)->member[i].prev = (*this)->laststat;
@@ -316,15 +350,15 @@ int ippool_free(struct ippool_t *this)
/* Find an IP address in the pool */
int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
struct in_addr *addr)
struct in46_addr *addr)
{
struct ippoolm_t *p;
uint32_t hash;
/* Find in hash table */
hash = ippool_hash4(addr) & this->hashmask;
hash = ippool_hash(addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
if (in46a_prefix_equal(&p->addr, addr)) {
if (member)
*member = p;
return 0;
@@ -344,14 +378,14 @@ int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
* address space.
**/
int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
struct in_addr *addr, int statip)
struct in46_addr *addr, int statip)
{
struct ippoolm_t *p;
struct ippoolm_t *p2 = NULL;
uint32_t hash;
/* If static:
* Look in dynaddr.
* Look in dynaddr.
* If found remove from firstdyn/lastdyn linked list.
* Else allocate from stataddr.
* Remove from firststat/laststat linked list.
@@ -365,33 +399,39 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
if (0)
(void)ippool_printaddr(this);
int specified = 0;
if (addr) {
if (addr->len == 4 && addr->v4.s_addr)
specified = 1;
if (addr->len == 16 && !IN6_IS_ADDR_UNSPECIFIED(&addr->v6))
specified = 1;
}
/* First check to see if this type of address is allowed */
if ((addr) && (addr->s_addr) && statip) { /* IP address given */
if (specified && statip) { /* IP address given */
if (!this->allowstat) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Static IP address not allowed");
return -1;
return -GTPCAUSE_NOT_SUPPORTED;
}
if ((addr->s_addr & this->statmask.s_addr) !=
this->stataddr.s_addr) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Static out of range");
if (!in46a_within_mask(addr, &this->stataddr, this->stataddrprefixlen)) {
SYS_ERR(DIP, LOGL_ERROR, 0, "Static out of range");
return -1;
}
} else {
if (!this->allowdyn) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Dynamic IP address not allowed");
return -1;
return -GTPCAUSE_NOT_SUPPORTED;
}
}
/* If IP address given try to find it in dynamic address pool */
if ((addr) && (addr->s_addr)) { /* IP address given */
if (specified) { /* IP address given */
/* Find in hash table */
hash = ippool_hash4(addr) & this->hashmask;
hash = ippool_hash(addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if ((p->addr.s_addr == addr->s_addr)) {
if (in46a_prefix_equal(&p->addr, addr)) {
p2 = p;
break;
}
@@ -408,7 +448,7 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
if (!this->firstdyn) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"No more IP addresses available");
return -1;
return -GTPCAUSE_ADDR_OCCUPIED;
} else
p2 = this->firstdyn;
}
@@ -417,7 +457,12 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
if (p2->inuse) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"IP address allready in use");
return -1; /* Allready in use / Should not happen */
return -GTPCAUSE_SYS_FAIL; /* Allready in use / Should not happen */
}
if (p2->addr.len != addr->len && !(addr->len == 16 && p2->addr.len == 8)) {
SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
return -GTPCAUSE_UNKNOWN_PDP;
}
/* Remove from linked list of free dynamic addresses */
@@ -442,14 +487,19 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
/* It was not possible to allocate from dynamic address pool */
/* Try to allocate from static address space */
if ((addr) && (addr->s_addr) && (statip)) { /* IP address given */
if (specified && (statip)) { /* IP address given */
if (!this->firststat) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"No more IP addresses available");
return -1; /* No more available */
return -GTPCAUSE_ADDR_OCCUPIED; /* No more available */
} else
p2 = this->firststat;
if (p2->addr.len != addr->len) {
SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
return -GTPCAUSE_UNKNOWN_PDP;
}
/* Remove from linked list of free static addresses */
if (p2->prev)
p2->prev->next = p2->next;
@@ -462,7 +512,15 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
p2->next = NULL;
p2->prev = NULL;
p2->inuse = 2; /* Static address in use */
memcpy(&p2->addr, addr, sizeof(addr));
/* p2->addr.len and addr->len already match (see above). */
if (p2->addr.len == sizeof(struct in_addr))
p2->addr.v4 = addr->v4;
else if (p2->addr.len == sizeof(struct in6_addr))
p2->addr.v6 = addr->v6;
else {
SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
return -GTPCAUSE_UNKNOWN_PDP;
}
*member = p2;
(void)ippool_hashadd(this, *member);
if (0)
@@ -472,7 +530,7 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
SYS_ERR(DIP, LOGL_ERROR, 0,
"Could not allocate IP address");
return -1; /* Should never get here. TODO: Bad code */
return -GTPCAUSE_SYS_FAIL; /* Should never get here. TODO: Bad code */
}
int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
@@ -518,7 +576,7 @@ int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
this->laststat = member;
member->inuse = 0;
member->addr.s_addr = 0;
memset(&member->addr, 0, sizeof(member->addr));
member->peer = NULL;
member->nexthash = NULL;
if (0)
@@ -530,9 +588,3 @@ int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
return -1;
}
}
#ifndef IPPOOL_NOIP6
extern unsigned long int ippool_hash6(struct in6_addr *addr);
extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
#endif

View File

@@ -1,17 +1,20 @@
/*
/*
* IP address pool functions.
* Copyright (C) 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 _IPPOOL_H
#define _IPPOOL_H
#include "../lib/in46_addr.h"
#include "../gtp/gtp.h"
/* Assuming that the address space is fragmented we need a hash table
in order to return the addresses.
@@ -20,17 +23,14 @@
When initialising a new address pool it should be possible to pass
a string of CIDR format networks: "10.0.0.0/24 10.15.0.0/20" would
translate to 256 addresses starting at 10.0.0.0 and 1024 addresses
starting at 10.15.0.0.
starting at 10.15.0.0.
The above also applies to IPv6 which can be specified as described
in RFC2373.
*/
#define IPPOOL_NOIP6
#define IPPOOL_NONETWORK 0x01
#define IPPOOL_NOBROADCAST 0x02
#define IPPOOL_NOGATEWAY 0x04
#define IPPOOL_STATSIZE 0x10000
@@ -40,8 +40,8 @@ struct ippool_t {
unsigned int listsize; /* Total number of addresses */
int allowdyn; /* Allow dynamic IP address allocation */
int allowstat; /* Allow static IP address allocation */
struct in_addr stataddr; /* Static address range network address */
struct in_addr statmask; /* Static address range network mask */
struct in46_addr stataddr; /* Static address range network address */
size_t stataddrprefixlen; /* IPv6 prefix length of stataddr */
struct ippoolm_t *member; /* Listsize array of members */
unsigned int hashsize; /* Size of hash table */
int hashlog; /* Log2 size of hash table */
@@ -54,11 +54,8 @@ struct ippool_t {
};
struct ippoolm_t {
#ifndef IPPOOL_NOIP6
struct in6_addr addr; /* IP address of this member */
#else
struct in_addr addr; /* IP address of this member */
#endif
struct in46_addr addr; /* IP address of this member */
struct ippool_t *pool; /* Pool to which we belong */
int inuse; /* 0=available; 1= dynamic; 2 = static */
struct ippoolm_t *nexthash; /* Linked list part of hash table */
struct ippoolm_t *prev, *next; /* Linked list of free dynamic or static */
@@ -70,35 +67,32 @@ struct ippoolm_t {
bytes for each address. */
/* Hash an IP address using code based on Bob Jenkins lookupa */
extern unsigned long int ippool_hash4(struct in_addr *addr);
extern unsigned long int ippool_hash(struct in46_addr *addr);
/* Create new address pool */
extern int ippool_new(struct ippool_t **this, char *dyn, char *stat,
int allowdyn, int allowstat, int flags);
extern int ippool_new(struct ippool_t **this, const struct in46_prefix *dyn,
const struct in46_prefix *stat, int flags,
struct in46_prefix *blacklist, size_t blacklist_size);
/* Delete existing address pool */
extern int ippool_free(struct ippool_t *this);
/* Find an IP address in the pool */
extern int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
struct in_addr *addr);
struct in46_addr *addr);
/* Get an IP address. If addr = 0.0.0.0 get a dynamic IP address. Otherwise
check to see if the given address is available */
extern int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
struct in_addr *addr, int statip);
struct in46_addr *addr, int statip);
/* Return a previously allocated IP address */
extern int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member);
/* Get net and mask based on ascii string */
extern int ippool_aton(struct in_addr *addr, struct in_addr *mask,
char *pool, int number);
int ippool_aton(struct in46_addr *addr, size_t *prefixlen, const char *pool, int number);
#ifndef IPPOOL_NOIP6
extern unsigned long int ippool_hash6(struct in6_addr *addr);
extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
#endif
/* Increase IPv4/IPv6 address by 1 */
extern void in46a_inc(struct in46_addr *addr);
#endif /* !_IPPOOL_H */

View File

@@ -37,7 +37,6 @@ register unsigned long int level; /* the previous hash, or an arbitrary value */
}
typedef unsigned long int ub4; /* unsigned 4-byte quantities */
typedef unsigned char ub1; /* unsigned 1-byte quantities */
register unsigned long int a, b, c, len;
/* Set up the internal state */

792
lib/netdev.c Normal file
View File

@@ -0,0 +1,792 @@
/*
* TUN interface functions.
* Copyright (C) 2002, 2003, 2004 Mondru AB.
* Copyright (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
*
* 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.
*
*/
/*
* netdev.c: Contains generic network device related functionality.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <errno.h>
#include <net/route.h>
#include <net/if.h>
#if defined(__linux__)
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#elif defined (__FreeBSD__)
#include <net/if_var.h>
#include <netinet/in_var.h>
#elif defined (__APPLE__)
#include <net/if.h>
#else
#error "Unknown platform!"
#endif
#include "netdev.h"
#include "syserr.h"
#if defined(__linux__)
#include <linux/ipv6.h>
static int netdev_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, int dlen)
{
int len = RTA_LENGTH(dlen);
int alen = NLMSG_ALIGN(n->nlmsg_len);
struct rtattr *rta = (struct rtattr *)(((void *)n) + alen);
if (alen + len > nsize)
return -1;
rta->rta_len = len;
rta->rta_type = type;
memcpy(RTA_DATA(rta), d, dlen);
n->nlmsg_len = alen + len;
return 0;
}
#endif
static int netdev_sifflags(const char *devname, int flags)
{
struct ifreq ifr;
int fd;
memset(&ifr, '\0', sizeof(ifr));
ifr.ifr_flags = flags;
strncpy(ifr.ifr_name, devname, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
if (ioctl(fd, SIOCSIFFLAGS, &ifr)) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCSIFFLAGS) failed");
close(fd);
return -1;
}
close(fd);
return 0;
}
int netdev_setaddr4(const char *devname, struct in_addr *addr,
struct in_addr *dstaddr, struct in_addr *netmask)
{
struct ifreq ifr;
int fd;
memset(&ifr, '\0', sizeof(ifr));
ifr.ifr_addr.sa_family = AF_INET;
ifr.ifr_dstaddr.sa_family = AF_INET;
#if defined(__linux__)
ifr.ifr_netmask.sa_family = AF_INET;
#elif defined(__FreeBSD__) || defined (__APPLE__)
((struct sockaddr_in *)&ifr.ifr_addr)->sin_len =
sizeof(struct sockaddr_in);
((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_len =
sizeof(struct sockaddr_in);
#endif
strncpy(ifr.ifr_name, devname, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
/* Create a channel to the NET kernel. */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
if (addr) { /* Set the interface address */
memcpy(&((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, addr,
sizeof(*addr));
if (ioctl(fd, SIOCSIFADDR, (void *)&ifr) < 0) {
if (errno != EEXIST) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCSIFADDR) failed");
} else {
SYS_ERR(DTUN, LOGL_NOTICE, errno,
"ioctl(SIOCSIFADDR): Address already exists");
}
close(fd);
return -1;
}
}
if (dstaddr) { /* Set the destination address */
memcpy(&((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_addr,
dstaddr, sizeof(*dstaddr));
if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t) & ifr) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCSIFDSTADDR) failed");
close(fd);
return -1;
}
}
if (netmask) { /* Set the netmask */
#if defined(__linux__)
memcpy(&((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr,
netmask, sizeof(*netmask));
#elif defined(__FreeBSD__) || defined (__APPLE__)
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr =
netmask->s_addr;
#endif
if (ioctl(fd, SIOCSIFNETMASK, (void *)&ifr) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCSIFNETMASK) failed");
close(fd);
return -1;
}
}
close(fd);
netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
/* On linux the route to the interface is set automatically
on FreeBSD we have to do this manually */
#if defined(__FreeBSD__) || defined (__APPLE__)
netdev_addroute4(dstaddr, addr, &this->netmask);
#endif
return 0;
}
int netdev_setaddr6(const char *devname, struct in6_addr *addr, struct in6_addr *dstaddr,
size_t prefixlen)
{
struct in6_ifreq ifr;
int fd;
memset(&ifr, 0, sizeof(ifr));
#if defined(__linux__)
ifr.ifr6_prefixlen = prefixlen;
ifr.ifr6_ifindex = if_nametoindex(devname);
if (ifr.ifr6_ifindex == 0) {
SYS_ERR(DTUN, LOGL_ERROR, 0, "Error getting ifindex for %s\n", devname);
return -1;
}
#elif defined(__FreeBSD__) || defined (__APPLE__)
strncpy(ifr.ifr_name, devname, IFNAMSIZ);
#endif
/* Create a channel to the NET kernel */
if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, 0, "socket() failed");
return -1;
}
#if defined(__linux__)
if (addr) {
memcpy(&ifr.ifr6_addr, addr, sizeof(*addr));
if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
if (errno != EEXIST) {
SYS_ERR(DTUN, LOGL_ERROR, 0, "ioctl(SIOCSIFADDR) failed");
} else {
SYS_ERR(DTUN, LOGL_NOTICE, 0, "ioctl(SIOCSIFADDR): Address already exists");
}
close(fd);
return -1;
}
}
#if 0
/* FIXME: looks like this is not possible/necessary for IPv6? */
if (dstaddr) {
memcpy(&ifr.ifr6_addr, dstaddr, sizeof(*dstaddr));
if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t *) &ifr) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, "ioctl(SIOCSIFDSTADDR) failed");
close(fd);
return -1;
}
}
#endif
#elif defined(__FreeBSD__) || defined (__APPLE__)
if (addr)
memcpy(&ifr.ifr_ifru.ifru_addr, addr, sizeof(ifr.ifr_ifru.ifru_addr));
if (dstaddr)
memcpy(&ifr.ifr_ifru.ifru_dstaddr, dstaddr, sizeof(ifr.ifr_ifru.ifru_dstaddr));
if (ioctl(fd, SIOCSIFADDR_IN6, (struct ifreq *)&ifr) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, 0, "ioctl(SIOCSIFADDR_IN6) failed");
close(fd);
return -1;
}
#endif
close(fd);
netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
/* On linux the route to the interface is set automatically
on FreeBSD we have to do this manually */
#if 0 /* FIXME */
//#if defined(__FreeBSD__) || defined (__APPLE__)
netdev_addroute6(dstaddr, addr, prefixlen);
#endif
return 0;
}
int netdev_addaddr4(const char *devname, struct in_addr *addr,
struct in_addr *dstaddr, struct in_addr *netmask)
{
int fd;
#if defined(__linux__)
struct {
struct nlmsghdr n;
struct ifaddrmsg i;
char buf[TUN_NLBUFSIZE];
} req;
struct sockaddr_nl local;
socklen_t addr_len;
int status;
struct sockaddr_nl nladdr;
struct iovec iov;
struct msghdr msg;
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
req.n.nlmsg_type = RTM_NEWADDR;
req.i.ifa_family = AF_INET;
req.i.ifa_prefixlen = 32; /* 32 FOR IPv4 */
req.i.ifa_flags = 0;
req.i.ifa_scope = RT_SCOPE_HOST; /* TODO or 0 */
req.i.ifa_index = if_nametoindex(devname);
if (!req.i.ifa_index) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "Unable to get ifindex for %s", devname);
return -1;
}
netdev_nlattr(&req.n, sizeof(req), IFA_ADDRESS, addr, sizeof(*addr));
if (dstaddr)
netdev_nlattr(&req.n, sizeof(req), IFA_LOCAL, dstaddr, sizeof(*dstaddr));
if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_groups = 0;
if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "bind() failed");
close(fd);
return -1;
}
addr_len = sizeof(local);
if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"getsockname() failed");
close(fd);
return -1;
}
if (addr_len != sizeof(local)) {
SYS_ERR(DTUN, LOGL_ERROR, 0,
"Wrong address length %d", addr_len);
close(fd);
return -1;
}
if (local.nl_family != AF_NETLINK) {
SYS_ERR(DTUN, LOGL_ERROR, 0,
"Wrong address family %d", local.nl_family);
close(fd);
return -1;
}
iov.iov_base = (void *)&req.n;
iov.iov_len = req.n.nlmsg_len;
msg.msg_name = (void *)&nladdr;
msg.msg_namelen = sizeof(nladdr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
req.n.nlmsg_seq = 0;
req.n.nlmsg_flags |= NLM_F_ACK;
status = sendmsg(fd, &msg, 0);
if (status != req.n.nlmsg_len) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "sendmsg() failed, returned %d", status);
close(fd);
return -1;
}
status = netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
if (status == -1) {
close(fd);
return -1;
}
#elif defined (__FreeBSD__) || defined (__APPLE__)
struct ifaliasreq areq;
memset(&areq, 0, sizeof(areq));
/* Set up interface name */
strncpy(areq.ifra_name, devname, IFNAMSIZ);
areq.ifra_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
((struct sockaddr_in *)&areq.ifra_addr)->sin_family = AF_INET;
((struct sockaddr_in *)&areq.ifra_addr)->sin_len =
sizeof(areq.ifra_addr);
((struct sockaddr_in *)&areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
((struct sockaddr_in *)&areq.ifra_mask)->sin_family = AF_INET;
((struct sockaddr_in *)&areq.ifra_mask)->sin_len =
sizeof(areq.ifra_mask);
((struct sockaddr_in *)&areq.ifra_mask)->sin_addr.s_addr =
netmask->s_addr;
/* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_family = AF_INET;
((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_len =
sizeof(areq.ifra_broadaddr);
((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_addr.s_addr =
dstaddr->s_addr;
/* Create a channel to the NET kernel. */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
if (ioctl(fd, SIOCAIFADDR, (void *)&areq) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCAIFADDR) failed");
close(fd);
return -1;
}
#endif
close(fd);
return 0;
}
int netdev_addaddr6(const char *devname, struct in6_addr *addr,
struct in6_addr *dstaddr, int prefixlen)
{
int fd;
#if defined(__linux__)
struct {
struct nlmsghdr n;
struct ifaddrmsg i;
char buf[TUN_NLBUFSIZE];
} req;
struct sockaddr_nl local;
socklen_t addr_len;
int status;
struct sockaddr_nl nladdr;
struct iovec iov;
struct msghdr msg;
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
req.n.nlmsg_type = RTM_NEWADDR;
req.i.ifa_family = AF_INET6;
req.i.ifa_prefixlen = prefixlen; /* 64 FOR IPv6 */
req.i.ifa_flags = 0;
req.i.ifa_scope = RT_SCOPE_HOST; /* TODO or 0 */
req.i.ifa_index = if_nametoindex(devname);
if (!req.i.ifa_index) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "Unable to get ifindex for %s", devname);
return -1;
}
netdev_nlattr(&req.n, sizeof(req), IFA_ADDRESS, addr, sizeof(*addr));
if (dstaddr)
netdev_nlattr(&req.n, sizeof(req), IFA_LOCAL, dstaddr, sizeof(*dstaddr));
if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_groups = 0;
if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "bind() failed");
close(fd);
return -1;
}
addr_len = sizeof(local);
if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"getsockname() failed");
close(fd);
return -1;
}
if (addr_len != sizeof(local)) {
SYS_ERR(DTUN, LOGL_ERROR, 0,
"Wrong address length %d", addr_len);
close(fd);
return -1;
}
if (local.nl_family != AF_NETLINK) {
SYS_ERR(DTUN, LOGL_ERROR, 0,
"Wrong address family %d", local.nl_family);
close(fd);
return -1;
}
iov.iov_base = (void *)&req.n;
iov.iov_len = req.n.nlmsg_len;
msg.msg_name = (void *)&nladdr;
msg.msg_namelen = sizeof(nladdr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
req.n.nlmsg_seq = 0;
req.n.nlmsg_flags |= NLM_F_ACK;
status = sendmsg(fd, &msg, 0);
if (status != req.n.nlmsg_len) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "sendmsg() failed, returned %d", status);
close(fd);
return -1;
}
status = netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
if (status == -1) {
close(fd);
return -1;
}
#elif defined (__FreeBSD__) || defined (__APPLE__)
struct ifaliasreq areq;
memset(&areq, 0, sizeof(areq));
/* Set up interface name */
strncpy(areq.ifra_name, devname, IFNAMSIZ);
areq.ifra_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
((struct sockaddr_in6 *)&areq.ifra_addr)->sin6_family = AF_INET6;
((struct sockaddr_in6 *)&areq.ifra_addr)->sin6_len = sizeof(areq.ifra_addr);
((struct sockaddr_in6 *)&areq.ifra_addr)->sin6_addr.s6_addr = addr->s6_addr;
((struct sockaddr_in6 *)&areq.ifra_mask)->sin6_family = AF_INET6;
((struct sockaddr_in6 *)&areq.ifra_mask)->sin6_len = sizeof(areq.ifra_mask);
((struct sockaddr_in6 *)&areq.ifra_mask)->sin6_addr.s6_addr = netmask->s6_addr;
/* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
((struct sockaddr_in6 *)&areq.ifra_broadaddr)->sin6_family = AF_INET6;
((struct sockaddr_in6 *)&areq.ifra_broadaddr)->sin6_len = sizeof(areq.ifra_broadaddr);
((struct sockaddr_in6 *)&areq.ifra_broadaddr)->sin6_addr.s6_addr = dstaddr->s6_addr;
/* Create a channel to the NET kernel. */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
if (ioctl(fd, SIOCAIFADDR, (void *)&areq) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCAIFADDR) failed");
close(fd);
return -1;
}
#endif
close(fd);
return 0;
}
static int netdev_route4(struct in_addr *dst, struct in_addr *gateway, struct in_addr *mask, int delete)
{
int fd;
#if defined(__linux__)
struct rtentry r;
memset(&r, '\0', sizeof(r));
r.rt_flags = RTF_UP | RTF_GATEWAY; /* RTF_HOST not set */
/* Create a channel to the NET kernel. */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
r.rt_dst.sa_family = AF_INET;
r.rt_gateway.sa_family = AF_INET;
r.rt_genmask.sa_family = AF_INET;
memcpy(&((struct sockaddr_in *)&r.rt_dst)->sin_addr, dst, sizeof(*dst));
memcpy(&((struct sockaddr_in *)&r.rt_gateway)->sin_addr, gateway,
sizeof(*gateway));
memcpy(&((struct sockaddr_in *)&r.rt_genmask)->sin_addr, mask,
sizeof(*mask));
if (delete) {
if (ioctl(fd, SIOCDELRT, (void *)&r) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCDELRT) failed");
close(fd);
return -1;
}
} else {
if (ioctl(fd, SIOCADDRT, (void *)&r) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCADDRT) failed");
close(fd);
return -1;
}
}
#elif defined(__FreeBSD__) || defined (__APPLE__)
struct {
struct rt_msghdr rt;
struct sockaddr_in dst;
struct sockaddr_in gate;
struct sockaddr_in mask;
} req;
struct rt_msghdr *rtm;
if ((fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
memset(&req, 0x00, sizeof(req));
rtm = &req.rt;
rtm->rtm_msglen = sizeof(req);
rtm->rtm_version = RTM_VERSION;
if (delete) {
rtm->rtm_type = RTM_DELETE;
} else {
rtm->rtm_type = RTM_ADD;
}
rtm->rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; /* TODO */
rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
rtm->rtm_pid = getpid();
rtm->rtm_seq = 0044; /* TODO */
req.dst.sin_family = AF_INET;
req.dst.sin_len = sizeof(req.dst);
req.mask.sin_family = AF_INET;
req.mask.sin_len = sizeof(req.mask);
req.gate.sin_family = AF_INET;
req.gate.sin_len = sizeof(req.gate);
req.dst.sin_addr.s_addr = dst->s_addr;
req.mask.sin_addr.s_addr = mask->s_addr;
req.gate.sin_addr.s_addr = gateway->s_addr;
if (write(fd, rtm, rtm->rtm_msglen) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "write() failed");
close(fd);
return -1;
}
#endif
close(fd);
return 0;
}
static int netdev_route6(struct in6_addr *dst, struct in6_addr *gateway, int prefixlen, const char *gw_iface, int delete)
{
int fd;
#if defined(__linux__)
struct in6_rtmsg r;
struct ifreq ifr;
memset(&r, 0, sizeof(r));
r.rtmsg_flags = RTF_UP | RTF_GATEWAY; /* RTF_HOST not set */
r.rtmsg_metric = 1;
/* Create a channel to the NET kernel. */
if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
return -1;
}
if (gw_iface) {
strncpy(ifr.ifr_name, gw_iface, IFNAMSIZ);
ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCGIFINDEX) failed");
close(fd);
return -1;
}
r.rtmsg_ifindex = ifr.ifr_ifindex;
}
memcpy(&r.rtmsg_dst, dst->s6_addr, sizeof(struct in6_addr));
memcpy(&r.rtmsg_gateway, gateway->s6_addr, sizeof(struct in6_addr));
r.rtmsg_dst_len = prefixlen;
if (delete) {
if (ioctl(fd, SIOCDELRT, (void *)&r) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCDELRT) failed");
close(fd);
return -1;
}
} else {
if (ioctl(fd, SIOCADDRT, (void *)&r) < 0) {
SYS_ERR(DTUN, LOGL_ERROR, errno,
"ioctl(SIOCADDRT) failed");
close(fd);
return -1;
}
}
close(fd);
#endif
return 0;
}
int netdev_addroute4(struct in_addr *dst, struct in_addr *gateway, struct in_addr *mask)
{
return netdev_route4(dst, gateway, mask, 0);
}
int netdev_delroute4(struct in_addr *dst, struct in_addr *gateway, struct in_addr *mask)
{
return netdev_route4(dst, gateway, mask, 1);
}
int netdev_addroute6(struct in6_addr *dst, struct in6_addr *gateway, int prefixlen, const char *gw_iface)
{
return netdev_route6(dst, gateway, prefixlen, gw_iface, 0);
}
int netdev_delroute6(struct in6_addr *dst, struct in6_addr *gateway, int prefixlen, const char *gw_iface)
{
return netdev_route6(dst, gateway, prefixlen, gw_iface, 1);
}
#include <ifaddrs.h>
/*! Obtain the local address of a network device
* \param[in] devname Target device owning the IP
* \param[out] prefix_list List of prefix structures to fill with each IPv4/6 and prefix length found.
* \param[in] prefix_size Amount of elements allowed to be fill in the prefix_list array.
* \param[in] flags Specify which kind of IP to look for: IP_TYPE_IPv4, IP_TYPE_IPv6_LINK, IP_TYPE_IPv6_NONLINK
* \returns The number of ips found following the criteria specified by flags, -1 on error.
*
* This function will fill prefix_list with up to prefix_size IPs following the
* criteria specified by flags parameter. It returns the number of IPs matching
* the criteria. As a result, the number returned can be bigger than
* prefix_size. It can be used with prefix_size=0 to get an estimate of the size
* needed for prefix_list.
*/
int netdev_ip_local_get(const char *devname, struct in46_prefix *prefix_list, size_t prefix_size, int flags)
{
static const uint8_t ll_prefix[] = { 0xfe,0x80, 0,0, 0,0, 0,0 };
struct ifaddrs *ifaddr, *ifa;
struct in46_addr netmask;
size_t count = 0;
bool is_ipv6_ll;
if (getifaddrs(&ifaddr) == -1) {
return -1;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
if (strcmp(ifa->ifa_name, devname))
continue;
if (ifa->ifa_addr->sa_family == AF_INET && (flags & IP_TYPE_IPv4)) {
struct sockaddr_in *sin4 = (struct sockaddr_in *) ifa->ifa_addr;
struct sockaddr_in *netmask4 = (struct sockaddr_in *) ifa->ifa_netmask;
if (count < prefix_size) {
netmask.len = sizeof(netmask4->sin_addr);
netmask.v4 = netmask4->sin_addr;
prefix_list[count].addr.len = sizeof(sin4->sin_addr);
prefix_list[count].addr.v4 = sin4->sin_addr;
prefix_list[count].prefixlen = in46a_netmasklen(&netmask);
}
count++;
}
if (ifa->ifa_addr->sa_family == AF_INET6 && (flags & IP_TYPE_IPv6)) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ifa->ifa_addr;
struct sockaddr_in6 *netmask6 = (struct sockaddr_in6 *) ifa->ifa_netmask;
is_ipv6_ll = !memcmp(sin6->sin6_addr.s6_addr, ll_prefix, sizeof(ll_prefix));
if ((flags & IP_TYPE_IPv6_NONLINK) && is_ipv6_ll)
continue;
if ((flags & IP_TYPE_IPv6_LINK) && !is_ipv6_ll)
continue;
if (count < prefix_size) {
netmask.len = sizeof(netmask6->sin6_addr);
netmask.v6 = netmask6->sin6_addr;
prefix_list[count].addr.len = sizeof(sin6->sin6_addr);
prefix_list[count].addr.v6 = sin6->sin6_addr;
prefix_list[count].prefixlen = in46a_netmasklen(&netmask);
}
count++;
}
}
freeifaddrs(ifaddr);
return count;
}

74
lib/netdev.h Normal file
View File

@@ -0,0 +1,74 @@
#pragma once
/*
* TUN interface functions.
* Copyright (C) 2002, 2003 Mondru AB.
* Copyright (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
*
* 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.
*
*/
#include <net/if.h>
#include "../lib/in46_addr.h"
#define TUN_NLBUFSIZE 1024
#include "config.h"
/* ipv6 ip type flags for tun_ipv6_local_get() */
enum {
IP_TYPE_IPv4 = 1,
IP_TYPE_IPv6_LINK = 2,
IP_TYPE_IPv6_NONLINK = 4,
};
#define IP_TYPE_IPv6 (IP_TYPE_IPv6_LINK | IP_TYPE_IPv6_NONLINK)
#ifndef HAVE_IPHDR
struct iphdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ihl:4;
unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
unsigned int version:4;
unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
/*The options start here. */
};
#endif /* !HAVE_IPHDR */
extern int netdev_setaddr4(const char *devname, struct in_addr *addr,
struct in_addr *dstaddr, struct in_addr *netmask);
extern int netdev_setaddr6(const char *devname, struct in6_addr *addr, struct in6_addr *dstaddr,
size_t prefixlen);
extern int netdev_addaddr4(const char *devname, struct in_addr *addr,
struct in_addr *dstaddr, struct in_addr *netmask);
extern int netdev_addaddr6(const char *devname, struct in6_addr *addr,
struct in6_addr *dstaddr, int prefixlen);
extern int netdev_addroute4(struct in_addr *dst, struct in_addr *gateway, struct in_addr *mask);
extern int netdev_delroute4(struct in_addr *dst, struct in_addr *gateway, struct in_addr *mask);
extern int netdev_addroute6(struct in6_addr *dst, struct in6_addr *gateway, int prefixlen, const char *gw_iface);
extern int netdev_delroute6(struct in6_addr *dst, struct in6_addr *gateway, int prefixlen, const char *gw_iface);
extern int netdev_ip_local_get(const char *devname, struct in46_prefix *prefix_list,
size_t prefix_size, int flags);

272
lib/netns.c Normal file
View File

@@ -0,0 +1,272 @@
/*
* Copyright (C) 2014-2017, Travelping GmbH <info@travelping.com>
* Copyright (C) 2020, Harald Welte <laforge@gnumonks.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if defined(__linux__)
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <fcntl.h>
#include <errno.h>
#include <osmocom/core/utils.h>
#include "netns.h"
#define NETNS_PATH "/var/run/netns"
/*! default namespace of the GGSN process */
static int default_nsfd = -1;
/*! switch to a (non-default) namespace, store existing signal mask in oldmask.
* \param[in] nsfd file descriptor representing the namespace to whch we shall switch
* \param[out] oldmask caller-provided memory location to which old signal mask is stored
* \ returns 0 on success or negative (errno) in case of error */
int switch_ns(int nsfd, sigset_t *oldmask)
{
sigset_t intmask;
int rc;
OSMO_ASSERT(default_nsfd >= 0);
if (sigfillset(&intmask) < 0)
return -errno;
if ((rc = sigprocmask(SIG_BLOCK, &intmask, oldmask)) != 0)
return -rc;
if (setns(nsfd, CLONE_NEWNET) < 0) {
/* restore old mask if we couldn't switch the netns */
sigprocmask(SIG_SETMASK, oldmask, NULL);
return -errno;
}
return 0;
}
/*! switch back to the default namespace, restoring signal mask.
* \param[in] oldmask signal mask to restore after returning to default namespace
* \returns 0 on successs; negative errno value in case of error */
int restore_ns(sigset_t *oldmask)
{
OSMO_ASSERT(default_nsfd >= 0);
int rc;
if (setns(default_nsfd, CLONE_NEWNET) < 0)
return -errno;
if ((rc = sigprocmask(SIG_SETMASK, oldmask, NULL)) != 0)
return -rc;
return 0;
}
/*! open a file from within specified network namespace */
int open_ns(int nsfd, const char *pathname, int flags)
{
sigset_t intmask, oldmask;
int ret;
int fd = -1;
int rc;
OSMO_ASSERT(default_nsfd >= 0);
/* mask off all signals, store old signal mask */
if (sigfillset(&intmask) < 0)
return -errno;
if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
return -rc;
/* associate the calling thread with namespace file descriptor */
if (setns(nsfd, CLONE_NEWNET) < 0) {
ret = -errno;
goto restore_sigmask;
}
/* open the requested file/path */
if ((fd = open(pathname, flags)) < 0) {
ret = -errno;
goto restore_defaultns;
}
ret = fd;
restore_defaultns:
/* return back to default namespace */
if (setns(default_nsfd, CLONE_NEWNET) < 0) {
if (fd >= 0)
close(fd);
return -errno;
}
restore_sigmask:
/* restore process mask */
if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) {
if (fd >= 0)
close(fd);
return -rc;
}
return ret;
}
/*! create a socket in another namespace.
* Switches temporarily to namespace indicated by nsfd, creates a socket in
* that namespace and then returns to the default namespace.
* \param[in] nsfd File descriptor of the namspace in which to create socket
* \param[in] domain Domain of the socket (AF_INET, ...)
* \param[in] type Type of the socket (SOCK_STREAM, ...)
* \param[in] protocol Protocol of the socket (IPPROTO_TCP, ...)
* \returns 0 on success; negative errno in case of error */
int socket_ns(int nsfd, int domain, int type, int protocol)
{
sigset_t intmask, oldmask;
int ret;
int sk = -1;
int rc;
OSMO_ASSERT(default_nsfd >= 0);
/* mask off all signals, store old signal mask */
if (sigfillset(&intmask) < 0)
return -errno;
if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
return -rc;
/* associate the calling thread with namespace file descriptor */
if (setns(nsfd, CLONE_NEWNET) < 0) {
ret = -errno;
goto restore_sigmask;
}
/* create socket of requested domain/type/proto */
if ((sk = socket(domain, type, protocol)) < 0) {
ret = -errno;
goto restore_defaultns;
}
ret = sk;
restore_defaultns:
/* return back to default namespace */
if (setns(default_nsfd, CLONE_NEWNET) < 0) {
if (sk >= 0)
close(sk);
return -errno;
}
restore_sigmask:
/* restore process mask */
if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0) {
if (sk >= 0)
close(sk);
return -rc;
}
return ret;
}
/*! initialize this network namespace helper module.
* Must be called before using any other functions of this file.
* \returns 0 on success; negative errno in case of error */
int init_netns()
{
/* store the default namespace for later reference */
if ((default_nsfd = open("/proc/self/ns/net", O_RDONLY)) < 0)
return -errno;
return 0;
}
/*! create obtain file descriptor for network namespace of give name.
* Creates /var/run/netns if it doesn't exist already.
* \param[in] name Name of the network namespace (in /var/run/netns/)
* \returns File descriptor of network namespace; negative errno in case of error */
int get_nsfd(const char *name)
{
int ret = 0;
int rc;
int fd;
sigset_t intmask, oldmask;
char path[MAXPATHLEN] = NETNS_PATH;
OSMO_ASSERT(default_nsfd >= 0);
/* create /var/run/netns, if it doesn't exist already */
rc = mkdir(path, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
if (rc < 0 && errno != EEXIST)
return rc;
/* create /var/run/netns/[name], if it doesn't exist already */
snprintf(path, sizeof(path), "%s/%s", NETNS_PATH, name);
fd = open(path, O_RDONLY|O_CREAT|O_EXCL, 0);
if (fd < 0) {
if (errno == EEXIST) {
if ((fd = open(path, O_RDONLY)) < 0)
return -errno;
return fd;
}
return -errno;
}
if (close(fd) < 0)
return -errno;
/* mask off all signals, store old signal mask */
if (sigfillset(&intmask) < 0)
return -errno;
if ((rc = sigprocmask(SIG_BLOCK, &intmask, &oldmask)) != 0)
return -rc;
/* create a new network namespace */
if (unshare(CLONE_NEWNET) < 0) {
ret = -errno;
goto restore_sigmask;
}
if (mount("/proc/self/ns/net", path, "none", MS_BIND, NULL) < 0)
ret = -errno;
/* switch back to default namespace */
if (setns(default_nsfd, CLONE_NEWNET) < 0)
return -errno;
restore_sigmask:
/* restore process mask */
if ((rc = sigprocmask(SIG_SETMASK, &oldmask, NULL)) != 0)
return -rc;
/* might have been set above in case mount fails */
if (ret < 0)
return ret;
/* finally, open the created namespace file descriptor from default ns */
if ((fd = open(path, O_RDONLY)) < 0)
return -errno;
return fd;
}
#endif

35
lib/netns.h Normal file
View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2014-2017, Travelping GmbH <info@travelping.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __NETNS_H
#define __NETNS_H
#if defined(__linux__)
int init_netns(void);
int switch_ns(int nsfd, sigset_t *oldmask);
int restore_ns(sigset_t *oldmask);
int open_ns(int nsfd, const char *pathname, int flags);
int socket_ns(int nsfd, int domain, int type, int protocol);
int get_nsfd(const char *name);
#endif
#endif

View File

@@ -19,6 +19,7 @@ enum {
DTUN,
DGGSN,
DSGSN,
DICMP6,
};
#define SYS_ERR(sub, pri, en, fmt, args...) \

866
lib/tun.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,29 @@
/*
/*
* TUN interface functions.
* Copyright (C) 2002, 2003 Mondru AB.
*
* Copyright (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
*
* 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 _TUN_H
#define _TUN_H
#include <stdbool.h>
#include <net/if.h>
#include "../lib/in46_addr.h"
#define PACKET_MAX 8196 /* Maximum packet size we receive */
#define TUN_SCRIPTSIZE 256
#define TUN_ADDRSIZE 128
#define TUN_NLBUFSIZE 1024
struct tun_packet_t {
unsigned int ver:4;
unsigned int ihl:4;
unsigned int dscp:6;
unsigned int ecn:2;
unsigned int length:16;
unsigned int id:16;
unsigned int flags:3;
unsigned int fragment:13;
unsigned int ttl:8;
unsigned int protocol:8;
unsigned int check:16;
unsigned int src:32;
unsigned int dst:32;
};
#include "config.h"
#include "netdev.h"
/* ***********************************************************
* Information storage for each tun instance
@@ -39,28 +31,24 @@ struct tun_packet_t {
struct tun_t {
int fd; /* File descriptor to tun interface */
struct in_addr addr;
struct in_addr dstaddr;
struct in46_addr addr;
struct in46_addr dstaddr;
struct in_addr netmask;
int addrs; /* Number of allocated IP addresses */
int routes; /* One if we allocated an automatic route */
char devname[IFNAMSIZ]; /* Name of the tun device */
int (*cb_ind) (struct tun_t * tun, void *pack, unsigned len);
/* to be used by libgtp callers/users (to attach their own private state) */
void *priv;
};
extern int tun_new(struct tun_t **tun);
extern int tun_new(struct tun_t **tun, const char *dev_name, bool use_kernel, int fd0, int fd1u);
extern int tun_free(struct tun_t *tun);
extern int tun_decaps(struct tun_t *this);
extern int tun_encaps(struct tun_t *tun, void *pack, unsigned len);
extern int tun_addaddr(struct tun_t *this, struct in_addr *addr,
struct in_addr *dstaddr, struct in_addr *netmask);
extern int tun_setaddr(struct tun_t *this, struct in_addr *our_adr,
struct in_addr *his_adr, struct in_addr *net_mask);
int tun_addroute(struct tun_t *this, struct in_addr *dst,
struct in_addr *gateway, struct in_addr *mask);
extern int tun_addaddr(struct tun_t *this, struct in46_addr *addr,
struct in46_addr *dstaddr, size_t prefixlen);
extern int tun_set_cb_ind(struct tun_t *this,
int (*cb_ind) (struct tun_t * tun, void *pack,
@@ -68,4 +56,10 @@ extern int tun_set_cb_ind(struct tun_t *this,
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 */

35
lib/util.c Normal file
View File

@@ -0,0 +1,35 @@
/*
* misc helpers
* Copyright 2019 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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.
*
*/
#include "../gtp/pdp.h"
#include "ippool.h"
#include "in46_addr.h"
/*! Get the peer of pdp based on IP version used.
* \param[in] pdp PDP context to select the peer from.
* \param[in] v4v6 IP version to select. Valid values are 4 and 6.
* \returns The selected peer matching the given IP version. NULL if not present.
*/
struct ippoolm_t *pdp_get_peer_ipv(struct pdp_t *pdp, bool is_ipv6) {
uint8_t i;
for (i = 0; i < 2; i++) {
struct ippoolm_t * ippool = pdp->peer[i];
if (!ippool)
continue;
if (is_ipv6 && in46a_is_v6(&ippool->addr))
return ippool;
else if (!is_ipv6 && in46a_is_v4(&ippool->addr))
return ippool;
}
return NULL;
}

18
lib/util.h Normal file
View File

@@ -0,0 +1,18 @@
#pragma once
/*
* misc helpers
* Copyright 2019 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* 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.
*
*/
#include <stdbool.h>
struct ippoolm_t;
struct pdp_t;
struct ippoolm_t *pdp_get_peer_ipv(struct pdp_t *pdp, bool is_ipv6);

View File

@@ -3,7 +3,7 @@ exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: OpenGGSN STP Library
Name: OsmoGGSN GTP Library
Description: C Utility Library
Version: @VERSION@
Libs: -L${libdir} -lgtp

View File

@@ -1,87 +0,0 @@
Summary: Open Source Gateway GPRS Support Node (GGSN)
Name: @PACKAGE@
Version: @VERSION@
Release: 1
URL: http://sourceforge.net/projects/ggsn/
Source0: http://prdownloads.sourceforge.net/ggsn/%{name}-%{version}.tar.gz
License: GPL
Group: System Environment/Daemons
BuildRoot: %{_tmppath}/%{name}-root
%description
OpenGGSN 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/ggsn
strip $RPM_BUILD_ROOT/usr/bin/sgsnemu
#Copy ggsn init script in place
mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
install -m755 examples/ggsn.init \
$RPM_BUILD_ROOT/etc/rc.d/init.d/ggsn
#Copy ggsn.conf in place
install -m755 examples/ggsn.conf \
$RPM_BUILD_ROOT/etc/ggsn.conf
#Copy gsn_restart file in place
mkdir -p $RPM_BUILD_ROOT/var/lib/ggsn
echo "0" > $RPM_BUILD_ROOT/var/lib/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 ggsn
%files
%defattr(-,root,root)
/usr/bin/ggsn
/usr/bin/sgsnemu
/etc/rc.d/init.d/ggsn
%dir /var/lib/ggsn
/var/lib/ggsn/gsn_restart
%doc AUTHORS ChangeLog COPYING INSTALL NEWS README
%doc examples/ggsn.conf
%doc examples/sgsnemu.conf
%doc examples/ggsn.init
%doc examples/firewall
%doc /usr/man/man8/ggsn.8.gz
%doc /usr/man/man8/sgsnemu.8.gz
%config /etc/ggsn.conf
#/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 2003 <jj@openggsn.org>
- Initial build.

Some files were not shown because too many files have changed in this diff Show More