Compare commits

...

97 Commits

Author SHA1 Message Date
Oliver Smith 7ba62d3061 contrib: remove rpm spec file
Related: https://osmocom.org/news/255
Related: OS#6446
Change-Id: I9e7a3beb861faab1b6852aa5b57847c590986976
2024-05-13 08:39:35 +00:00
Vadim Yanitskiy 62b28ffe1b VTY: sync default UMTS UEA config with osmo-msc
As was reported in OS#6442, nano3g S16 is unhappy when CS and PS
domains use different UEA configuration for simultaneous RANAP
connections.  Bring osmo-sgsn in sync with osmo-msc to avoid this.

Change-Id: I4eb9451b4267fc1436ed90a55ff200cf36f16bf6
Related: OS#6442
2024-05-09 10:50:08 +02:00
Vadim Yanitskiy cdf716cf9a VTY: move default settings to sgsn_instance_alloc()
It's cleaner to have all configuration defaults in one place.

Change-Id: I1a439dcc76272a181986b6ec9368ef16441dc098
Related: OS#6442
2024-05-09 10:48:29 +02:00
Oliver Smith a9c39c04de .deb/.rpm: various fixes related to non-root
* Explicitly chown /var/lib/osmocom to osmocom:osmocom, instead of
  relying on systemd to do it when the service starts up. This does not
  work with the systemd versions in debian 10 and almalinux 8.
* deb: Use "useradd" instead of the interactive "adduser" perl script
  from Debian. This makes it consistent with how we do it in rpm, and
  avoids the dependency on "adduser".
* deb: Consistently use tabs through the file, instead of mixing tabs
  and spaces.
* deb: Remove support for the "dpkg-statoverride --list" logic. This
  seems to be a rather obscure feature to override permissions for
  certain files or directories, for which it does not seem to be a good
  idea to make the postinst script less maintainable. Something similar
  can be achieved by using your own Osmocom config file in a different
  path with different permissions.

Related: OS#4107
Change-Id: I406ff0d625b02991d580c8382aa4be04dba45a00
2024-05-08 06:46:32 +00:00
Vadim Yanitskiy 282de031f1 gmm: mmctx_timer_stop(): warn about timer not running
This turns errors like:

  DMM ERROR MM(262420000000038/e2ff704e) Stopping MM timer 3350 but 0 is running

into warnings with a more accurate reason:

  DMM NOTICE MM(262420000000037/e2ff704e) Stopping *inactive* MM timer 3350

Change-Id: I56ecad9d8f1049974b0896f6d0e7fc61580155ec
2024-05-01 10:44:27 +02:00
Vadim Yanitskiy c3156193da gmm: cosmetic: fix preprocessor macro formatting
Change-Id: I77171d65db23794d8fd9872e0cc4d6f3b50dda0d
2024-05-01 10:44:27 +02:00
Alexander Couzens cd3a8cfad6 docs: front page: use https:// instead of http://
Change-Id: If3c3b8e79f94da7a3bcc9262808da09f6a5a601c
2024-04-28 12:17:10 +00:00
Alexander Couzens e51b3be379 docs: update year to 2024
Change-Id: I85a987eee470d2040c91289d33c5d97c3e90674d
2024-04-28 12:17:10 +00:00
Alexander Couzens b34e0a5720 docs: replace legacy NS with new NS2 chapters
osmo-sgsn already switched to the new NS2 code. Use the correct
NS2 chapter

Change-Id: I9cc86d234e029b5192e36aeb14b0e39d1496842d
2024-04-28 12:17:10 +00:00
Oliver Smith 05363e0a32 contrib/osmo-sgsn.spec: fix build for almalinux:8
Add the missing "%if 0%{?suse_version}" around %service_del/add
commands, as these are only available on opensuse.

Fix for:
  error: line 106: Too many names: %preun  -n osmo-gtphub %service_del_preun   osmo-gtphub.service

Fixes: a07e6d9c (".deb/.rpm: add osmocom user during package install")
Change-Id: I89802f926bfccc0f7b4bb1ff64115b232b1db022
2024-04-26 09:58:51 +02:00
Max a07e6d9c58 .deb/.rpm: add osmocom user during package install
Create osmocom user & group during package installation.
Fix the configuration dir/files permission to match.

Related: OS#4107
Tweaked-By: Oliver Smith <osmith@sysmocom.de>
Change-Id: I55ce205d4b314d01b2641c8f3d52455c051d6282
2024-04-24 11:52:50 +02:00
Harald Welte 1ede89a35a README.md: Add Forum and Issue Tracker sections
Change-Id: I69dfe4124c2a2be30c9ef04e70e3f15d10a2305c
2024-03-23 17:15:07 +01:00
Harald Welte 647304fbe5 README.md: Overhaul (more links; improved formatting)
Change-Id: I0cf9898877aab2f834c886491f4d203d55a8b4b9
2024-03-23 17:07:07 +01:00
Harald Welte 370d6e8b59 Add funding link to github mirror
see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository

Change-Id: Icf0fd068742eba60c23f0e567e6e72b42063f2c0
2024-03-23 17:03:36 +01:00
Pau Espin dc4c294f94 gsup: Use new libosmogsm struct osmo_gsup_pdp_info fields
This also makes sure it doesn't compile against older libosmogsm gsup
versions which would break ABI.

Change-Id: I0d03d368e73ab62ec631420769f6af91f2ff9987
Related: OS#6091
Depends: libosmocore.git Change-Id 70be3560659c58f24b8db529c4fc85da4bb0ec04
2024-01-29 11:07:03 +01:00
Vadim Yanitskiy f2545b1b8f build: include README.md into the release tarball
Change-Id: Ia467ae8cc6eec0dc9fb36d4c159d2762e965c4f8
2024-01-26 23:37:30 +07:00
Andreas Eversberg 1f1d90f175 Use uniform log format for default config files
Related: OS#6272
Change-Id: I6b6aa5a5100cf0045dcba1b062acc9376d34b0ae
2023-12-01 12:40:54 +01:00
Oliver Smith 2a89bbf66f Bump version: 1.11.0.5-67677-dirty → 1.11.1
Depends: osmo-ggsn I1f116e1cded135f231f22ebc9b817aebf3736fc2
Change-Id: I869eef2032d6025c8ed59a1b25192c6c5c08977e
2023-11-28 13:43:15 +01:00
Daniel Willmann 676777c5f9 libgtp: Check for all successful create_pdp_conf causes
Related: OS#6268
Change-Id: I11ce72908c2dfb983887e6c1db316fd7de42f027
2023-11-23 18:00:07 +01:00
Daniel Willmann ff9c46cc61 vty-tests: Test encryption options
Change-Id: I471c04602dedfb2a80d4408c09125e51c465a8b8
2023-11-22 16:06:43 +01:00
Daniel Willmann 75a0aa78a3 sgsn_vty: Correctly indent encryption cipher-plugin-path
Change-Id: I16b3450c3919bebbceb8d27f73d7c6dde102d0f7
2023-11-22 16:06:43 +01:00
Daniel Willmann 20aef4de28 sgsn_vty: Fix output in config_write_sgsn
The encryption uea option was missing

Change-Id: I2c81ced87c53d69a94b3894441323201f81f1a76
2023-11-22 13:14:25 +01:00
Philipp Maier e746b0bef6 sgsn_rim: forward message based on RIM ROUTING ADDRESS
At the moment we parse the RAN TRANSPARENT CONTAINER to look at the
destination RIM ROUTING INFORMATION. This is not correct. The SGSN
should not decode the RAN TRANSPARENT CONTAINER and use the RIM ROUTING
ADDRESS / RIM ROUTING ADDRESS DISCRIMINATOR IE to make the routing
decision.

Related: OS#6095
Depends: libosmocore.git Ibca1f08906c4ffeecdae80d4e91c6c7b05fe4f8a
Change-Id: Ifd2b915ed2f05130cff8ee77714b82005c17de3d
2023-09-18 21:53:39 +02:00
Pau Espin 57567968ea Bump version: 1.10.0.16-7e4d-dirty → 1.11.0
Change-Id: Ia56d2e1c4247396522f02df2c95b842db655e171
2023-09-12 16:57:03 +02:00
Philipp Maier 7e4dbb4b34 sgsn_rim: do not check the origin of a RIM message
When we forward RIM messages from GTP to BSSGP, we do not have to check
the origin of the message since it does not matter from which origin the
message came when we are forwarding it.

Related: OS#6095
Change-Id: Iea8176dcfe64c25d207bafc0ef61ca9d9ad415be
2023-08-10 10:24:23 +02:00
Philipp Maier 7840375d51 sgsn_rim: get rid of MME check in sgsn_rim_rx_from_gtp:
There is no point in checking the MME any further. When the message has
reached this code path it is about to be forwarded to BSSGP, so the MME
does not play a role in the following code pathes.

The check also relys on the source RIM ROUTING INFORMATION IE inside the
RAN TRANSPARENT CONTAINER, which we are not supposed to decode.

Change-Id: I97c89aeb11537ae54d1fbea48c75619d8a92af61
Related: OS#6095
2023-08-10 10:23:06 +02:00
Philipp Maier 429d332ece sgsn_rim: cosmetic: improve comment
Let's describe more clear what we do in sgsn_bssgp_fwd_rim_to_geran

Related: OS#6095
Change-Id: I54aa82845515bcaa6badc9e0e87fa6248333430e
2023-08-10 10:19:37 +02:00
Philipp Maier f24970a7ca sgsn_rim: fix typo
Related: OS#6095
Change-Id: I86f70ea9a1a3e43523ec327165bfeb1737ad300a
2023-07-28 13:23:49 +02:00
Pau Espin 2365fec0fb gmm: Add missing GSM48_IE_GMM_RX_NPDU_NUM_LIST IE in gsm48_gmm_att_tlvdef
Depends: libosmocore.git Change-Id Ifac09653141758af345efe2eb9cef25ebf4dcff9
Change-Id: I5b43384407b1c9c33790cae9c48c2816213578e6
2023-07-18 17:41:09 +02:00
Pau Espin 5df65b6c30 gmm: Update DRX params during rx RAU REQ
The DRX params where already parsed in GMM Attached Req and transmitted
to PCU over BSSGP DL UD packets, but it was not being updated if the MS
changed it during RAU Req.

TS 24.008 9.4.14.3 DRX parameter:
"This IE shall be included if the MS changes the access network
from GSM to UMTS, or the MS wants to indicate new DRX parameters
to the network."

Change-Id: I1dd7f8f161280dd017c337eacc3aa2be4ccd65ea
2023-07-14 18:11:31 +02:00
Pau Espin 5f1020b963 Write explicit role & sctp-role fields in ASP configurations
Change-Id: I44e251ca2df02e4f1fdfc1492306ec25d0653ef6
2023-06-08 19:34:21 +02:00
Oliver Smith eda1b83f75 systemd: depend on networking-online.target
Related: SYS#6400
Change-Id: Idadcbbf55e976ae035cfac4b85ccd870e0f27b82
2023-05-26 14:10:48 +02:00
Vadim Yanitskiy b83aabaa95 copyright: fix typo: sysmocom s/s.m.f.c./s.f.m.c./ GmbH
Change-Id: Ie2d864d5171e0da2e8a6c8551d151fd14f89bf05
2023-05-18 17:22:26 +07:00
Pau Espin 1bebd08a4b gprs_sm.c: Fix load of misaligned ptr address
Got this Asan runtime error in osmo-sgsn while implementing the MS side of SM:
"""
DMM gprs_sm.c:427 MM(901700000015254/c655d609) -> ACTIVATE PDP CONTEXT REQ: SAPI=3 NSAPI=6 IETF IPv4 /osmo-sgsn/src/sgsn/gprs_sm.c:453:16: runtime error: load of misaligned address 0x61f000064ba3 for type 'uint32_t', which requires 4 byte alignment
0x61f000064ba3: note: pointer points here
 00  06 01 21 00 00 00 00 28  09 27 01 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00
              ^
"""

Change-Id: I8069e3457120b22bb6514fd5d192bff486d7d87f
2023-05-03 11:35:24 +02:00
Oliver Smith a86056fdf3 debian: set compat level to 10
Related: OS#5958
Change-Id: Ib45ad7c44cdefa4c5acab2da09f24796253a133d
2023-04-25 16:48:32 +02:00
Vadim Yanitskiy 99ec755643 tests: $(BUILT_SOURCES) is not defined, depend on osmo-sgsn
Change-Id: I4f9e99ed3673bb51fa5f7d374c35c3c92735eacb
2023-03-30 02:11:21 +07:00
Pau Espin d5dca3a67f gmm: Ciphering Key Sequence Number IE has half octet tag
As per 3GPP TS 24.008:
* 10.5.1.2 Ciphering Key Sequence Number
* Table 9.4.9/TS 24.00

The IE is so far being encoded manually, hence why it worked fine until
now.

Change-Id: Ic220113f30377a14cbe3550a04cd04f3caef49cf
2023-03-22 13:36:35 +01:00
Vadim Yanitskiy 3c26a1dc3c tests: use -no-install libtool flag to avoid ./lt-* scripts
This option should be used for any executables which are used only
for testing, or for generating other files and are consequently never
installed.  By specifying this option, we are telling Libtool that
the executable it links will only ever be executed from where it is
built in the build tree.  Libtool is usually able to considerably
speed up the link process for such executables.

Change-Id: I8af6a38d7abbf06aa8268981c80c3bfda2f80a27
2023-03-11 05:02:17 +07:00
arehbein 642019f288 Transition to use of 'telnet_init_default'
Related: OS#5809
Change-Id: Icc57c68337d55c6594c1c36e9bf41624d11dab0a
2023-02-26 21:16:12 +01:00
Oliver Smith f8a5066ad0 Run struct_endianness.py
Ensure there is no diff to prepare to run this in CI.

Related: OS#5884
Change-Id: I808afd0e9833e6e99d30a37675cbd200ced027e4
2023-02-20 10:51:48 +01:00
Pau Espin 8c42673eba Bump version: 1.9.0.56-07fe-dirty → 1.10.0
Change-Id: I89eb79ffeb28b8dae5b4a5c3cc1142d07052692c
2023-02-07 17:34:27 +01:00
Pau Espin 07feb06d54 Fix extra whitespace in pdpctx_ctr_description
Change-Id: I4d9145c681e725b709fde38f6e9b4516d37b4d8c
2023-01-11 12:58:23 +01:00
Pau Espin 86b630cfe1 vty: Introduce encryption cipher-plugin-path command
The load of plugins will eventually be moved to libosmo-gprs
implementation, and path will be passed as a parameter. Once it's moved
inside libosmo-gprs, it will be more strict on load failures, which can
cause internally if the path doesn't exist (unless NULL is passed).
Hence, add a VTY config to allow configuring the right path, and have it
disabled by default.

Change-Id: I4f965c7afafa193f4d7486750dd3e43cca22bb65
2023-01-11 12:58:23 +01:00
Pau Espin 93bc518b53 Move global mmctx list into struct sgsn_instance
Change-Id: Idf8458902321da03b9b0831dad3ad383a9c7afa1
2023-01-11 12:58:23 +01:00
Pau Espin 58101ea587 Split gprs_sgsn.{c,h} -> {auth,mmctx,sgsn}.{c,h}
Some level of split already existed, like sgsn_auth.c, but headers were
entangled together.
Let's clearly separate application centric code (sgsn.c/h), auth related
code (auth.c/h) and mmctx related code (mmctx.c/h).

Change-Id: I048a082851c1275c959649942904205b02acce2a
2023-01-11 12:58:15 +01:00
Pau Espin 6aad14c3fa gtphub.h: Remove dependency on sgsn/gprs_sgsn.h
It is only really needed to import define GSM_APN_LENGTH, which is
actually also available in libosmogsm. Hence simply use the one from
libosmogsm.

Change-Id: I4c6110feeeaa1adfb6b1f0147eeb56dfe34636ec
2023-01-11 12:51:38 +01:00
Pau Espin f44dfa8a0e Rename bscconfig.h -> config.h
Change-Id: I007103be34c1aaab7a9375c44b226d4590fe5b24
2023-01-11 12:51:38 +01:00
Pau Espin e931b39b3c Move LOGGSUBSCRP to gprs_subscriber.h
The define belongs to gprs_subscriber.h header.

Change-Id: Icdb7e55ca8e90dd2ba79ccdb1a8ba650a3942ab3
2023-01-11 12:51:38 +01:00
Pau Espin fd9e82da31 Move sgsn_ctrl_cmds_install() declaration to sgsn.h
sgsn.h is the main header containing all misc app related contents.
This is another step towards shrinking gprs_sgsn.h mess.

Change-Id: I80e3a68e2e368d8c73135c850e4728bdf6cf5f09
2023-01-11 12:51:38 +01:00
Pau Espin f2307c483f Move gtphub header to include/osmocom/gtphub/
Change-Id: I82e1f2a3bc8e22b28747a540879bd661f1704cde
2023-01-11 12:51:38 +01:00
Pau Espin 15a52d92c4 Move global pdp_list inside struct sgsn_instance
This way pdp contexts are managed by the lifcycle of the main global struct
sgsn_instance automatically.

Change-Id: I725218fd54adcc68dceded5eb43675f25771bb96
2023-01-11 12:51:38 +01:00
Pau Espin 05190c36bb Move sgsn_pdp_ctx to its own file pdpctx.{c,h}
This further shrinks the mess in gprs_sgsn.h, and allows to easily see
layer violations (like pdpctx.c requiring llc.h)

Change-Id: Iad4da06efee7d8514ff48423bdaebc0f26413cc1
2023-01-11 12:51:34 +01:00
Pau Espin 3d3c8c55f0 Drop extern declarations of global sgsn_instance in source files
There's an extern declaration already in sgsn.h.

Change-Id: I2375e13c8436a069e8fe60136c8e1759a9adc2d1
2023-01-11 12:46:34 +01:00
Pau Espin 164a1eeb8a Move extern declarations of tall_sgsn_ctx to sgsn.h
Change-Id: Ifbd54b2e92db8d4a0e0cd1c569cfd83dd85165b8
2023-01-11 12:43:18 +01:00
Pau Espin 69569879ae gtp_{ggsn,mme}: Allocate contexts under struct sgsn_instance
This way apns are managed by the lifcycle of the main global struct
sgsn_instance automatically.

Change-Id: Ie65d59632a368c6957c33dca64e856ace792b2c6
2023-01-11 12:31:23 +01:00
Pau Espin fd4d435442 Move global apn_list inside struct sgsn_instance
This way apns are managed by the lifcycle of the main global struct
sgsn_instance automatically.

Change-Id: I8cc8e540cfb64d0f130e9c0aaedf7b0835f8fe16
2023-01-05 19:37:07 +01:00
Pau Espin 8ec269a0e0 Move gtp related functions to gtp.h
The functions are implemented in sgsn_libgtp.c and hence belong to
header file gtp.h

Change-Id: I7f5cf2895b05e03435769548b61051e6284ccb3c
2023-01-05 19:20:43 +01:00
Pau Espin 4bd6f663a7 sndcp: Standarize unitdata function naming
Use sndcp_<sap>_type>_<op> so that it's easier to distinguish and
identify them.

Change-Id: Ib8825570a8f61d0a28d631f86f5244e70d3194aa
2023-01-05 19:00:56 +01:00
Pau Espin 52c9b8e593 Move func defintions of funcs implemented in gprs_sndcp.c to gprs_sndcp.h
Move them to the correct header where they belong, so that the all the
related protocol stuff is placed together.

Change-Id: I9052f48a0af125bb445194f4ae94ebbe49508fda
2023-01-05 18:57:39 +01:00
Pau Espin 51028e2c16 Properly split llc->sndcp->gtp unitdata pathi through extra func call
Beforehand the function handling the LL-UNITDATA primitive from LLC was
already submitting the packet to GTP code which had an SNDCP related
name, so everything was really confusing and layer separation was not
clean.

Change-Id: Ia544a9dd4c0c7647b0c1b64ca110351f40820618
2023-01-05 18:46:23 +01:00
Pau Espin e69f460ae7 sgsn.h: Drop declaration of non existing function
Change-Id: Idabea56d1ff89e51b517b15771a5a1ed3b050ec9
2023-01-05 18:23:03 +01:00
Pau Espin 0e707fc83a Move struct sgsn_subscriber_pdp_data to gprs_subscriber.h
The functions driving its lifcyecles are already in gprs_subscriber.c,
and are used mainly by functions in the same file, hence move it to the
related header to further shrink gprs_sgsn.h.

Change-Id: Iff7be91af130a3317d57d3649c17e3d5d2540e7a
2023-01-05 17:48:17 +01:00
Pau Espin ffd6e37eb5 Move struct apn_ctx and APN related definitions to its own file
This allows further shrinking of gprs_sgsn.{c,h} and also being able to
use GSM_APN_LENGTH on different headers easily (needed by follow-up
patch).

Change-Id: Id225ed8b84e1376f4a30f17dd4b153b6b1a6efa8
2023-01-05 17:45:28 +01:00
Pau Espin 44bde6b85a Move global ggsn_list into struct sgsn_instance
Change-Id: I9d4c74476b777a866af2796dd376ed50da7b5d01
2023-01-05 17:23:43 +01:00
Pau Espin e659f75cf1 Keep sgsn subsystems under struct sgsn_instance lifecycle
Rework initialization and destruction of several sgsn subsystems to be
allocated & released together with the struct sgsn_instance.

This makes it easier to destroy and recreate the entire context and
allows us to start moving global variables scattered around to be under
struct sgsn_instance.

Change-Id: Idf60519b8e475b94d38bbb69e737132a5afaefab
2023-01-05 17:23:43 +01:00
Pau Espin 67e71eac1c Remove unneeded extern declaration from libosmocotrl
Change-Id: I464df2d03538c71f6666046c67170746690e723d
2023-01-05 17:23:43 +01:00
Pau Espin c1cf4af11b Move related structs to gprs_subscriber.h
This allows shrinking a bit more gprs_sgsn.h and and in turn have
everything much more tidy.

Change-Id: Ie39b48a0d612aa632327cc5a21c833b05f5bf297
2023-01-05 15:43:29 +01:00
Pau Espin f37aedbf76 Fix -Werror=old-style-definition
Change-Id: I119d4ba58d9c68df12b433b0cee924468a1473d8
2023-01-05 14:25:47 +01:00
Pau Espin 920c6c8c81 Introduce new header file sgsn/gtp.h
It will be used to store all stuff relatd to libgtp use and GTP
protocol, similar to what we already do for other protocols.

Change-Id: I4aae35cd0ea401856cd822cb507d668350d07a89
2023-01-05 14:15:52 +01:00
Pau Espin df203361e8 Move gprs_sndcp_vty_init() declaration to gprs_sndcp.h
Change-Id: Iea9692e7ef9bd017d89ef654d2f2ae5b30cc4550
2023-01-05 14:15:52 +01:00
Pau Espin b61ab9b9ac gprs_subscriber: Move API declarations to correct header
Change-Id: Iaa1032c38fa54ad57c472d9120cfbb34b2ae90e9
2023-01-05 14:15:50 +01:00
Pau Espin 5f4736aa85 Move struct sgsn_ggsn_ctx to its own file gtp_ggsn.{c,h}
Similar to what we already have for struct sgsn_mme_ctx in
gtp_mme.{c,h}.

This is just the nth step of properly splitting different
protocol layers, data model, etc.

Change-Id: Iad1895f09e43e299df7bb126bf52fdb98268392e
2023-01-05 00:11:57 +01:00
Pau Espin fc1a5538d0 Replace gprs_str_to_apn() with libosmocore API osmo_apn_from_str()
The exact same function exists in libosmocore with a different naming.

Change-Id: Ibef55a648f2d58f4fdd24fa553efde530982af2d
2023-01-04 19:56:39 +01:00
Pau Espin eb967fccb2 Remove unused function gprs_parse_mi_tmsi()
Change-Id: I6fb7688bf54c7ae3ca3e06bf3a1b729fa62d82f9
2023-01-04 16:29:43 +01:00
Pau Espin 13c00008b4 Standarize lle and llme state enum & value_string
Change-Id: Iaf102ce5ca60854fe7eb1af17c73a80e7c76181b
2023-01-04 13:57:52 +01:00
Pau Espin e5614e434f vty: Fix wrong value_string used to print llme state
Change-Id: Id3eec91b47029964092087858e4ae3a824929ce3
2023-01-04 13:53:57 +01:00
Pau Espin b0b582bff8 cosmetic: gprs_llc_vty.c: Fix trailing whitespace
Change-Id: I543fd784f7e1a0f7c82bd7c79e073104becc88da
2023-01-04 13:49:22 +01:00
Pau Espin bc46812bd7 Move gprs_tmr_to_secs() to tests/gprs/gprs_test.c
That function is only used in the test. Let's hence move the function to
the same test file in order to simplify osmo-sgsn code.

Change-Id: I69d80810362d75eb93974af34f61639514f99f8a
2023-01-02 13:38:01 +01:00
Pau Espin 4398ac073b Rename gprs_gb.[c,h] -> gprs_ns.[c,h]
All remaining code in that file is NS protocol related, hence let's
rename it so that we end up with one file per protocol in the Gb stack.

Change-Id: I8312c8a70d60cab48764950c5b57ca02964e9db2
2022-12-28 23:14:20 +01:00
Pau Espin 05d5f28e93 Move some functions gprs_gb.[c,h] -> gprs_gmm.[c,h]
This leaves only NS protocol related code in gprs_gb.[c,h], which will
be renamed to gprs_ns.[c,h] in a follow up patch.

Change-Id: I3dcbe1d0f75cb91ec8b700e239e2ba16fff030a2
2022-12-28 23:12:47 +01:00
Pau Espin 7a74ae492e Create new specific file for BSSGP code
Right now there's no much code there since the related code is totally
entangled with the LLC one.
This will eventually change in the future when we switch to use
libosmo-gprs.
Hence, this commit is a preparation to have already some place to put
new BSSGP specific code in the future.

Change-Id: I816396ab5ccb86032bbc21b41a959934a7768780
2022-12-28 23:11:49 +01:00
Pau Espin 749ca7c850 Move gprs_gb_parse.[c,h] to tests/sgsn/
That big file is really only used by tests/sgsn/sgsn_test nowadays, so
let's keep it out of osmo-sgsn app code base.

Change-Id: Ia5a639832f52b2f015a2800bd0d94a28d7bc689b
2022-12-22 19:49:39 +01:00
Max e7ccfdb4aa ctrl: take both address and port from vty config
Change-Id: Ie1330b152a2e5cdcdb80a1c958e7c1d784b78eab
2022-12-17 21:16:58 +03:00
Oliver Smith e39ff86dd9 osmo-gtphub.cfg: fix conflict with osmo-ggsn.cfg
Change bind-to-ggsns from 127.0.0.2 to 127.0.0.20, so osmo-gtphub's
default config does not confligt with the osmo-ggsn default config. This
change is for the effort of making the configs of all Osmocom programs
not conflict with each other.

A similar change was made in Id892e1f4ab2daabbe9824b819b5fed985373b97a
with bind-to-sgsns.

Related: OS#5817
Change-Id: I57ee457b62139d831707b6ebd6baaea8d33c2d9c
2022-12-08 16:28:32 +01:00
Pau Espin 57b63875c7 sndcp: Put decompress handling code into helper function
This further simplifies code and avoids duplicating it.

Change-Id: Id83f9e4a87139de2b2f64c8523460c186d5b5649
2022-12-06 12:06:26 +01:00
Oliver Smith 55e3dc8ec8 sgsn_libgtp: cb_data_ind: remove mm_idle assert
Log an error message and drop the packet instead of asserting if
mm state fsm is in ST_MM_IDLE while the gmm fsm is in
ST_GMM_REGISTERED_NORMAL.

Fixes: OS#5725
Change-Id: I9dab98917c622b36dae22399bb359d747a598208
2022-11-17 14:08:30 +01:00
Oliver Smith acd967a177 contrib/jenkins.sh: use enable-werror with IU too
Now that the warnings in osmo-iuh have been fixed, we should be able to
build the IU version of OsmoSGSN with --enable-werror too.

Related: OS#4462
Change-Id: I8cc4e209e21acfe513bef72927499f1ccdead783
2022-11-15 13:01:25 +01:00
Pau Espin 8501126031 vty: Make new libgtp tdefs configurable through VTY
Related: OS#5485
Depends: osmo-ggsn.git Change-Id I10bc8e2e197c0e8753b23b684b5ae41025672bf7
Change-Id: I46e9cd158a9f2f721c69f807beb7bb67a459f4a4
2022-11-04 14:27:30 +01:00
Max b43496a60d GMM: permit E_GMM_COMMON_PROC_SUCCESS in normal state
The FSM might be moved out of ST_GMM_COMMON_PROC_INIT state either
by E_GMM_ATTACH_SUCCESS or by E_GMM_COMMON_PROC_SUCCESS events
which are not mutually exclusive. Hence the later event will arrive when we're already in
the ST_GMM_REGISTERED_NORMAL state.

Let's have both events permitted to keep the logs clean from useless error.

Related: OS#5349
Change-Id: Ia97b50aac6c665812ddca9010de7f97b17b78bd5
2022-10-14 15:04:36 +03:00
Max caff83e702 Constify LLC/SNDCP parameters
That makes it easier to track side-effects while reading the code.

Related: OS#5349
Change-Id: I903f8a747a8d3b7f734dac7b0c12373ecbb90b11
2022-10-11 10:54:39 +03:00
Max 61f2186592 GTP: migrate from deprecated function
The gtp_set_cb_recovery3() is similar to gtp_set_cb_recovery2()
with extra parameter representing GSN.

Change-Id: I8b46cf8c52e36b0312eddf37f3e136662b95732e
2022-10-11 10:54:39 +03:00
Max 559636a4a2 SNDCP: log more details on failure
Related: OS#5349
Change-Id: Iad3ebbc28909a827db7b3a0ae2d3e1de7991210f
2022-10-08 20:24:22 +03:00
Vadim Yanitskiy 13ccbc1e61 llc: gprs_llc_fcs(): make the input data pointer const
Change-Id: If95210fe69f915ab1010fe5916cb6bee3faeb7b9
2022-09-08 12:51:54 +00:00
Vadim Yanitskiy d32852664d gprs_llc.h: use '#pragma once'
Change-Id: Iff748fe68dbef83589bfb5e3bea5183deb365fa6
2022-09-08 12:51:43 +00:00
Max 77cdc424cb Set working directory in systemd service file
By default systemd will execute service with root directory (or home directory for user instance) which might result in
attempts to create files in unexpected place. Let's set it to 'osmocom' subdir of state directory (/var/lib for system instance) instead.

Related: OS#4821
Change-Id: I950d84853c6737276d02b3275127b499ae567c38
2022-08-30 19:42:59 +07:00
Vadim Yanitskiy fb6cf3221e gprs_llc: fix misleading spacing in gprs_llc_rcvmsg()
Change-Id: I7ec97a7d9b37f0541887bc13e31f547613f8945e
2022-08-26 05:38:33 +07:00
Vadim Yanitskiy c63a8381e5 configure.ac: do not require unused dlsym/dlopen
Change-Id: I90b383ed45b27d8b59272116dd81acb72912349d
2022-08-16 23:31:22 +07:00
98 changed files with 2092 additions and 1527 deletions

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

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

4
.gitignore vendored
View File

@ -6,8 +6,8 @@ debian/*.log
.deps
Makefile
Makefile.in
bscconfig.h
bscconfig.h.in
config.h
config.h.in
*.*~
*.sw?
.libs

View File

@ -19,7 +19,7 @@ SUBDIRS = \
BUILT_SOURCES = $(top_srcdir)/.version
EXTRA_DIST = \
.version \
contrib/osmo-sgsn.spec.in \
README.md \
debian \
git-version-gen \
osmoappdesc.py \

View File

@ -1,28 +1,30 @@
osmo-sgssn - Osmocom SGSN Implementation
========================================
osmo-sgsn - Osmocom SGSN Implementation
=======================================
This repository contains a C-language implementation of a GSM Serving GPRS
Support Node (SGSN) for 2G (GSM) and 3G (UMTS). It is part of the
This repository contains a C-language implementation of a *Serving GPRS
Support Node (SGSN)* for 2.5/2.75G (GPRS/EDGE) and 3G (UMTS). It is part of the
[Osmocom](https://osmocom.org/) Open Source Mobile Communications
project.
OsmoSGSN exposes
* Gb towards PCUs (e.g. OsmoPCU): Various GbIP flavors + Gb/FR/E1
* GTP towards a GGSN (e.g. OsmoGGSN);
* IuPS over IP towards RNCs / HNBGW (e.g. osmo-hnbgw)
* The Osmocom typical telnet VTY and CTRL interfaces.
* The Osmocom typical statsd exporter.
* GSUP (custom MAP-like protocol) towards osmo-hlr
* *Gb* towards PCUs (e.g. [OsmoPCU](https://osmocom.org/projects/osmopcu/wiki/OsmoPCU)): Various GbIP flavors + Gb/FR/E1
* *GTP* towards a GGSN (e.g. [OsmoGGSN](https://osmocom.org/projects/openggsn/wiki))
* IuPS over IP towards RNCs / HNBGW (e.g. [osmo-hnbgw](https://osmocom.org/projects/osmohnbgw/wiki))
* The Osmocom typical telnet *VTY* and *CTRL* interfaces.
* The Osmocom typical *statsd* exporter.
* GSUP (custom MAP-like protocol) towards [osmo-hlr](https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR)
OsmoSGSN implements
* GPRS mobility management
* GPRS session management
Homepage
--------
You can find the OsmoSGSN issue tracker and wiki online at
<https://osmocom.org/projects/osmosgsn> and <https://osmocom.org/projects/osmosgsn/wiki>.
You can find the OsmoSGSN homepage online at <https://osmocom.org/projects/osmosgsn/wiki>.
GIT Repository
@ -46,6 +48,14 @@ Pre-rendered PDF version of the current "master" can be found at
as well as the [VTY Reference Manual](https://ftp.osmocom.org/docs/latest/osmosgsn-vty-reference.pdf)
Forum
-----
We welcome any osmo-sgsn related discussions in the
[Cellular Network Infratructure -> 2G/3G Core Network](https://discourse.osmocom.org/c/cni/2g-3g-cn).
section of the osmocom discourse (web based Forum).
Mailing List
------------
@ -58,6 +68,15 @@ Please observe the [Osmocom Mailing List
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
when posting.
Issue Tracker
-------------
We use the [issue tracker of the osmo-sgsn project on osmocom.org](https://osmocom.org/projects/osmosgsn/issues) for
tracking the state of bug reports and feature requests. Feel free to submit any issues you may find, or help
us out by resolving existing issues.
Contributing
------------

View File

@ -1 +1,2 @@
#component what description / commit summary line
libosmocore > 1.9.0 gsup.h: Using new fields in struct osmo_gsup_pdp_info (ABI break)

View File

@ -38,30 +38,23 @@ dnl use a defined standard across all builds and don't depend on compiler defaul
CFLAGS="$CFLAGS -std=gnu11"
dnl checks for libraries
AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
AC_SUBST(LIBRARY_DL)
AC_SEARCH_LIBS([dlsym], [dl dld], [LIBRARY_DLSYM="$LIBS";LIBS=""])
AC_SUBST(LIBRARY_DLSYM)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.7.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.3.0)
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.2.0)
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.5.0)
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.9.0)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.9.0)
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.9.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.5.0)
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.4.0)
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.7.0)
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.11.0)
# Enable/disable 3G aka IuPS + IuCS support?
AC_ARG_ENABLE([iu], [AS_HELP_STRING([--enable-iu], [Build 3G support, aka IuPS and IuCS interfaces])],
[osmo_ac_iu="$enableval"],[osmo_ac_iu="no"])
if test "x$osmo_ac_iu" = "xyes" ; then
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.6.0)
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.8.0)
PKG_CHECK_MODULES(LIBASN1C, libasn1c >= 0.9.30)
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 1.3.0)
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 1.5.0)
AC_DEFINE(BUILD_IU, 1, [Define if we want to build IuPS and IuCS interfaces support])
fi
AM_CONDITIONAL(BUILD_IU, test "x$osmo_ac_iu" = "xyes")
@ -237,11 +230,12 @@ AC_MSG_RESULT([CFLAGS="$CFLAGS"])
AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
dnl Generate the output
AM_CONFIG_HEADER(bscconfig.h)
AM_CONFIG_HEADER(config.h)
AC_OUTPUT(
include/Makefile
include/osmocom/Makefile
include/osmocom/gtphub/Makefile
include/osmocom/sgsn/Makefile
src/Makefile
src/gprs/Makefile
@ -261,5 +255,4 @@ AC_OUTPUT(
doc/manuals/Makefile
contrib/Makefile
contrib/systemd/Makefile
contrib/osmo-sgsn.spec
Makefile)

View File

@ -37,14 +37,11 @@ osmo-build-dep.sh libosmo-netif
osmo-build-dep.sh osmo-ggsn
osmo-build-dep.sh osmo-hlr
enable_werror=""
if [ "x$IU" = "x--enable-iu" ]; then
osmo-build-dep.sh libosmo-sccp
osmo-build-dep.sh libasn1c
#osmo-build-dep.sh asn1c aper-prefix # only needed for make regen in osmo-iuh
osmo-build-dep.sh osmo-iuh
else
enable_werror="--enable-werror"
fi
# Additional configure options and depends
@ -63,12 +60,12 @@ set -x
cd "$base"
autoreconf --install --force
./configure --enable-sanitize $enable_werror $IU --enable-external-tests $CONFIG
./configure --enable-sanitize --enable-werror $IU --enable-external-tests $CONFIG
$MAKE $PARALLEL_MAKE
LD_LIBRARY_PATH="$inst/lib" $MAKE check \
|| cat-testlogs.sh
LD_LIBRARY_PATH="$inst/lib" \
DISTCHECK_CONFIGURE_FLAGS="$enable_werror $IU --enable-external-tests $CONFIG" \
DISTCHECK_CONFIGURE_FLAGS="--enable-werror $IU --enable-external-tests $CONFIG" \
$MAKE $PARALLEL_MAKE distcheck \
|| cat-testlogs.sh

View File

@ -1,118 +0,0 @@
#
# spec file for package osmo-sgsn
#
# Copyright (c) 2017, Martin Hauke <mardnh@gmx.de>
#
# 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/4116
%define _lto_cflags %{nil}
%define with_iu 1
Name: osmo-sgsn
Version: @VERSION@
Release: 0
Summary: Osmocom's SGSN for 2G and 3G packet-switched mobile networks
License: AGPL-3.0-or-later AND GPL-2.0-or-later
Group: Productivity/Telephony/Servers
URL: https://osmocom.org/projects/osmosgsn
Source: %{name}-%{version}.tar.xz
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libtool
BuildRequires: pkgconfig
%if 0%{?suse_version}
BuildRequires: systemd-rpm-macros
%endif
BuildRequires: pkgconfig(libcares)
BuildRequires: pkgconfig(libcrypto) >= 0.9.5
BuildRequires: pkgconfig(libgtp) >= 1.9.0
BuildRequires: pkgconfig(libosmo-gsup-client) >= 1.5.0
BuildRequires: pkgconfig(libosmo-netif) >= 1.2.0
BuildRequires: pkgconfig(libosmoabis) >= 1.3.0
BuildRequires: pkgconfig(libosmocore) >= 1.7.0
BuildRequires: pkgconfig(libosmoctrl) >= 1.7.0
BuildRequires: pkgconfig(libosmogb) >= 1.7.0
BuildRequires: pkgconfig(libosmogsm) >= 1.7.0
BuildRequires: pkgconfig(libosmovty) >= 1.7.0
%{?systemd_requires}
%if %{with_iu}
BuildRequires: pkgconfig(libasn1c)
BuildRequires: pkgconfig(libosmo-ranap) >= 1.3.0
BuildRequires: pkgconfig(libosmo-sigtran) >= 1.6.0
%endif
%description
OsmoSGSN is Osmocom's Serving GPRS Support Node for 2G and 3G
packet-switched mobile networks.
%package -n osmo-gtphub
Summary: Osmocom GTP Hub: Proxy for GTP traffic between multiple SGSNs and GGSNs
Group: Productivity/Telephony/Servers
%description -n osmo-gtphub
Osmocom GTP Hub: Proxy for GTP traffic between multiple SGSNs and GGSNs.
%prep
%setup -q
%build
echo "%{version}" >.tarball-version
autoreconf -fi
%configure \
%if %{with_iu}
--enable-iu \
%endif
--docdir=%{_docdir}/%{name} \
--with-systemdsystemunitdir=%{_unitdir}
make %{?_smp_mflags}
%install
%make_install
%if 0%{?suse_version}
%preun %service_del_preun %{name}.service
%postun %service_del_postun %{name}.service
%pre %service_add_pre %{name}.service
%post %service_add_post %{name}.service
%preun -n osmo-gtphub %service_del_preun osmo-gtphub.service
%postun -n osmo-gtphub %service_del_postun osmo-gtphub.service
%pre -n osmo-gtphub %service_add_pre osmo-gtphub.service
%post -n osmo-gtphub %service_add_post osmo-gtphub.service
%endif
%check
make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%files
%doc AUTHORS README.md
%dir %{_docdir}/%{name}/examples
%dir %{_docdir}/%{name}/examples/osmo-sgsn
%exclude %{_docdir}/%{name}/examples/osmo-gtphub
%{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn-accept-all.cfg
%{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn.cfg
%{_docdir}/%{name}/examples/osmo-sgsn/osmo-sgsn_custom-sccp.cfg
%{_bindir}/osmo-sgsn
%dir %{_sysconfdir}/osmocom
%config(noreplace) %{_sysconfdir}/osmocom/osmo-sgsn.cfg
%{_unitdir}/%{name}.service
%files -n osmo-gtphub
%dir %{_docdir}/%{name}/examples
%dir %{_docdir}/%{name}/examples/osmo-gtphub
%{_docdir}/%{name}/examples/osmo-gtphub/osmo-gtphub-1iface.cfg
%{_docdir}/%{name}/examples/osmo-gtphub/osmo-gtphub.cfg
%{_bindir}/osmo-gtphub
%dir %{_sysconfdir}/osmocom
%config(noreplace) %{_sysconfdir}/osmocom/osmo-gtphub.cfg
%{_unitdir}/osmo-gtphub.service
%changelog

View File

@ -1,9 +1,15 @@
[Unit]
Description=Osmocom GTP Hub
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=osmocom
Group=osmocom
ExecStart=/usr/bin/osmo-gtphub -c /etc/osmocom/osmo-gtphub.cfg
StateDirectory=osmocom
WorkingDirectory=%S/osmocom
Restart=always
RestartSec=2
RestartPreventExitStatus=1

View File

@ -3,10 +3,16 @@ Description=Osmocom SGSN (Serving GPRS Support Node)
Wants=osmo-hlr.service
After=osmo-hlr.service
After=osmo-hnbgw.service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
StateDirectory=osmocom
WorkingDirectory=%S/osmocom
Restart=always
User=osmocom
Group=osmocom
ExecStart=/usr/bin/osmo-sgsn -c /etc/osmocom/osmo-sgsn.cfg
RestartSec=2

111
debian/changelog vendored
View File

@ -1,3 +1,114 @@
osmo-sgsn (1.11.1) unstable; urgency=medium
[ Philipp Maier ]
* sgsn_rim: forward message based on RIM ROUTING ADDRESS
[ Daniel Willmann ]
* sgsn_vty: Fix output in config_write_sgsn
* sgsn_vty: Correctly indent encryption cipher-plugin-path
* vty-tests: Test encryption options
* libgtp: Check for all successful create_pdp_conf causes
-- Oliver Smith <osmith@sysmocom.de> Tue, 28 Nov 2023 13:32:46 +0100
osmo-sgsn (1.11.0) unstable; urgency=medium
[ Oliver Smith ]
* Run struct_endianness.py
* debian: set compat level to 10
* systemd: depend on networking-online.target
[ arehbein ]
* Transition to use of 'telnet_init_default'
[ Vadim Yanitskiy ]
* tests: use -no-install libtool flag to avoid ./lt-* scripts
* tests: $(BUILT_SOURCES) is not defined, depend on osmo-sgsn
* copyright: fix typo: sysmocom s/s.m.f.c./s.f.m.c./ GmbH
[ Pau Espin Pedrol ]
* gmm: Ciphering Key Sequence Number IE has half octet tag
* gprs_sm.c: Fix load of misaligned ptr address
* Write explicit role & sctp-role fields in ASP configurations
* gmm: Update DRX params during rx RAU REQ
* gmm: Add missing GSM48_IE_GMM_RX_NPDU_NUM_LIST IE in gsm48_gmm_att_tlvdef
[ Philipp Maier ]
* sgsn_rim: fix typo
* sgsn_rim: cosmetic: improve comment
* sgsn_rim: get rid of MME check in sgsn_rim_rx_from_gtp:
* sgsn_rim: do not check the origin of a RIM message
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 12 Sep 2023 16:57:02 +0200
osmo-sgsn (1.10.0) unstable; urgency=medium
[ Vadim Yanitskiy ]
* configure.ac: do not require unused dlsym/dlopen
* gprs_llc: fix misleading spacing in gprs_llc_rcvmsg()
* gprs_llc.h: use '#pragma once'
* llc: gprs_llc_fcs(): make the input data pointer const
[ Max ]
* Set working directory in systemd service file
* SNDCP: log more details on failure
* GTP: migrate from deprecated function
* Constify LLC/SNDCP parameters
* GMM: permit E_GMM_COMMON_PROC_SUCCESS in normal state
* ctrl: take both address and port from vty config
[ Pau Espin Pedrol ]
* vty: Make new libgtp tdefs configurable through VTY
* sndcp: Put decompress handling code into helper function
* Move gprs_gb_parse.[c,h] to tests/sgsn/
* Create new specific file for BSSGP code
* Move some functions gprs_gb.[c,h] -> gprs_gmm.[c,h]
* Rename gprs_gb.[c,h] -> gprs_ns.[c,h]
* Move gprs_tmr_to_secs() to tests/gprs/gprs_test.c
* cosmetic: gprs_llc_vty.c: Fix trailing whitespace
* vty: Fix wrong value_string used to print llme state
* Standarize lle and llme state enum & value_string
* Remove unused function gprs_parse_mi_tmsi()
* Replace gprs_str_to_apn() with libosmocore API osmo_apn_from_str()
* Move struct sgsn_ggsn_ctx to its own file gtp_ggsn.{c,h}
* gprs_subscriber: Move API declarations to correct header
* Move gprs_sndcp_vty_init() declaration to gprs_sndcp.h
* Introduce new header file sgsn/gtp.h
* Fix -Werror=old-style-definition
* Move related structs to gprs_subscriber.h
* Remove unneeded extern declaration from libosmocotrl
* Keep sgsn subsystems under struct sgsn_instance lifecycle
* Move global ggsn_list into struct sgsn_instance
* Move struct apn_ctx and APN related definitions to its own file
* Move struct sgsn_subscriber_pdp_data to gprs_subscriber.h
* sgsn.h: Drop declaration of non existing function
* Properly split llc->sndcp->gtp unitdata pathi through extra func call
* Move func defintions of funcs implemented in gprs_sndcp.c to gprs_sndcp.h
* sndcp: Standarize unitdata function naming
* Move gtp related functions to gtp.h
* Move global apn_list inside struct sgsn_instance
* gtp_{ggsn,mme}: Allocate contexts under struct sgsn_instance
* Move extern declarations of tall_sgsn_ctx to sgsn.h
* Drop extern declarations of global sgsn_instance in source files
* Move sgsn_pdp_ctx to its own file pdpctx.{c,h}
* Move global pdp_list inside struct sgsn_instance
* Move gtphub header to include/osmocom/gtphub/
* Move sgsn_ctrl_cmds_install() declaration to sgsn.h
* Move LOGGSUBSCRP to gprs_subscriber.h
* Rename bscconfig.h -> config.h
* gtphub.h: Remove dependency on sgsn/gprs_sgsn.h
* Split gprs_sgsn.{c,h} -> {auth,mmctx,sgsn}.{c,h}
* Move global mmctx list into struct sgsn_instance
* vty: Introduce encryption cipher-plugin-path command
* Fix extra whitespace in pdpctx_ctr_description
[ Oliver Smith ]
* contrib/jenkins.sh: use enable-werror with IU too
* sgsn_libgtp: cb_data_ind: remove mm_idle assert
* osmo-gtphub.cfg: fix conflict with osmo-ggsn.cfg
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 07 Feb 2023 17:34:26 +0100
osmo-sgsn (1.9.0) unstable; urgency=medium
[ Oliver Smith ]

2
debian/compat vendored
View File

@ -1 +1 @@
9
10

20
debian/control vendored
View File

@ -2,7 +2,7 @@ Source: osmo-sgsn
Section: net
Priority: extra
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
Build-Depends: debhelper (>=9),
Build-Depends: debhelper (>= 10),
dh-autoreconf,
autotools-dev,
autoconf,
@ -11,16 +11,16 @@ Build-Depends: debhelper (>=9),
pkg-config,
libtalloc-dev,
libc-ares-dev,
libgtp-dev (>= 1.9.0),
libosmocore-dev (>= 1.7.0),
libosmo-abis-dev (>= 1.3.0),
libosmo-netif-dev (>= 1.2.0),
libosmo-gsup-client-dev (>= 1.5.0),
libgtp-dev (>= 1.11.0),
libosmocore-dev (>= 1.9.0),
libosmo-abis-dev (>= 1.5.0),
libosmo-netif-dev (>= 1.4.0),
libosmo-gsup-client-dev (>= 1.7.0),
libasn1c-dev (>= 0.9.30),
libosmo-ranap-dev (>= 1.3.0),
libosmo-sigtran-dev (>= 1.6.0),
libosmo-sccp-dev (>= 1.6.0),
osmo-gsm-manuals-dev (>= 1.3.0)
libosmo-ranap-dev (>= 1.5.0),
libosmo-sigtran-dev (>= 1.8.0),
libosmo-sccp-dev (>= 1.8.0),
osmo-gsm-manuals-dev (>= 1.5.0)
Standards-Version: 3.9.8
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn

6
debian/copyright vendored
View File

@ -33,7 +33,6 @@ Files: .gitignore
include/osmocom/sgsn/crc24.h
include/osmocom/sgsn/debug.h
include/osmocom/sgsn/gb_proxy.h
include/osmocom/sgsn/gprs_gb_parse.h
include/osmocom/sgsn/gprs_gmm.h
include/osmocom/sgsn/gprs_llc.h
include/osmocom/sgsn/gprs_sgsn.h
@ -53,6 +52,7 @@ Files: .gitignore
tests/gprs/gprs_test.ok
tests/gtphub/Makefile.am
tests/gtphub/gtphub_test.ok
tests/sgsn/gprs_gb_parse.h
tests/sgsn/Makefile.am
tests/sgsn/sgsn_test.ok
tests/slhc/Makefile.am
@ -74,11 +74,10 @@ Files: include/osmocom/sgsn/a_reset.h
include/osmocom/sgsn/gprs_sndcp_pcomp.h
include/osmocom/sgsn/gprs_sndcp_xid.h
include/osmocom/sgsn/gprs_utils.h
include/osmocom/sgsn/gtphub.h
include/osmocom/gtphub/gtphub.h
include/osmocom/sgsn/signal.h
src/gprs/gprs_llc_parse.c
src/gprs/crc24.c
src/gprs/gprs_gb_parse.c
src/gprs/gprs_utils.c
src/gprs/sgsn_ares.c
src/gtphub/gtphub.c
@ -103,6 +102,7 @@ Files: include/osmocom/sgsn/a_reset.h
src/sgsn/sgsn_main.c
src/sgsn/sgsn_vty.c
tests/gtphub/gtphub_test.c
tests/sgsn/gprs_gb_parse.c
tests/sgsn/sgsn_test.c
tests/slhc/slhc_test.c
tests/sndcp_xid/sndcp_xid_test.c

30
debian/postinst vendored Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh -e
case "$1" in
configure)
# Create the osmocom group and user (if it doesn't exist yet)
if ! getent group osmocom >/dev/null; then
groupadd --system osmocom
fi
if ! getent passwd osmocom >/dev/null; then
useradd \
--system \
--gid osmocom \
--home-dir /var/lib/osmocom \
--shell /sbin/nologin \
--comment "Open Source Mobile Communications" \
osmocom
fi
# Fix permissions of previous (root-owned) install (OS#4107)
chown osmocom:osmocom /etc/osmocom/osmo-sgsn.cfg
chmod 0660 /etc/osmocom/osmo-sgsn.cfg
chown root:osmocom /etc/osmocom
chmod 2775 /etc/osmocom
mkdir -p /var/lib/osmocom
chown -R osmocom:osmocom /var/lib/osmocom
;;
esac
# dh_installdeb(1) will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#

View File

@ -5,6 +5,14 @@
! For the test, try to use most config commands.
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login

View File

@ -2,6 +2,14 @@
! Osmocom gtphub configuration
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login
@ -9,7 +17,7 @@ gtphub
! Local addresses to listen on and send from, each on standard ports
! 2123 and 2152. Setting these addresses is mandatory.
bind-to-sgsns 127.0.0.10
bind-to-ggsns 127.0.0.2
bind-to-ggsns 127.0.0.20
! Local nonstandard ports or separate IPs:
!bind-to-sgsns ctrl 127.0.0.1 2342 user 127.0.0.1 4223

View File

@ -2,6 +2,14 @@
! Osmocom SGSN configuration
!
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login
!

View File

@ -2,6 +2,14 @@
! Osmocom SGSN configuration
!
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login
!

View File

@ -2,6 +2,14 @@
! Osmocom SGSN configuration
!
!
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
line vty
no login
!
@ -9,6 +17,8 @@ cs7 instance 0
point-code 0.23.4
asp asp-clnt-OsmoSGSN-A 2905 0 m3ua
remote-ip 172.18.8.200 ! where to reach the STP
role asp
sctp-role client
as as-clnt-OsmoSGSN-A m3ua
asp asp-clnt-OsmoSGSN-A
routing-key 3 0.23.4

View File

@ -422,6 +422,7 @@ cs7 instance 0
point-code 0.23.4
asp asp-clnt-OsmoSGSN 2905 0 m3ua
remote-ip 127.0.0.1
role asp
sctp-role client
as as-clnt-OsmoSGSN m3ua
asp asp-clnt-OsmoSGSN

View File

@ -15,6 +15,14 @@
Conversion to asciidoc, removal of sysmoBTS specific parts.
</revremark>
</revision>
<revision>
<revnumber>3</revnumber>
<date>April 2024</date>
<authorinitials>AC</authorinitials>
<revremark>
Replace NS chapter with new NS2 chapter to match the code.
</revremark>
</revision>
</revhistory>
<authorgroup>
@ -29,10 +37,21 @@
<jobtitle>Managing Director</jobtitle>
</affiliation>
</author>
<author>
<firstname>Alexander</firstname>
<surname>Couzens</surname>
<email>acouzens@sysmocom.de</email>
<authorinitials>AC</authorinitials>
<affiliation>
<shortaffil>sysmocom</shortaffil>
<orgname>sysmocom - s.f.m.c. GmbH</orgname>
<jobtitle>Developer</jobtitle>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2013-2016</year>
<year>2013-2024</year>
<holder>sysmocom - s.f.m.c. GmbH</holder>
</copyright>
@ -47,8 +66,8 @@
</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 url="https://git.osmocom.org/osmo-gsm-manuals/">
https://git.osmocom.org/osmo-gsm-manuals/
</ulink>
</para>
</legalnotice>

View File

@ -21,7 +21,7 @@ include::{srcdir}/chapters/configuration.adoc[]
include::./common/chapters/cs7-config.adoc[]
include::./common/chapters/gb.adoc[]
include::./common/chapters/gb-ns2.adoc[]
include::./common/chapters/control_if.adoc[]

View File

@ -1,3 +1,4 @@
SUBDIRS = \
gtphub \
sgsn \
$(NULL)

View File

@ -0,0 +1,3 @@
noinst_HEADERS = \
gtphub.h \
$(NULL)

View File

@ -27,9 +27,7 @@
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/gsm/apn.h>
/* support */
@ -428,7 +426,7 @@ struct gtphub_resolved_ggsn {
/* The APN OI, the Operator Identifier, is the combined address,
* including parts of the IMSI and APN NI, and ending with ".gprs". */
char apn_oi_str[GSM_APN_LENGTH];
char apn_oi_str[APN_MAXLEN+1];
/* Which address and port we resolved that to. */
struct gtphub_peer_port *peer;

View File

@ -1,18 +1,19 @@
noinst_HEADERS = \
apn.h \
auth.h \
common.h \
crc24.h \
debug.h \
gprs_gb.h \
gprs_gb_parse.h \
gprs_bssgp.h \
gprs_gmm.h \
gprs_gmm_fsm.h \
gprs_gmm_attach.h \
gprs_mm_state_gb_fsm.h \
gprs_mm_state_iu_fsm.h \
gprs_ns.h \
gprs_llc.h \
gprs_llc_xid.h \
gprs_ranap.h \
gprs_sgsn.h \
gprs_sm.h \
gprs_sndcp_comp.h \
gprs_sndcp_dcomp.h \
@ -21,8 +22,11 @@ noinst_HEADERS = \
gprs_sndcp_xid.h \
gprs_subscriber.h \
gprs_utils.h \
gtphub.h \
gtp.h \
gtp_ggsn.h \
gtp_mme.h \
mmctx.h \
pdpctx.h \
sgsn.h \
sgsn_rim.h \
signal.h \

View File

@ -0,0 +1,20 @@
#pragma once
#include <osmocom/core/linuxlist.h>
struct sgsn_ggsn_ctx;
#define GSM_APN_LENGTH 102
struct apn_ctx {
struct llist_head list;
struct sgsn_ggsn_ctx *ggsn;
char *name;
char *imsi_prefix;
char *description;
};
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix);
void sgsn_apn_ctx_free(struct apn_ctx *actx);
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix);
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi_prefix);

View File

@ -0,0 +1,39 @@
/* MS authorization and subscriber data handling */
#pragma once
#include <osmocom/core/linuxlist.h>
struct sgsn_config;
struct sgsn_instance;
struct sgsn_mm_ctx;
struct gsm_auth_tuple;
/* Authorization/ACL handling */
enum sgsn_auth_state {
SGSN_AUTH_UNKNOWN,
SGSN_AUTH_AUTHENTICATE,
SGSN_AUTH_UMTS_RESYNC,
SGSN_AUTH_ACCEPTED,
SGSN_AUTH_REJECTED
};
extern const struct value_string *sgsn_auth_state_names;
void sgsn_auth_init(struct sgsn_instance *sgsn);
/* Request authorization */
enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm);
int sgsn_auth_request(struct sgsn_mm_ctx *mm);
void sgsn_auth_update(struct sgsn_mm_ctx *mm);
struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
unsigned key_seq);
/*
* Authorization/ACL handling
*/
struct imsi_acl_entry {
struct llist_head list;
char imsi[OSMO_IMSI_BUF_SIZE];
};
struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, const struct sgsn_config *cfg);
int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg);
int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg);

View File

@ -5,6 +5,6 @@
#define INIT_CRC24 0xffffff
uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len);
uint32_t crc24_calc(uint32_t fcs, const uint8_t *cp, unsigned int len);
#endif

View File

@ -0,0 +1,12 @@
#pragma once
#include <osmocom/core/msgb.h>
/* Called by bssgp layer when a prim is received from lower layers. */
int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph);
/* called by the bssgp layer to send NS PDUs */
int sgsn_bssgp_dispatch_ns_unitdata_req_cb(void *ctx, struct msgb *msg);
/* page a MS in its routing area */
int sgsn_bssgp_page_ps_ra(struct sgsn_mm_ctx *mmctx);

View File

@ -1,20 +0,0 @@
#pragma once
#include <stdbool.h>
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_llc.h>
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable);
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg);
/* page a MS in its routing area */
int gprs_gb_page_ps_ra(struct sgsn_mm_ctx *mmctx);
/* called by the bssgp layer to send NS PDUs */
int gprs_gb_send_cb(void *ctx, struct msgb *msg);
/* called by the ns layer */
int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx);

View File

@ -1,11 +1,15 @@
#ifndef _GPRS_GMM_H
#define _GPRS_GMM_H
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <stdbool.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/crypt/auth.h>
struct sgsn_mm_ctx;
struct gprs_llc_llme;
int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm,
const struct osmo_auth_vector *vec,
uint8_t key_seq, bool force_standby);
@ -28,6 +32,11 @@ int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli);
int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
uint8_t suspend_ref);
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable);
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg);
time_t gprs_max_time_to_idle(void);
int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type);

View File

@ -1,8 +1,10 @@
#pragma once
#include <osmocom/core/fsm.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
struct gprs_llc_llme;
/* 3GPP TS 24.008 § 4.1.3.3 GMM mobility management states on the network side */
enum gmm_fsm_states {

View File

@ -1,11 +1,16 @@
#ifndef _GPRS_LLC_H
#define _GPRS_LLC_H
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/core/timer.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/crypt/gprs_cipher.h>
#include <osmocom/sgsn/gprs_llc_xid.h>
struct sgsn_mm_ctx;
/* Section 4.7 LLC Layer Structure */
enum gprs_llc_sapi {
GPRS_SAPI_GMM = 1,
@ -91,6 +96,7 @@ enum gprs_llc_lle_state {
GPRS_LLES_LOCAL_REL = 6, /* Local Release */
GPRS_LLES_TIMER_REC = 7, /* Timer Recovery */
};
extern const struct value_string gprs_llc_lle_state_names[];
enum gprs_llc_llme_state {
GPRS_LLMS_UNASSIGNED = 1, /* No TLLI yet */
@ -272,18 +278,15 @@ static inline int gprs_llc_is_retransmit(uint16_t nu, uint16_t vur)
}
/* LLC low level functions */
void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
void gprs_llme_copy_key(const struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
/* parse a GPRS LLC header, also check for invalid frames */
int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp,
uint8_t *llc_hdr, int len);
void gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph, struct gprs_llc_lle *lle);
int gprs_llc_fcs(uint8_t *data, unsigned int len);
int gprs_llc_fcs(const uint8_t *data, unsigned int len);
/* LLME handling routines */
struct llist_head *gprs_llme_list(void);
struct gprs_llc_lle *gprs_lle_get_or_create(const uint32_t tlli, uint8_t sapi);
#endif

View File

@ -0,0 +1,9 @@
#pragma once
#include <stdbool.h>
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_llc.h>
/* called by the ns layer */
int gprs_ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx);

View File

@ -1,13 +1,15 @@
#pragma once
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#ifdef BUILD_IU
#include <osmocom/ranap/ranap_ies_defs.h>
#include <osmocom/ranap/ranap_msg_factory.h>
#include <osmocom/ranap/iu_client.h>
struct sgsn_mm_ctx;
struct sgsn_pdp_ctx;
void activate_pdp_rabs(struct sgsn_mm_ctx *ctx);
int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data);
int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp);

View File

@ -1,7 +1,10 @@
#pragma once
#include <osmocom/core/msgb.h>
#include <osmocom/sgsn/gprs_sgsn.h>
struct sgsn_mm_ctx;
struct sgsn_pdp_ctx;
struct gprs_llc_llme;
int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause, bool teardown);
int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,

View File

@ -3,6 +3,9 @@
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/gsm48.h>
struct gprs_llc_lle;
/* A fragment queue header, maintaining list of fragments for one N-PDU */
struct defrag_state {
@ -60,6 +63,8 @@ struct gprs_sndcp_entity {
extern struct llist_head gprs_sndcp_entities;
int gprs_sndcp_vty_init(void);
/* Set of SNDCP-XID negotiation (See also: TS 144 065,
* Section 6.8 XID parameter negotiation) */
int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi);
@ -68,7 +73,7 @@ int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi);
* Section 6.8 XID parameter negotiation) */
int sndcp_sn_xid_ind(struct gprs_llc_xid_field *xid_field_indication,
struct gprs_llc_xid_field *xid_field_response,
struct gprs_llc_lle *lle);
const struct gprs_llc_lle *lle);
/* Process SNDCP-XID indication
* (See also: TS 144 065, Section 6.8 XID parameter negotiation) */
@ -77,6 +82,20 @@ int sndcp_sn_xid_conf(struct gprs_llc_xid_field *xid_field_conf,
struct gprs_llc_lle *lle);
/* Clean up all gprs_sndcp_entities related to llme (OS#4824) */
void gprs_sndcp_sm_deactivate_ind_by_llme(struct gprs_llc_llme *llme);
void gprs_sndcp_sm_deactivate_ind_by_llme(const struct gprs_llc_llme *llme);
/* Called by SNDCP when it has received/re-assembled a N-PDU */
int sndcp_sn_unitdata_ind(struct gprs_sndcp_entity *sne, struct msgb *msg,
uint32_t npdu_len, uint8_t *npdu);
int sndcp_sn_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
void *mmcontext);
/* Entry point for the SNSM-ACTIVATE.indication */
int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
/* Entry point for the SNSM-DEACTIVATE.indication */
int sndcp_sm_deactivate_ind(const struct gprs_llc_lle *lle, uint8_t nsapi);
int sndcp_ll_unitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
uint8_t *hdr, uint16_t len);
#endif /* INT_SNDCP_H */

View File

@ -4,10 +4,70 @@
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/socket.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/sgsn/apn.h>
struct sgsn_instance;
struct sgsn_mm_ctx;
extern struct llist_head * const gprs_subscribers;
#define GPRS_SUBSCRIBER_FIRST_CONTACT 0x00000001
#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
#define GPRS_SUBSCRIBER_ENABLE_PURGE (1 << 19)
#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
)
struct gsm_auth_tuple {
int use_count;
int key_seq;
struct osmo_auth_vector vec;
};
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
struct sgsn_subscriber_data {
struct sgsn_mm_ctx *mm;
struct gsm_auth_tuple auth_triplets[5];
int auth_triplets_updated;
struct llist_head pdp_list;
int error_cause;
uint8_t msisdn[9];
size_t msisdn_len;
uint8_t hlr[9];
size_t hlr_len;
uint8_t pdp_charg[2];
bool has_pdp_charg;
};
/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
/* see GSM 09.02, B.1, gprsSubscriptionData */
struct sgsn_subscriber_pdp_data {
struct llist_head list;
unsigned int context_id;
enum gsm48_pdp_type_org pdp_type_org;
enum gsm48_pdp_type_nr pdp_type_nr;
struct osmo_sockaddr pdp_address[2];
char apn_str[GSM_APN_LENGTH];
uint8_t qos_subscribed[20];
size_t qos_subscribed_len;
uint8_t pdp_charg[2];
bool has_pdp_charg;
};
struct sgsn_subscriber_pdp_data *sgsn_subscriber_pdp_data_alloc(struct sgsn_subscriber_data *sdata);
struct gprs_subscr {
struct llist_head entry;
int use_count;
@ -29,3 +89,22 @@ struct gprs_subscr *_gprs_subscr_put(struct gprs_subscr *gsub,
const char *file, int line);
#define gprs_subscr_get(gsub) _gprs_subscr_get(gsub, __FILE__, __LINE__)
#define gprs_subscr_put(gsub) _gprs_subscr_put(gsub, __FILE__, __LINE__)
int gprs_subscr_init(struct sgsn_instance *sgi);
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
const uint8_t *auts,
const uint8_t *auts_rand);
void gprs_subscr_cleanup(struct gprs_subscr *subscr);
struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi);
struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx);
struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi);
void gprs_subscr_cancel(struct gprs_subscr *subscr);
void gprs_subscr_update(struct gprs_subscr *subscr);
void gprs_subscr_update_auth_info(struct gprs_subscr *subscr);
int gprs_subscr_rx_gsup_message(struct msgb *msg);
#define LOGGSUBSCRP(level, subscr, fmt, args...) \
LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
(subscr) ? (subscr)->imsi : "---", \
## args)

View File

@ -29,15 +29,11 @@
struct msgb;
struct gprs_ra_id;
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str);
/* GSM 04.08, 10.5.7.3 GPRS Timer */
int gprs_tmr_to_secs(uint8_t tmr);
uint8_t gprs_secs_to_tmr_floor(int secs);
int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len);
int gprs_is_mi_imsi(const uint8_t *value, size_t value_len);
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi);
void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi);
int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2);

View File

@ -0,0 +1,30 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/gprs/gprs_bssgp_rim.h>
struct gprs_ra_id;
struct sgsn_instance;
struct sgsn_ggsn_ctx;
struct sgsn_pdp_ctx;
struct sgsn_mm_ctx;
struct sgsn_mme_ctx;
int sgsn_gtp_init(struct sgsn_instance *sgi);
int sgsn_mme_ran_info_req(struct sgsn_mme_ctx *mme, const struct bssgp_ran_information_pdu *pdu);
void sgsn_ggsn_echo_req(struct sgsn_ggsn_ctx *ggc);
struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
struct sgsn_mm_ctx *mmctx,
uint16_t nsapi,
struct tlv_parsed *tp);
int sgsn_gtp_data_req(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen);
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx);

View File

@ -0,0 +1,41 @@
#pragma once
#include <stdint.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
#include <osmocom/gprs/protocol/gsm_24_301.h>
struct gsn_t;
struct sgsn_pdp_ctx;
struct sgsn_instance;
struct sgsn_ggsn_ctx {
struct llist_head list;
uint32_t id;
unsigned int gtp_version;
struct in_addr remote_addr;
int remote_restart_ctr;
struct gsn_t *gsn;
struct llist_head pdp_list; /* list of associated pdp ctx (struct sgsn_pdp_ctx*) */
struct osmo_timer_list echo_timer;
unsigned int echo_interval;
};
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(struct sgsn_instance *sgsn, uint32_t id);
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(struct sgsn_instance *sgsn, uint32_t id);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct sgsn_instance *sgsn, struct in_addr *addr);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(struct sgsn_instance *sgsn, uint32_t id);
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx);
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except);
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn);
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc);
#define LOGGGSN(ggc, level, fmt, args...) { \
char _buf[INET_ADDRSTRLEN]; \
LOGP(DGTP, level, "GGSN(%" PRIu32 ":%s): " fmt, (ggc)->id, inet_ntop(AF_INET, &(ggc)->remote_addr, _buf, sizeof(_buf)), ## args); \
} while (0)

View File

@ -1,5 +1,4 @@
#ifndef _GPRS_SGSN_H
#define _GPRS_SGSN_H
#pragma once
#include <stdint.h>
#include <netinet/in.h>
@ -14,12 +13,17 @@
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/crypt/auth.h>
#include <osmocom/sgsn/apn.h>
#include <osmocom/sgsn/auth.h>
#include <osmocom/sgsn/gprs_subscriber.h>
#define GSM_EXTENSION_LENGTH 15
#define GSM_APN_LENGTH 102
struct gprs_llc_lle;
struct ctrl_handle;
struct gprs_subscr;
struct sgsn_ggsn_ctx;
struct sgsn_pdp_ctx;
enum gsm48_gsm_cause;
@ -37,13 +41,6 @@ enum gprs_mm_ctr {
GMM_CTR_RA_UPDATE,
};
enum gprs_pdp_ctx {
PDP_CTR_PKTS_UDATA_IN,
PDP_CTR_PKTS_UDATA_OUT,
PDP_CTR_BYTES_UDATA_IN,
PDP_CTR_BYTES_UDATA_OUT,
};
enum gprs_t3350_mode {
GMM_T3350_MODE_NONE,
GMM_T3350_MODE_ATT,
@ -51,17 +48,6 @@ enum gprs_t3350_mode {
GMM_T3350_MODE_PTMSI_REALL,
};
/* Authorization/ACL handling */
enum sgsn_auth_state {
SGSN_AUTH_UNKNOWN,
SGSN_AUTH_AUTHENTICATE,
SGSN_AUTH_UMTS_RESYNC,
SGSN_AUTH_ACCEPTED,
SGSN_AUTH_REJECTED
};
#define MS_RADIO_ACCESS_CAPA
enum sgsn_ggsn_lookup_state {
SGSN_GGSN_2DIGIT,
SGSN_GGSN_3DIGIT,
@ -104,13 +90,6 @@ struct service_info {
struct ranap_ue_conn_ctx;
struct gsm_auth_tuple {
int use_count;
int key_seq;
struct osmo_auth_vector vec;
};
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
struct sgsn_mm_ctx {
@ -295,64 +274,6 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
enum gsm48_gsm_cause *gsm_cause,
char *apn_str);
enum pdp_ctx_state {
PDP_STATE_NONE,
PDP_STATE_CR_REQ,
PDP_STATE_CR_CONF,
/* 04.08 / Figure 6.2 / 6.1.2.2 */
PDP_STATE_INACT_PEND,
PDP_STATE_INACTIVE = PDP_STATE_NONE,
};
enum pdp_type {
PDP_TYPE_NONE,
PDP_TYPE_ETSI_PPP,
PDP_TYPE_IANA_IPv4,
PDP_TYPE_IANA_IPv6,
};
struct sgsn_pdp_ctx {
struct llist_head list; /* list_head for mmctx->pdp_list */
struct llist_head g_list; /* list_head for global list */
struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
int destroy_ggsn; /* destroy it on destruction */
struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
struct llist_head ggsn_list; /* list_head for ggsn->pdp_list */
struct rate_ctr_group *ctrg;
//unsigned int id;
struct pdp_t *lib; /* pointer to libgtp PDP ctx */
enum pdp_ctx_state state;
enum pdp_type type;
uint32_t address;
char *apn_subscribed;
//char *apn_used;
uint16_t nsapi; /* SNDCP */
uint16_t sapi; /* LLC */
uint8_t ti; /* transaction identifier */
int vplmn_allowed;
uint32_t qos_profile_subscr;
//uint32_t qos_profile_req;
//uint32_t qos_profile_neg;
uint8_t radio_prio;
//uint32_t charging_id;
struct osmo_timer_list timer;
unsigned int T; /* Txxxx number */
unsigned int num_T_exp; /* number of consecutive T expirations */
struct osmo_timer_list cdr_timer; /* CDR record wird timer */
struct timespec cdr_start; /* The start of the CDR */
uint64_t cdr_bytes_in;
uint64_t cdr_bytes_out;
uint32_t cdr_charging_id;
};
#define LOGPDPCTXP(level, pdp, fmt, args...) \
LOGP(DGPRS, level, "PDP(%s/%u) " \
fmt, (pdp)->mm ? (pdp)->mm->imsi : "---", (pdp)->ti, ## args)
/* look up PDP context by MM context and NSAPI */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
uint8_t nsapi);
@ -360,168 +281,7 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
uint8_t tid);
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
struct sgsn_ggsn_ctx *ggsn,
uint8_t nsapi);
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp);
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
struct sgsn_ggsn_ctx {
struct llist_head list;
uint32_t id;
unsigned int gtp_version;
struct in_addr remote_addr;
int remote_restart_ctr;
struct gsn_t *gsn;
struct llist_head pdp_list; /* list of associated pdp ctx (struct sgsn_pdp_ctx*) */
struct osmo_timer_list echo_timer;
unsigned int echo_interval;
};
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx);
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except);
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn);
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc);
#define LOGGGSN(ggc, level, fmt, args...) { \
char _buf[INET_ADDRSTRLEN]; \
LOGP(DGTP, level, "GGSN(%" PRIu32 ":%s): " fmt, (ggc)->id, inet_ntop(AF_INET, &(ggc)->remote_addr, _buf, sizeof(_buf)), ## args); \
} while (0)
struct apn_ctx {
struct llist_head list;
struct sgsn_ggsn_ctx *ggsn;
char *name;
char *imsi_prefix;
char *description;
};
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix);
void sgsn_apn_ctx_free(struct apn_ctx *actx);
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix);
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi_prefix);
extern struct llist_head sgsn_mm_ctxts;
extern struct llist_head sgsn_ggsn_ctxts;
extern struct llist_head sgsn_apn_ctxts;
extern struct llist_head sgsn_pdp_ctxts;
uint32_t sgsn_alloc_ptmsi(void);
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx);
void sgsn_inst_init(struct sgsn_instance *sgsn);
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6);
/*
* ctrl interface related work
*/
int sgsn_ctrl_cmds_install(void);
/*
* Authorization/ACL handling
*/
struct imsi_acl_entry {
struct llist_head list;
char imsi[OSMO_IMSI_BUF_SIZE];
};
/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
/* see GSM 09.02, B.1, gprsSubscriptionData */
struct sgsn_subscriber_pdp_data {
struct llist_head list;
unsigned int context_id;
uint16_t pdp_type;
char apn_str[GSM_APN_LENGTH];
uint8_t qos_subscribed[20];
size_t qos_subscribed_len;
uint8_t pdp_charg[2];
bool has_pdp_charg;
};
struct sgsn_subscriber_data {
struct sgsn_mm_ctx *mm;
struct gsm_auth_tuple auth_triplets[5];
int auth_triplets_updated;
struct llist_head pdp_list;
int error_cause;
uint8_t msisdn[9];
size_t msisdn_len;
uint8_t hlr[9];
size_t hlr_len;
uint8_t pdp_charg[2];
bool has_pdp_charg;
};
#define SGSN_ERROR_CAUSE_NONE (-1)
#define LOGGSUBSCRP(level, subscr, fmt, args...) \
LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
(subscr) ? (subscr)->imsi : "---", \
## args)
struct sgsn_config;
struct sgsn_instance;
extern const struct value_string *sgsn_auth_state_names;
void sgsn_auth_init(struct sgsn_instance *sgsn);
struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, const struct sgsn_config *cfg);
int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg);
int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg);
/* Request authorization */
int sgsn_auth_request(struct sgsn_mm_ctx *mm);
enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm);
void sgsn_auth_update(struct sgsn_mm_ctx *mm);
struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
unsigned key_seq);
/*
* GPRS subscriber data
*/
#define GPRS_SUBSCRIBER_FIRST_CONTACT 0x00000001
#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
#define GPRS_SUBSCRIBER_ENABLE_PURGE (1 << 19)
#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
)
int gprs_subscr_init(struct sgsn_instance *sgi);
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
const uint8_t *auts,
const uint8_t *auts_rand);
int gprs_subscr_auth_sync(struct gprs_subscr *subscr,
const uint8_t *auts, const uint8_t *auts_rand);
void gprs_subscr_cleanup(struct gprs_subscr *subscr);
struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi);
struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx( struct sgsn_mm_ctx *mmctx);
struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi);
void gprs_subscr_cancel(struct gprs_subscr *subscr);
void gprs_subscr_update(struct gprs_subscr *subscr);
void gprs_subscr_update_auth_info(struct gprs_subscr *subscr);
int gprs_subscr_rx_gsup_message(struct msgb *msg);
/* Called on subscriber data updates */
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);
int gprs_sndcp_vty_init(void);
struct sgsn_instance;
int sgsn_gtp_init(struct sgsn_instance *sgi);
void sgsn_rate_ctr_init();
#endif /* _GPRS_SGSN_H */

View File

@ -0,0 +1,94 @@
#pragma once
#include <stdint.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/crypt/gprs_cipher.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/crypt/auth.h>
#include <osmocom/sgsn/apn.h>
#include <osmocom/sgsn/gprs_subscriber.h>
struct sgsn_mm_ctx;
struct sgsn_ggsn_ctx;
enum gprs_pdp_ctx {
PDP_CTR_PKTS_UDATA_IN,
PDP_CTR_PKTS_UDATA_OUT,
PDP_CTR_BYTES_UDATA_IN,
PDP_CTR_BYTES_UDATA_OUT,
};
enum pdp_ctx_state {
PDP_STATE_NONE,
PDP_STATE_CR_REQ,
PDP_STATE_CR_CONF,
/* 04.08 / Figure 6.2 / 6.1.2.2 */
PDP_STATE_INACT_PEND,
PDP_STATE_INACTIVE = PDP_STATE_NONE,
};
enum pdp_type {
PDP_TYPE_NONE,
PDP_TYPE_ETSI_PPP,
PDP_TYPE_IANA_IPv4,
PDP_TYPE_IANA_IPv6,
};
struct sgsn_pdp_ctx {
struct llist_head list; /* list_head for mmctx->pdp_list */
struct llist_head g_list; /* list_head for global list */
struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
int destroy_ggsn; /* destroy it on destruction */
struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
struct llist_head ggsn_list; /* list_head for ggsn->pdp_list */
struct rate_ctr_group *ctrg;
//unsigned int id;
struct pdp_t *lib; /* pointer to libgtp PDP ctx */
enum pdp_ctx_state state;
enum pdp_type type;
uint32_t address;
char *apn_subscribed;
//char *apn_used;
uint16_t nsapi; /* SNDCP */
uint16_t sapi; /* LLC */
uint8_t ti; /* transaction identifier */
int vplmn_allowed;
uint32_t qos_profile_subscr;
//uint32_t qos_profile_req;
//uint32_t qos_profile_neg;
uint8_t radio_prio;
//uint32_t charging_id;
struct osmo_timer_list timer;
unsigned int T; /* Txxxx number */
unsigned int num_T_exp; /* number of consecutive T expirations */
struct osmo_timer_list cdr_timer; /* CDR record wird timer */
struct timespec cdr_start; /* The start of the CDR */
uint64_t cdr_bytes_in;
uint64_t cdr_bytes_out;
uint32_t cdr_charging_id;
};
#define LOGPDPCTXP(level, pdp, fmt, args...) \
LOGP(DGPRS, level, "PDP(%s/%u) " \
fmt, (pdp)->mm ? (pdp)->mm->imsi : "---", (pdp)->ti, ## args)
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
struct sgsn_ggsn_ctx *ggsn,
uint8_t nsapi);
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp);
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6);

View File

@ -8,13 +8,13 @@
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/auth.h>
#include <osmocom/sgsn/gtp_mme.h>
#include <osmocom/gsm/oap_client.h>
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/sgsn/common.h>
#include "../../bscconfig.h"
#include "../../config.h"
#if BUILD_IU
#include <osmocom/ranap/iu_client.h>
@ -25,6 +25,8 @@
struct hostent;
#define SGSN_ERROR_CAUSE_NONE (-1)
enum sgsn_auth_policy {
SGSN_AUTH_POLICY_OPEN,
SGSN_AUTH_POLICY_CLOSED,
@ -75,6 +77,7 @@ struct sgsn_config {
/* misc */
struct gprs_ns2_inst *nsi;
char *crypt_cipher_plugin_path;
enum sgsn_auth_policy auth_policy;
uint8_t gea_encryption_mask;
uint8_t uea_encryption_mask;
@ -93,6 +96,7 @@ struct sgsn_config {
/* Timer defintions */
struct osmo_tdef *T_defs;
struct osmo_tdef *T_defs_gtp;
int dynamic_lookup;
@ -150,10 +154,22 @@ struct sgsn_instance {
struct rate_ctr_group *rate_ctrs;
struct llist_head apn_list; /* list of struct sgsn_apn_ctx */
struct llist_head ggsn_list; /* list of struct sgsn_ggsn_ctx */
struct llist_head mme_list; /* list of struct sgsn_mme_ctx */
struct llist_head mm_list; /* list of struct sgsn_mm_ctx */
struct llist_head pdp_list; /* list of struct sgsn_pdp_ctx */
struct ctrl_handle *ctrlh;
};
extern struct sgsn_instance *sgsn;
extern void *tall_sgsn_ctx;
/*
* ctrl interface related work (sgsn_ctrl.c)
*/
int sgsn_ctrl_cmds_install(void);
/* sgsn_vty.c */
@ -162,40 +178,13 @@ int sgsn_parse_config(const char *config_file);
char *sgsn_gtp_ntoa(struct ul16_t *ul);
/* sgsn.c */
/* Main input function for Gb proxy */
int sgsn_rcvmsg(struct msgb *msg, struct gprs_ns2_vc *nsvc, uint16_t ns_bvci);
/* sgsn_libgtp.c */
struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
struct sgsn_mm_ctx *mmctx,
uint16_t nsapi,
struct tlv_parsed *tp);
int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen);
void sgsn_ggsn_echo_req(struct sgsn_ggsn_ctx *ggc);
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx);
int sgsn_mme_ran_info_req(struct sgsn_mme_ctx *mme, const struct bssgp_ran_information_pdu *pdu);
/* gprs_sndcp.c */
/* Entry point for the SNSM-ACTIVATE.indication */
int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
/* Entry point for the SNSM-DEACTIVATE.indication */
int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
/* Called by SNDCP when it has received/re-assembled a N-PDU */
int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
void *mmcontext);
int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
uint8_t *hdr, uint16_t len);
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx);
int sgsn_inst_init(struct sgsn_instance *sgsn);
/*
* CDR related functionality
*/
int sgsn_cdr_init(struct sgsn_instance *sgsn);
void sgsn_cdr_release(struct sgsn_instance *sgsn);
/*

View File

@ -3,4 +3,4 @@
struct sgsn_mme_ctx;
int sgsn_rim_rx_from_gb(struct osmo_bssgp_prim *bp, struct msgb *msg);
int sgsn_rim_rx_from_gtp(struct bssgp_ran_information_pdu *pdu, struct sgsn_mme_ctx *mme);
int sgsn_rim_rx_from_gtp(struct msgb *msg, struct bssgp_rim_routing_info *rim_routing_address);

View File

@ -29,7 +29,6 @@ endif
noinst_LTLIBRARIES = libcommon.la
libcommon_la_SOURCES = \
gprs_gb_parse.c \
gprs_llc_parse.c \
crc24.c \
gprs_utils.c \

View File

@ -59,7 +59,7 @@ static const uint32_t tbl_crc24[256] = {
#define INIT_CRC24 0xffffff
uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len)
uint32_t crc24_calc(uint32_t fcs, const uint8_t *cp, unsigned int len)
{
while (len--)
fcs = (fcs >> 8) ^ tbl_crc24[(fcs ^ *cp++) & 0xff];

View File

@ -29,7 +29,7 @@
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/crc24.h>
@ -55,7 +55,7 @@ static const struct value_string llc_cmd_strs[] = {
#define N202 4
#define CRC24_LENGTH 3
int gprs_llc_fcs(uint8_t *data, unsigned int len)
int gprs_llc_fcs(const uint8_t *data, unsigned int len)
{
uint32_t fcs_calc;

View File

@ -30,56 +30,6 @@
#include <string.h>
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str)
{
uint8_t *last_len_field;
int len;
/* Can we even write the length field to the output? */
if (max_len == 0)
return -1;
/* Remember where we need to put the length once we know it */
last_len_field = apn_enc;
len = 1;
apn_enc += 1;
while (str[0]) {
if (len >= max_len)
return -1;
if (str[0] == '.') {
*last_len_field = (apn_enc - last_len_field) - 1;
last_len_field = apn_enc;
} else {
*apn_enc = str[0];
}
apn_enc += 1;
str += 1;
len += 1;
}
*last_len_field = (apn_enc - last_len_field) - 1;
return len;
}
/* GSM 04.08, 10.5.7.3 GPRS Timer */
int gprs_tmr_to_secs(uint8_t tmr)
{
switch (tmr & GPRS_TMR_UNIT_MASK) {
case GPRS_TMR_2SECONDS:
return 2 * (tmr & GPRS_TMR_FACT_MASK);
default:
case GPRS_TMR_MINUTE:
return 60 * (tmr & GPRS_TMR_FACT_MASK);
case GPRS_TMR_6MINUTE:
return 360 * (tmr & GPRS_TMR_FACT_MASK);
case GPRS_TMR_DEACTIVATED:
return -1;
}
}
/* This functions returns a tmr value such that
* - f is monotonic
* - f(s) <= s
@ -132,19 +82,6 @@ int gprs_is_mi_imsi(const uint8_t *value, size_t value_len)
return 1;
}
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi)
{
uint32_t tmsi_be;
if (!gprs_is_mi_tmsi(value, value_len))
return 0;
memcpy(&tmsi_be, value + 1, sizeof(tmsi_be));
*tmsi = ntohl(tmsi_be);
return 1;
}
void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi)
{
uint32_t tmsi_be;

View File

@ -24,8 +24,6 @@
#include <netdb.h>
extern void *tall_sgsn_ctx;
struct cares_event_fd {
struct llist_head head;
struct osmo_fd fd;

View File

@ -32,7 +32,7 @@
#include <gtp.h>
#include <gtpie.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_utils.h>
@ -475,7 +475,7 @@ static int get_ie_imsi_str(union gtpie_member *ie[], int i,
* present but cannot be decoded. */
static int get_ie_apn_str(union gtpie_member *ie[], const char **apn_str)
{
static char apn_buf[GSM_APN_LENGTH];
static char apn_buf[APN_MAXLEN+1];
unsigned int len;
if (gtpie_gettlv(ie, GTPIE_APN, 0,
&len, apn_buf, sizeof(apn_buf)) != 0)
@ -971,7 +971,7 @@ static inline void set_tei(struct gtp_packet_desc *p, uint32_t tei)
static void gtphub_mapping_del_cb(struct expiring_item *expi);
static struct nr_mapping *gtphub_mapping_new()
static struct nr_mapping *gtphub_mapping_new(void)
{
struct nr_mapping *nrm;
nrm = talloc_zero(osmo_gtphub_ctx, struct nr_mapping);
@ -995,7 +995,7 @@ static const char *gtphub_tunnel_side_str(struct gtphub_tunnel *tun,
char *pos = buf;
int left = sizeof(buf);
int l;
struct gtphub_tunnel_endpoint *c, *u;
c = &tun->endpoint[side_idx][GTPH_PLANE_CTRL];
u = &tun->endpoint[side_idx][GTPH_PLANE_USER];
@ -1104,7 +1104,7 @@ static void gtphub_tunnel_del_cb(struct expiring_item *expi)
/* rate counter index for hubs: [7; 10] */
#define CTR_IDX_HUB(s, p) CTR_IDX(s, p, 3, 2)
static struct gtphub_tunnel *gtphub_tunnel_new()
static struct gtphub_tunnel *gtphub_tunnel_new(void)
{
struct gtphub_tunnel *tun;
tun = talloc_zero(osmo_gtphub_ctx, struct gtphub_tunnel);
@ -2283,7 +2283,7 @@ int gtphub_handle_buf(struct gtphub *hub,
!= 0)
return -1;
}
/* Either to_peer was resolved from an existing tunnel,
* or a PDP Ctx and thus a tunnel has just been created,
* or the tunnel has been deleted due to this message. */
@ -2690,7 +2690,7 @@ static struct gtphub_peer_addr *gtphub_addr_have(struct gtphub *hub,
struct gtphub_peer *peer = gtphub_peer_new(hub, bind);
a = gtphub_peer_add_addr(peer, addr);
LOG(LOGL_DEBUG, "New peer address: %s %s\n",
bind->label,
gsn_addr_to_str(&a->addr));

View File

@ -28,11 +28,12 @@
#include <string.h>
#include <unistd.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/apn.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
/* TODO split GRX ares from sgsn into a separate struct and allow use without
* globals. */
@ -56,8 +57,8 @@ struct ggsn_lookup {
struct gtphub *hub;
char imsi_str[GSM23003_IMSI_MAX_DIGITS+1];
char apn_ni_str[GSM_APN_LENGTH];
char apn_oi_str[GSM_APN_LENGTH];
char apn_ni_str[APN_MAXLEN+1];
char apn_oi_str[APN_MAXLEN+1];
int have_3dig_mnc;
};

View File

@ -34,6 +34,7 @@
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/msgb.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/telnet_interface.h>
@ -41,10 +42,10 @@
#include <osmocom/vty/misc.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
#include <osmocom/sgsn/vty.h>
#include "../../bscconfig.h"
#include "../../config.h"
#if BUILD_IU
#include <osmocom/sigtran/osmo_ss7.h>
@ -353,8 +354,7 @@ int main(int argc, char **argv)
}
/* start telnet after reading config for vty_get_bind_addr() */
rc = telnet_init_dynif(osmo_gtphub_ctx, 0, vty_get_bind_addr(),
OSMO_VTY_PORT_GTPHUB);
rc = telnet_init_default(osmo_gtphub_ctx, NULL, OSMO_VTY_PORT_GTPHUB);
if (rc < 0)
exit(1);

View File

@ -25,7 +25,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <osmocom/sgsn/gtphub.h>
#include <errno.h>
#include <string.h>
#include <osmocom/core/utils.h>
#include <osmocom/gtphub/gtphub.h>
#include <osmocom/sgsn/debug.h>
/* Convenience makro, note: only within this C file. */

View File

@ -31,7 +31,7 @@
#include <osmocom/vty/misc.h>
#include <osmocom/sgsn/vty.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
/* TODO split GRX ares from sgsn into a separate struct and allow use without
* globals. */

View File

@ -40,12 +40,13 @@ bin_PROGRAMS = \
$(NULL)
osmo_sgsn_SOURCES = \
gprs_gb.c \
apn.c \
gprs_bssgp.c \
gprs_gmm_attach.c \
gprs_gmm.c \
gprs_gmm_fsm.c \
gprs_mm_state_gb_fsm.c \
gprs_sgsn.c \
gprs_ns.c \
gprs_sm.c \
gprs_sndcp.c \
gprs_sndcp_comp.c \
@ -53,12 +54,16 @@ osmo_sgsn_SOURCES = \
gprs_sndcp_pcomp.c \
gprs_sndcp_vty.c \
gprs_sndcp_xid.c \
gtp_ggsn.c \
gtp_mme.c \
sgsn.c \
sgsn_main.c \
sgsn_vty.c \
sgsn_libgtp.c \
gprs_llc.c \
gprs_llc_vty.c \
mmctx.c \
pdpctx.c \
sgsn_ctrl.c \
sgsn_auth.c \
gprs_subscriber.c \

123
src/sgsn/apn.c Normal file
View File

@ -0,0 +1,123 @@
/* APN contexts */
/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by On-Waves
* (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* 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/>.
*
*/
#include <string.h>
#include <talloc.h>
#include <osmocom/sgsn/apn.h>
#include <osmocom/sgsn/sgsn.h>
static struct apn_ctx *sgsn_apn_ctx_alloc(const char *ap_name, const char *imsi_prefix)
{
struct apn_ctx *actx;
actx = talloc_zero(sgsn, struct apn_ctx);
if (!actx)
return NULL;
actx->name = talloc_strdup(actx, ap_name);
actx->imsi_prefix = talloc_strdup(actx, imsi_prefix);
llist_add_tail(&actx->list, &sgsn->apn_list);
return actx;
}
void sgsn_apn_ctx_free(struct apn_ctx *actx)
{
llist_del(&actx->list);
talloc_free(actx);
}
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi)
{
struct apn_ctx *actx;
struct apn_ctx *found_actx = NULL;
size_t imsi_prio = 0;
size_t name_prio = 0;
size_t name_req_len = strlen(name);
llist_for_each_entry(actx, &sgsn->apn_list, list) {
size_t name_ref_len, imsi_ref_len;
const char *name_ref_start, *name_match_start;
imsi_ref_len = strlen(actx->imsi_prefix);
if (strncmp(actx->imsi_prefix, imsi, imsi_ref_len) != 0)
continue;
if (imsi_ref_len < imsi_prio)
continue;
/* IMSI matches */
name_ref_start = &actx->name[0];
if (name_ref_start[0] == '*') {
/* Suffix match */
name_ref_start += 1;
name_ref_len = strlen(name_ref_start);
if (name_ref_len > name_req_len)
continue;
} else {
name_ref_len = strlen(name_ref_start);
if (name_ref_len != name_req_len)
continue;
}
name_match_start = name + (name_req_len - name_ref_len);
if (strcasecmp(name_match_start, name_ref_start) != 0)
continue;
/* IMSI and name match */
if (imsi_ref_len == imsi_prio && name_ref_len < name_prio)
/* Lower priority, skip */
continue;
imsi_prio = imsi_ref_len;
name_prio = name_ref_len;
found_actx = actx;
}
return found_actx;
}
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix)
{
struct apn_ctx *actx;
llist_for_each_entry(actx, &sgsn->apn_list, list) {
if (strcasecmp(name, actx->name) == 0 &&
strcasecmp(imsi_prefix, actx->imsi_prefix) == 0)
return actx;
}
return NULL;
}
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix)
{
struct apn_ctx *actx;
actx = sgsn_apn_ctx_by_name(name, imsi_prefix);
if (!actx)
actx = sgsn_apn_ctx_alloc(name, imsi_prefix);
return actx;
}

95
src/sgsn/gprs_bssgp.c Normal file
View File

@ -0,0 +1,95 @@
/* GPRS BSSGP protocol implementation as per 3GPP TS 08.18 */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by On-Waves
* (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* 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/>.
*
*/
#include <osmocom/core/prim.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/sgsn_rim.h>
#include <osmocom/sgsn/mmctx.h>
/* call-back function for the BSSGP protocol */
int sgsn_bssgp_rx_prim(struct osmo_prim_hdr *oph)
{
struct osmo_bssgp_prim *bp;
bp = container_of(oph, struct osmo_bssgp_prim, oph);
switch (oph->sap) {
case SAP_BSSGP_LL:
switch (oph->primitive) {
case PRIM_BSSGP_UL_UD:
return gprs_llc_rcvmsg(oph->msg, bp->tp);
}
break;
case SAP_BSSGP_GMM:
switch (oph->primitive) {
case PRIM_BSSGP_GMM_SUSPEND:
return gprs_gmm_rx_suspend(bp->ra_id, bp->tlli);
case PRIM_BSSGP_GMM_RESUME:
return gprs_gmm_rx_resume(bp->ra_id, bp->tlli,
bp->u.resume.suspend_ref);
}
break;
case SAP_BSSGP_NM:
break;
case SAP_BSSGP_RIM:
return sgsn_rim_rx_from_gb(bp, oph->msg);
}
return 0;
}
int sgsn_bssgp_page_ps_ra(struct sgsn_mm_ctx *mmctx)
{
struct bssgp_paging_info pinfo;
int rc;
/* FIXME: page whole routing area, not only the last known cell */
/* initiate PS PAGING procedure */
memset(&pinfo, 0, sizeof(pinfo));
pinfo.mode = BSSGP_PAGING_PS;
pinfo.scope = BSSGP_PAGING_BVCI;
pinfo.bvci = mmctx->gb.bvci;
pinfo.imsi = mmctx->imsi;
pinfo.ptmsi = &mmctx->p_tmsi;
pinfo.drx_params = mmctx->drx_parms;
pinfo.qos[0] = 0; // FIXME
rc = bssgp_tx_paging(mmctx->gb.nsei, 0, &pinfo);
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PAGING_PS));
return rc;
}
/* called by the bssgp layer to send NS PDUs */
int sgsn_bssgp_dispatch_ns_unitdata_req_cb(void *ctx, struct msgb *msg)
{
struct gprs_ns2_inst *nsi = (struct gprs_ns2_inst *) ctx;
struct osmo_gprs_ns2_prim nsp = {};
nsp.nsei = msgb_nsei(msg);
nsp.bvci = msgb_bvci(msg);
osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA, PRIM_OP_REQUEST, msg);
return gprs_ns2_recv_prim(nsi, &nsp.oph);
}

View File

@ -30,7 +30,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include "bscconfig.h"
#include "config.h"
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
@ -48,7 +48,7 @@
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/gprs_subscriber.h>
@ -60,17 +60,17 @@
#include <osmocom/sgsn/signal.h>
#include <osmocom/sgsn/gprs_sndcp.h>
#include <osmocom/sgsn/gprs_ranap.h>
#include <osmocom/sgsn/gprs_sm.h>
#include <osmocom/sgsn/gtp.h>
#include <osmocom/sgsn/pdpctx.h>
#include <pdp.h>
#define PTMSI_ALLOC
extern struct sgsn_instance *sgsn;
extern void *tall_sgsn_ctx;
static const struct tlv_definition gsm48_gmm_att_tlvdef = {
.def = {
[GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_FIXED, 1 },
[GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_SINGLE_TV, 1 },
[GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 },
[GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 },
[GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 },
@ -79,6 +79,7 @@ static const struct tlv_definition gsm48_gmm_att_tlvdef = {
[GSM48_IE_GMM_AUTH_RES_EXT] = { TLV_TYPE_TLV, 0 },
[GSM48_IE_GMM_AUTH_FAIL_PAR] = { TLV_TYPE_TLV, 0 },
[GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 },
[GSM48_IE_GMM_RX_NPDU_NUM_LIST] = { TLV_TYPE_TLV, 0 },
[GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_FIXED, 2 },
[GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 },
[GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 },
@ -110,9 +111,14 @@ static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T)
static void mmctx_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
{
if (mm->T != T)
if (!osmo_timer_pending(&mm->timer)) {
LOGMMCTXP(LOGL_NOTICE, mm, "Stopping *inactive* MM timer %u\n", T);
return;
}
if (mm->T != T) {
LOGMMCTXP(LOGL_ERROR, mm, "Stopping MM timer %u but "
"%u is running\n", T, mm->T);
}
osmo_timer_del(&mm->timer);
}
@ -1390,11 +1396,11 @@ static int gsm48_rx_gmm_att_compl(struct sgsn_mm_ctx *mmctx)
/* only in case SGSN offered new P-TMSI */
LOGMMCTXP(LOGL_INFO, mmctx, "-> GMM ATTACH COMPLETE\n");
#ifdef BUILD_IU
#ifdef BUILD_IU
if (mmctx->iu.ue_ctx) {
ranap_iu_tx_release(mmctx->iu.ue_ctx, NULL);
}
#endif
#endif
mmctx_timer_stop(mmctx, 3350);
mmctx->t3350_mode = GMM_T3350_MODE_NONE;
@ -1766,6 +1772,10 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
/* Update the MM context with the new (i.e. foreign) TLLI */
mmctx->gb.tlli = msgb_tlli(msg);
}
/* Update the MM context with the new DRX params */
if (TLVP_PRESENT(&tp, GSM48_IE_GMM_DRX_PARAM))
memcpy(&mmctx->drx_parms, TLVP_VAL(&tp, GSM48_IE_GMM_DRX_PARAM), sizeof(mmctx->drx_parms));
/* FIXME: Update the MM context with the MS radio acc capabilities */
/* FIXME: Update the MM context with the MS network capabilities */
@ -2313,3 +2323,51 @@ int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
osmo_fsm_inst_dispatch(mmctx->gmm_fsm, E_GMM_RESUME, NULL);
return 0;
}
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg)
{
msgid2mmctx(mmctx, msg);
if (mmctx->gb.llme)
osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_PDU_RECEPTION, NULL);
}
/* Main entry point for incoming 04.08 GPRS messages from Gb */
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable)
{
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
uint8_t pdisc = gsm48_hdr_pdisc(gh);
struct sgsn_mm_ctx *mmctx;
struct gprs_ra_id ra_id;
int rc = -EINVAL;
bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
if (mmctx) {
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PKTS_SIG_IN));
mmctx->gb.llme = llme;
gprs_gb_recv_pdu(mmctx, msg);
}
/* MMCTX can be NULL */
switch (pdisc) {
case GSM48_PDISC_MM_GPRS:
rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
break;
case GSM48_PDISC_SM_GPRS:
rc = gsm0408_rcv_gsm(mmctx, msg, llme);
break;
default:
LOGMMCTXP(LOGL_NOTICE, mmctx,
"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
/* FIXME: return status message */
break;
}
/* MMCTX can be invalid */
return rc;
}

View File

@ -6,6 +6,7 @@
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/sgsn.h>
#define X(s) (1 << (s))

View File

@ -1,6 +1,6 @@
/* GMM mobility management states on the network side, 3GPP TS 24.008 § 4.1.3.3 */
/*
* (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
* (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* SPDX-License-Identifier: AGPL-3.0+
@ -80,6 +80,11 @@ static void st_gmm_registered_normal(struct osmo_fsm_inst *fi, uint32_t event, v
case E_GMM_COMMON_PROC_INIT_REQ:
gmm_fsm_state_chg(fi, ST_GMM_COMMON_PROC_INIT);
break;
case E_GMM_COMMON_PROC_SUCCESS:
/* If we were moved from ST_GMM_COMMON_PROC_INIT here by
* E_GMM_ATTACH_SUCCESS instead of E_GMM_COMMON_PROC_SUCCESS then we'll receive the latter here:
* we should simply ignore it */
break;
/* case E_GMM_NET_INIT_DETACH_REQ:
gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED_INIT);
break; */
@ -141,6 +146,7 @@ static struct osmo_fsm_state gmm_fsm_states[] = {
[ST_GMM_REGISTERED_NORMAL] = {
.in_event_mask =
X(E_GMM_COMMON_PROC_INIT_REQ) |
X(E_GMM_COMMON_PROC_SUCCESS) |
/* X(E_GMM_NET_INIT_DETACH_REQ) | */
/* X(E_GMM_MS_INIT_DETACH_REQ) | */
X(E_GMM_SUSPEND),

View File

@ -33,7 +33,7 @@
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/crc24.h>
@ -50,10 +50,21 @@ const struct value_string gprs_llc_llme_state_names[] = {
{ 0, NULL }
};
const struct value_string gprs_llc_lle_state_names[] = {
{ GPRS_LLES_UNASSIGNED, "TLLI Unassigned" },
{ GPRS_LLES_ASSIGNED_ADM, "TLLI Assigned" },
{ GPRS_LLES_LOCAL_EST, "Local Establishment" },
{ GPRS_LLES_REMOTE_EST, "Remote Establishment" },
{ GPRS_LLES_ABM, "Asynchronous Balanced Mode" },
{ GPRS_LLES_LOCAL_REL, "Local Release" },
{ GPRS_LLES_TIMER_REC, "Timer Recovery" },
{ 0, NULL }
};
static struct gprs_llc_llme *llme_alloc(uint32_t tlli);
static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
static int gprs_llc_tx_xid(const struct gprs_llc_lle *lle, struct msgb *msg,
int command);
static int gprs_llc_tx_dm(struct gprs_llc_lle *lle);
static int gprs_llc_tx_dm(const struct gprs_llc_lle *lle);
static int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi,
int command, enum gprs_llc_u_cmd u_cmd, int pf_bit);
@ -212,7 +223,7 @@ static int gprs_llc_process_xid_ind(uint8_t *bytes_request,
int bytes_request_len,
uint8_t *bytes_response,
int bytes_response_maxlen,
struct gprs_llc_lle *lle)
const struct gprs_llc_lle *lle)
{
/* Note: This function computes the response that is sent back to the
* MS when a mobile originated XID is received. The function is
@ -288,7 +299,7 @@ static int gprs_llc_process_xid_ind(uint8_t *bytes_request,
/* Dispatch XID indications and responses comming from the MS */
static void rx_llc_xid(struct gprs_llc_lle *lle,
struct gprs_llc_hdr_parsed *gph)
const struct gprs_llc_hdr_parsed *gph)
{
uint8_t response[1024];
int response_len;
@ -681,7 +692,7 @@ int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi, int command,
}
/* Send XID response to LLE */
static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
static int gprs_llc_tx_xid(const struct gprs_llc_lle *lle, struct msgb *msg,
int command)
{
/* copy identifiers from LLE to ensure lower layers can route */
@ -692,7 +703,7 @@ static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
return gprs_llc_tx_u(msg, lle->sapi, command, GPRS_LLC_U_XID, 1);
}
static int gprs_llc_tx_dm(struct gprs_llc_lle *lle)
static int gprs_llc_tx_dm(const struct gprs_llc_lle *lle)
{
struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_DM");
@ -705,7 +716,7 @@ static int gprs_llc_tx_dm(struct gprs_llc_lle *lle)
}
/* encrypt information field + FCS, if needed! */
static int apply_gea(struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu,
static int apply_gea(const struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu,
uint32_t oc, uint8_t sapi, uint8_t *fcs, uint8_t *data)
{
uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK];
@ -965,9 +976,9 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
llhp.data);
if (rc < 0)
return rc;
llhp.fcs = *(llhp.data + llhp.data_len);
llhp.fcs |= *(llhp.data + llhp.data_len + 1) << 8;
llhp.fcs |= *(llhp.data + llhp.data_len + 2) << 16;
llhp.fcs = *(llhp.data + llhp.data_len);
llhp.fcs |= *(llhp.data + llhp.data_len + 1) << 8;
llhp.fcs |= *(llhp.data + llhp.data_len + 2) << 16;
} else {
LOGP(DLLC, LOGL_NOTICE, "encrypted frame for LLC that "
"has no KC/Algo! Dropping.\n");
@ -1019,7 +1030,7 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
case GPRS_SAPI_SNDCP9:
case GPRS_SAPI_SNDCP11:
/* send LL_DATA_IND/LL_UNITDATA_IND to SNDCP */
rc = sndcp_llunitdata_ind(msg, lle, llhp.data, llhp.data_len);
rc = sndcp_ll_unitdata_ind(msg, lle, llhp.data, llhp.data_len);
break;
case GPRS_SAPI_SMS:
/* FIXME */
@ -1037,7 +1048,7 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
}
/* Propagate crypto parameters MM -> LLME */
void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme)
void gprs_llme_copy_key(const struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme)
{
if (!mm)
return;

View File

@ -39,22 +39,11 @@
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
struct value_string gprs_llc_state_strs[] = {
{ GPRS_LLES_UNASSIGNED, "TLLI Unassigned" },
{ GPRS_LLES_ASSIGNED_ADM, "TLLI Assigned" },
{ GPRS_LLES_LOCAL_EST, "Local Establishment" },
{ GPRS_LLES_REMOTE_EST, "Remote Establishment" },
{ GPRS_LLES_ABM, "Asynchronous Balanced Mode" },
{ GPRS_LLES_LOCAL_REL, "Local Release" },
{ GPRS_LLES_TIMER_REC, "Timer Recovery" },
{ 0, NULL }
};
static void vty_dump_lle(struct vty *vty, struct gprs_llc_lle *lle)
{
struct gprs_llc_params *par = &lle->params;
vty_out(vty, " SAPI %2u State %s VUsend=%u, VUrecv=%u", lle->sapi,
get_value_string(gprs_llc_state_strs, lle->state),
vty_out(vty, " SAPI %2u State %s VUsend=%u, VUrecv=%u", lle->sapi,
get_value_string(gprs_llc_lle_state_names, lle->state),
lle->vu_send, lle->vu_recv);
vty_out(vty, " Vsent=%u Vack=%u Vrecv=%u, RetransCtr=%u%s",
lle->v_sent, lle->v_ack, lle->v_recv,
@ -79,7 +68,7 @@ static void vty_dump_llme(struct vty *vty, struct gprs_llc_llme *llme)
get_value_string(gprs_cipher_names, llme->algo), llme->iov_ui,
llme->cksn, llme->age_timestamp == GPRS_LLME_RESET_AGE ? 0 :
(int)(now_tp.tv_sec - (time_t)llme->age_timestamp),
get_value_string(gprs_llc_state_strs, llme->state), VTY_NEWLINE);
get_value_string(gprs_llc_llme_state_names, llme->state), VTY_NEWLINE);
for (i = 0; i < ARRAY_SIZE(valid_sapis); i++) {
struct gprs_llc_lle *lle;

View File

@ -1,6 +1,6 @@
/* TS 23.060 § 6.1.1 Mobility Management States (A/Gb mode) */
/*
* (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
* (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* SPDX-License-Identifier: AGPL-3.0+
@ -27,6 +27,7 @@
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#define X(s) (1 << (s))

View File

@ -1,6 +1,6 @@
/* TS 23.060 § 6.1.2 Mobility Management States (Iu mode) */
/*
* (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
* (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* SPDX-License-Identifier: AGPL-3.0+
@ -29,6 +29,9 @@
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_ranap.h>
#include <osmocom/sgsn/gtp.h>
#include <osmocom/sgsn/pdpctx.h>
#include <osmocom/sgsn/mmctx.h>
#define X(s) (1 << (s))

View File

@ -29,95 +29,10 @@
#include <osmocom/gprs/gprs_bssgp_bss.h>
#include <osmocom/sgsn/gprs_llc.h>
#include "bscconfig.h"
#include "config.h"
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_sm.h>
#include <osmocom/sgsn/debug.h>
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx, const struct msgb *msg) {
msgid2mmctx(mmctx, msg);
if (mmctx->gb.llme)
osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_PDU_RECEPTION, NULL);
}
/* Main entry point for incoming 04.08 GPRS messages from Gb */
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable)
{
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
uint8_t pdisc = gsm48_hdr_pdisc(gh);
struct sgsn_mm_ctx *mmctx;
struct gprs_ra_id ra_id;
int rc = -EINVAL;
bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
if (mmctx) {
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PKTS_SIG_IN));
mmctx->gb.llme = llme;
gprs_gb_recv_pdu(mmctx, msg);
}
/* MMCTX can be NULL */
switch (pdisc) {
case GSM48_PDISC_MM_GPRS:
rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
break;
case GSM48_PDISC_SM_GPRS:
rc = gsm0408_rcv_gsm(mmctx, msg, llme);
break;
default:
LOGMMCTXP(LOGL_NOTICE, mmctx,
"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
/* FIXME: return status message */
break;
}
/* MMCTX can be invalid */
return rc;
}
int gprs_gb_page_ps_ra(struct sgsn_mm_ctx *mmctx)
{
struct bssgp_paging_info pinfo;
int rc;
/* FIXME: page whole routing area, not only the last known cell */
/* initiate PS PAGING procedure */
memset(&pinfo, 0, sizeof(pinfo));
pinfo.mode = BSSGP_PAGING_PS;
pinfo.scope = BSSGP_PAGING_BVCI;
pinfo.bvci = mmctx->gb.bvci;
pinfo.imsi = mmctx->imsi;
pinfo.ptmsi = &mmctx->p_tmsi;
pinfo.drx_params = mmctx->drx_parms;
pinfo.qos[0] = 0; // FIXME
rc = bssgp_tx_paging(mmctx->gb.nsei, 0, &pinfo);
rate_ctr_inc(rate_ctr_group_get_ctr(mmctx->ctrg, GMM_CTR_PAGING_PS));
return rc;
}
/* called by the bssgp layer to send NS PDUs */
int gprs_gb_send_cb(void *ctx, struct msgb *msg)
{
struct gprs_ns2_inst *nsi = (struct gprs_ns2_inst *) ctx;
struct osmo_gprs_ns2_prim nsp = {};
nsp.nsei = msgb_nsei(msg);
nsp.bvci = msgb_bvci(msg);
osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA, PRIM_OP_REQUEST, msg);
return gprs_ns2_recv_prim(nsi, &nsp.oph);
}
void gprs_ns_prim_status_cb(struct osmo_gprs_ns2_prim *nsp)
{
switch (nsp->u.status.cause) {

View File

@ -21,7 +21,7 @@
*
*/
#include "bscconfig.h"
#include "config.h"
#include <gtp.h>
#include <osmocom/core/rate_ctr.h>
@ -37,6 +37,10 @@
#include <osmocom/sgsn/gprs_ranap.h>
#include <osmocom/sgsn/gprs_gmm_attach.h>
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/gtp.h>
#include <osmocom/sgsn/pdpctx.h>
#include <osmocom/sgsn/mmctx.h>
/* Send RAB activation requests for all PDP contexts */
void activate_pdp_rabs(struct sgsn_mm_ctx *ctx)

View File

@ -26,7 +26,7 @@
#include <arpa/inet.h>
#include <netdb.h>
#include "bscconfig.h"
#include "config.h"
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/tdef.h>
@ -36,13 +36,15 @@
#include <osmocom/sgsn/gprs_sm.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_sndcp.h>
#include <osmocom/sgsn/gprs_ranap.h>
extern void *tall_sgsn_ctx;
#include <osmocom/sgsn/gtp.h>
#include <osmocom/sgsn/pdpctx.h>
#include <osmocom/sgsn/mmctx.h>
/* 3GPP TS 04.08 sec 6.1.3.4.3(.a) "Abnormal cases" */
#define T339X_MAX_RETRANS 4
@ -376,7 +378,7 @@ static void ggsn_lookup_cb(void *arg, int status, int timeouts, struct hostent *
goto reject_due_failure;
}
ggsn = sgsn_ggsn_ctx_alloc(UINT32_MAX);
ggsn = sgsn_ggsn_ctx_alloc(sgsn, UINT32_MAX);
if (!ggsn) {
LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "Failed to create ggsn.\n");
goto reject_due_failure;
@ -448,7 +450,7 @@ static int do_act_pdp_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg, bool *del
DEBUGPC(DMM, "IPv4 ");
if (req_pdpa_len >= 6) {
struct in_addr ia;
ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2)));
ia.s_addr = osmo_load32be(req_pdpa+2);
DEBUGPC(DMM, "%s ", inet_ntop(AF_INET, &ia, buf, sizeof(buf)));
}
break;

View File

@ -32,7 +32,7 @@
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_gb.h>
#include <osmocom/sgsn/gprs_ns.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_sndcp.h>
@ -41,6 +41,9 @@
#include <osmocom/sgsn/gprs_sndcp_pcomp.h>
#include <osmocom/sgsn/gprs_sndcp_dcomp.h>
#include <osmocom/sgsn/gprs_sndcp_comp.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gtp.h>
#define DEBUG_IP_PACKETS 0 /* 0=Disabled, 1=Enabled */
@ -66,7 +69,7 @@ static uint16_t calc_ip_csum(uint8_t *data, int len)
}
/* Calculate TCP/IP checksum */
static uint16_t calc_tcpip_csum(const void *ctx, uint8_t *packet, int len)
static uint16_t calc_tcpip_csum(const void *ctx, const uint8_t *packet, int len)
{
uint8_t *buf;
uint16_t csum;
@ -84,7 +87,7 @@ static uint16_t calc_tcpip_csum(const void *ctx, uint8_t *packet, int len)
}
/* Show some ip packet details */
static void debug_ip_packet(uint8_t *data, int len, int dir, char *info)
static void debug_ip_packet(const uint8_t *data, int len, int dir, const char *info)
{
uint8_t tcp_flags;
char flags_debugmsg[256];
@ -173,7 +176,7 @@ struct sndcp_common_hdr {
uint8_t first:1;
uint8_t spare:1;
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t spare:1, first:1, type:1, more:1, nsapi:4;
#endif
} __attribute__((packed));
@ -185,7 +188,7 @@ struct sndcp_comp_hdr {
uint8_t pcomp:4;
uint8_t dcomp:4;
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t dcomp:4, pcomp:4;
#endif
} __attribute__((packed));
@ -198,7 +201,7 @@ struct sndcp_udata_hdr {
/* octet 4 */
uint8_t npdu_low;
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
uint8_t seg_nr:4, npdu_high:4;
uint8_t npdu_low;
#endif
@ -221,7 +224,8 @@ struct defrag_queue_entry {
LLIST_HEAD(gprs_sndcp_entities);
/* Check if any compression parameters are set in the sgsn configuration */
static inline int any_pcomp_or_dcomp_active(struct sgsn_instance *sgsn) {
static inline int any_pcomp_or_dcomp_active(const struct sgsn_instance *sgsn)
{
if (sgsn->cfg.pcomp_rfc1144.active || sgsn->cfg.pcomp_rfc1144.passive ||
sgsn->cfg.dcomp_v42bis.active || sgsn->cfg.dcomp_v42bis.passive)
return true;
@ -260,7 +264,7 @@ static int defrag_enqueue(struct gprs_sndcp_entity *sne, uint8_t seg_nr,
}
/* return if we have all segments of this N-PDU */
static int defrag_have_all_segments(struct gprs_sndcp_entity *sne)
static int defrag_have_all_segments(const struct gprs_sndcp_entity *sne)
{
uint32_t seg_needed = 0;
unsigned int i;
@ -275,7 +279,7 @@ static int defrag_have_all_segments(struct gprs_sndcp_entity *sne)
return 0;
}
static struct defrag_queue_entry *defrag_get_seg(struct gprs_sndcp_entity *sne,
static struct defrag_queue_entry *defrag_get_seg(const struct gprs_sndcp_entity *sne,
uint32_t seg_nr)
{
struct defrag_queue_entry *dqe;
@ -289,13 +293,62 @@ static struct defrag_queue_entry *defrag_get_seg(struct gprs_sndcp_entity *sne,
return NULL;
}
/* Returns talloced buffer containing decompressed data, NULL on error. */
static uint8_t *decompress_segment(struct gprs_sndcp_entity *sne, void *ctx,
const uint8_t *compressed_data, unsigned int compressed_data_len,
unsigned int *decompressed_data_len)
{
int rc;
uint8_t *expnd = NULL;
*decompressed_data_len = 0;
#if DEBUG_IP_PACKETS == 1
DEBUGP(DSNDCP, "\n");
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
DEBUGP(DSNDCP, "===================================================\n");
#endif
expnd = talloc_zero_size(ctx, compressed_data_len * MAX_DATADECOMPR_FAC +
MAX_HDRDECOMPR_INCR);
memcpy(expnd, compressed_data, compressed_data_len);
/* Apply data decompression */
rc = gprs_sndcp_dcomp_expand(expnd, compressed_data_len, sne->defrag.dcomp,
sne->defrag.data);
if (rc < 0) {
LOGP(DSNDCP, LOGL_ERROR,
"Data decompression failed!\n");
talloc_free(expnd);
return NULL;
}
/* Apply header decompression */
rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp, sne->defrag.proto);
if (rc < 0) {
LOGP(DSNDCP, LOGL_ERROR,
"TCP/IP Header decompression failed!\n");
talloc_free(expnd);
return NULL;
}
*decompressed_data_len = rc;
#if DEBUG_IP_PACKETS == 1
debug_ip_packet(expnd, *decompressed_data_len, 1, "defrag_segments()");
DEBUGP(DSNDCP, "===================================================\n");
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
DEBUGP(DSNDCP, "\n");
#endif
return expnd;
}
/* Perform actual defragmentation and create an output packet */
static int defrag_segments(struct gprs_sndcp_entity *sne)
{
struct msgb *msg;
unsigned int seg_nr;
uint8_t *npdu;
int npdu_len;
unsigned int npdu_len;
int rc;
uint8_t *expnd = NULL;
@ -336,53 +389,20 @@ static int defrag_segments(struct gprs_sndcp_entity *sne)
* hands it off to the correct GTP tunnel + GGSN via gtp_data_req() */
/* Decompress packet */
#if DEBUG_IP_PACKETS == 1
DEBUGP(DSNDCP, " \n");
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
DEBUGP(DSNDCP, "===================================================\n");
#endif
if (any_pcomp_or_dcomp_active(sgsn)) {
expnd = talloc_zero_size(msg, npdu_len * MAX_DATADECOMPR_FAC +
MAX_HDRDECOMPR_INCR);
memcpy(expnd, npdu, npdu_len);
/* Apply data decompression */
rc = gprs_sndcp_dcomp_expand(expnd, npdu_len, sne->defrag.dcomp,
sne->defrag.data);
if (rc < 0) {
LOGP(DSNDCP, LOGL_ERROR,
"Data decompression failed!\n");
talloc_free(expnd);
return -EIO;
expnd = decompress_segment(sne, msg, npdu, npdu_len, &npdu_len);
if (!expnd) {
rc = -EIO;
goto ret_free;
}
/* Apply header decompression */
rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp,
sne->defrag.proto);
if (rc < 0) {
LOGP(DSNDCP, LOGL_ERROR,
"TCP/IP Header decompression failed!\n");
talloc_free(expnd);
return -EIO;
}
/* Modify npu length, expnd is handed directly handed
* over to gsn_rx_sndcp_ud_ind(), see below */
npdu_len = rc;
} else
} else {
expnd = npdu;
#if DEBUG_IP_PACKETS == 1
debug_ip_packet(expnd, npdu_len, 1, "defrag_segments()");
DEBUGP(DSNDCP, "===================================================\n");
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
DEBUGP(DSNDCP, " \n");
#endif
}
/* Hand off packet to gtp */
rc = sgsn_rx_sndcp_ud_ind(&sne->ra_id, sne->lle->llme->tlli,
sne->nsapi, msg, npdu_len, expnd);
/* Hand off packet to SGSN (SNDCP SN-UNITDATA.ind), which will forward it to GGSN (GTP): */
rc = sndcp_sn_unitdata_ind(sne, msg, npdu_len, expnd);
ret_free:
/* we must free the memory we allocated above; ownership is not transferred
* downwards in the call above */
msgb_free(msg);
@ -522,7 +542,7 @@ int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
}
/* Entry point for the SNSM-DEACTIVATE.indication */
int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
int sndcp_sm_deactivate_ind(const struct gprs_llc_lle *lle, uint8_t nsapi)
{
struct gprs_sndcp_entity *sne;
@ -545,7 +565,7 @@ int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi)
}
/* Clean up all gprs_sndcp_entities related to llme (OS#4824) */
void gprs_sndcp_sm_deactivate_ind_by_llme(struct gprs_llc_llme *llme)
void gprs_sndcp_sm_deactivate_ind_by_llme(const struct gprs_llc_llme *llme)
{
struct gprs_sndcp_entity *sne, *sne2;
@ -665,7 +685,7 @@ static int sndcp_send_ud_frag(struct sndcp_frag_state *fs,
}
/* Request transmission of a SN-PDU over specified LLC Entity + SAPI */
int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
int sndcp_sn_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
void *mmcontext)
{
struct gprs_sndcp_entity *sne;
@ -723,13 +743,14 @@ int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi
sne = gprs_sndcp_entity_by_lle(lle, nsapi);
if (!sne) {
LOGP(DSNDCP, LOGL_ERROR, "Cannot find SNDCP Entity\n");
LOGP(DSNDCP, LOGL_ERROR, "Cannot find SNDCP Entity (lle=%p, TLLI=%08x, SAPI=%u, NSAPI=%u)\n",
lle, lle->llme->tlli, lle->sapi, nsapi);
msgb_free(msg);
return -EIO;
}
/* Check if we need to fragment this N-PDU into multiple SN-PDUs */
if (msg->len > lle->params.n201_u -
if (msg->len > lle->params.n201_u -
(sizeof(*sch) + sizeof(*suh) + sizeof(*scomph))) {
/* initialize the fragmenter state */
fs.msg = msg;
@ -774,7 +795,7 @@ int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi
}
/* Section 5.1.2.17 LL-UNITDATA.ind */
int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
int sndcp_ll_unitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
uint8_t *hdr, uint16_t len)
{
struct gprs_sndcp_entity *sne;
@ -844,63 +865,40 @@ int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
LOGP(DSNDCP, LOGL_ERROR, "Short SNDCP N-PDU: %d\n", npdu_len);
return -EIO;
}
/* actually send the N-PDU to the SGSN core code, which then
* hands it off to the correct GTP tunnel + GGSN via gtp_data_req() */
/* actually send the N-PDU to the SGSN core code (SNDCP SN-UNITDATA.ind) */
/* Decompress packet */
#if DEBUG_IP_PACKETS == 1
DEBUGP(DSNDCP, " \n");
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
DEBUGP(DSNDCP, "===================================================\n");
#endif
if (any_pcomp_or_dcomp_active(sgsn)) {
expnd = talloc_zero_size(msg, npdu_len * MAX_DATADECOMPR_FAC +
MAX_HDRDECOMPR_INCR);
memcpy(expnd, npdu, npdu_len);
/* Apply data decompression */
rc = gprs_sndcp_dcomp_expand(expnd, npdu_len, sne->defrag.dcomp,
sne->defrag.data);
if (rc < 0) {
LOGP(DSNDCP, LOGL_ERROR,
"Data decompression failed!\n");
talloc_free(expnd);
return -EIO;
expnd = decompress_segment(sne, msg, npdu, npdu_len, (unsigned int *)&npdu_len);
if (!expnd) {
rc = -EIO;
goto ret_free;
}
/* Apply header decompression */
rc = gprs_sndcp_pcomp_expand(expnd, rc, sne->defrag.pcomp,
sne->defrag.proto);
if (rc < 0) {
LOGP(DSNDCP, LOGL_ERROR,
"TCP/IP Header decompression failed!\n");
talloc_free(expnd);
return -EIO;
}
/* Modify npu length, expnd is handed directly handed
* over to gsn_rx_sndcp_ud_ind(), see below */
npdu_len = rc;
} else
} else {
expnd = npdu;
#if DEBUG_IP_PACKETS == 1
debug_ip_packet(expnd, npdu_len, 1, "sndcp_llunitdata_ind()");
DEBUGP(DSNDCP, "===================================================\n");
DEBUGP(DSNDCP, ":::::::::::::::::::::::::::::::::::::::::::::::::::\n");
DEBUGP(DSNDCP, " \n");
#endif
}
/* Hand off packet to gtp */
rc = sgsn_rx_sndcp_ud_ind(&sne->ra_id, lle->llme->tlli,
sne->nsapi, msg, npdu_len, expnd);
rc = sndcp_sn_unitdata_ind(sne, msg, npdu_len, expnd);
ret_free:
if (any_pcomp_or_dcomp_active(sgsn))
talloc_free(expnd);
return rc;
}
/* 5.1.1.4 SN-UNITDATA.indication
* Called by SNDCP when it has received/re-assembled a N-PDU
*/
int sndcp_sn_unitdata_ind(struct gprs_sndcp_entity *sne,
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu)
{
/* Hand it off N-PDU to the correct GTP tunnel + GGSN: */
return sgsn_gtp_data_req(&sne->ra_id, sne->lle->llme->tlli,
sne->nsapi, msg, npdu_len, npdu);
}
#if 0
/* Section 5.1.2.1 LL-RESET.ind */
static int sndcp_ll_reset_ind(struct gprs_sndcp_entity *se)
@ -1056,7 +1054,7 @@ int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi)
/* Handle header compression entites */
static int handle_pcomp_entities(struct gprs_sndcp_comp_field *comp_field,
struct gprs_llc_lle *lle)
const struct gprs_llc_lle *lle)
{
/* Note: This functions also transforms the comp_field into its
* echo form (strips comp values, resets propose bit etc...)
@ -1106,7 +1104,7 @@ static int handle_pcomp_entities(struct gprs_sndcp_comp_field *comp_field,
/* Hanle data compression entites */
static int handle_dcomp_entities(struct gprs_sndcp_comp_field *comp_field,
struct gprs_llc_lle *lle)
const struct gprs_llc_lle *lle)
{
/* See note in handle_pcomp_entities() */
@ -1148,7 +1146,7 @@ static int handle_dcomp_entities(struct gprs_sndcp_comp_field *comp_field,
* (See also: TS 144 065, Section 6.8 XID parameter negotiation) */
int sndcp_sn_xid_ind(struct gprs_llc_xid_field *xid_field_indication,
struct gprs_llc_xid_field *xid_field_response,
struct gprs_llc_lle *lle)
const struct gprs_llc_lle *lle)
{
/* Note: This function computes the SNDCP-XID response that is sent
* back to the ms when a ms originated XID is received. The

View File

@ -30,7 +30,7 @@
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_utils.h>
@ -48,8 +48,6 @@
(gsup)->imsi, \
## args)
extern void *tall_sgsn_ctx;
LLIST_HEAD(_gprs_subscribers);
struct llist_head * const gprs_subscribers = &_gprs_subscribers;
@ -378,7 +376,8 @@ static void gprs_subscr_gsup_insert_data(struct gprs_subscr *subscr,
}
OSMO_ASSERT(pdp_data != NULL);
pdp_data->pdp_type = pdp_info->pdp_type;
pdp_data->pdp_type_org = pdp_info->pdp_type_org;
pdp_data->pdp_type_nr = pdp_info->pdp_type_nr;
osmo_apn_to_str(pdp_data->apn_str,
pdp_info->apn_enc, pdp_info->apn_enc_len);

178
src/sgsn/gtp_ggsn.c Normal file
View File

@ -0,0 +1,178 @@
/* GGSN context (peer) */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* 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/>.
*
*/
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/gtp.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <osmocom/sgsn/gprs_sm.h>
#include <osmocom/sgsn/pdpctx.h>
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc)
{
bool pending = osmo_timer_pending(&ggc->echo_timer);
/* Only enable if allowed by policy and at least 1 pdp ctx exists against ggsn */
if (!llist_empty(&ggc->pdp_list) && ggc->echo_interval) {
if (!pending)
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
} else {
if (pending)
osmo_timer_del(&ggc->echo_timer);
}
}
/* GGSN contexts */
static void echo_timer_cb(void *data)
{
struct sgsn_ggsn_ctx *ggc = (struct sgsn_ggsn_ctx *) data;
sgsn_ggsn_echo_req(ggc);
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
}
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(struct sgsn_instance *sgsn, uint32_t id)
{
struct sgsn_ggsn_ctx *ggc;
ggc = talloc_zero(sgsn, struct sgsn_ggsn_ctx);
if (!ggc)
return NULL;
ggc->id = id;
ggc->gtp_version = 1;
ggc->remote_restart_ctr = -1;
/* if we are called from config file parse, this gsn doesn't exist yet */
ggc->gsn = sgsn->gsn;
INIT_LLIST_HEAD(&ggc->pdp_list);
osmo_timer_setup(&ggc->echo_timer, echo_timer_cb, ggc);
llist_add(&ggc->list, &sgsn->ggsn_list);
return ggc;
}
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc)
{
OSMO_ASSERT(llist_empty(&ggc->pdp_list));
llist_del(&ggc->list);
talloc_free(ggc);
}
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(struct sgsn_instance *sgsn, uint32_t id)
{
struct sgsn_ggsn_ctx *ggc;
llist_for_each_entry(ggc, &sgsn->ggsn_list, list) {
if (id == ggc->id)
return ggc;
}
return NULL;
}
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct sgsn_instance *sgsn, struct in_addr *addr)
{
struct sgsn_ggsn_ctx *ggc;
llist_for_each_entry(ggc, &sgsn->ggsn_list, list) {
if (!memcmp(addr, &ggc->remote_addr, sizeof(*addr)))
return ggc;
}
return NULL;
}
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(struct sgsn_instance *sgsn, uint32_t id)
{
struct sgsn_ggsn_ctx *ggc;
ggc = sgsn_ggsn_ctx_by_id(sgsn, id);
if (!ggc)
ggc = sgsn_ggsn_ctx_alloc(sgsn, id);
return ggc;
}
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx)
{
/* the MM context can be deleted while the GGSN is not reachable or
* if has been crashed. */
if (pctx->mm && pctx->mm->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL) {
gsm48_tx_gsm_deact_pdp_req(pctx, GSM_CAUSE_NET_FAIL, true);
sgsn_ggsn_ctx_remove_pdp(pctx->ggsn, pctx);
} else {
/* FIXME: GPRS paging in case MS is SUSPENDED */
LOGPDPCTXP(LOGL_NOTICE, pctx, "Hard-dropping PDP ctx due to GGSN "
"recovery\n");
/* FIXME: how to tell this to libgtp? */
sgsn_pdp_ctx_free(pctx);
}
}
/* 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. */
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except)
{
int num = 0;
struct sgsn_pdp_ctx *pdp, *pdp2;
llist_for_each_entry_safe(pdp, pdp2, &ggsn->pdp_list, ggsn_list) {
if (pdp == except)
continue;
sgsn_ggsn_ctx_drop_pdp(pdp);
num++;
}
return num;
}
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn)
{
return sgsn_ggsn_ctx_drop_all_pdp_except(ggsn, NULL);
}
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
{
llist_add(&pdp->ggsn_list, &ggc->pdp_list);
sgsn_ggsn_ctx_check_echo_timer(ggc);
}
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
{
llist_del(&pdp->ggsn_list);
sgsn_ggsn_ctx_check_echo_timer(ggc);
if (pdp->destroy_ggsn)
sgsn_ggsn_ctx_free(pdp->ggsn);
pdp->ggsn = NULL;
/* Drop references to libgtp since the conn is down */
if (pdp->lib)
pdp_freepdp(pdp->lib);
pdp->lib = NULL;
}

View File

@ -1,6 +1,6 @@
/* TS 29.060 § 7.5.14 RAN Information Management Messages */
/*
* (C) 2021 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
* (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* SPDX-License-Identifier: AGPL-3.0+
@ -26,8 +26,6 @@
#include <osmocom/sgsn/gtp_mme.h>
#include <osmocom/sgsn/sgsn.h>
extern void *tall_sgsn_ctx;
static bool _eutran_tai_equal(const struct osmo_eutran_tai *t1, const struct osmo_eutran_tai *t2)
{
return t1->mcc == t2->mcc &&
@ -39,7 +37,7 @@ static bool _eutran_tai_equal(const struct osmo_eutran_tai *t1, const struct osm
struct sgsn_mme_ctx *sgsn_mme_ctx_alloc(struct sgsn_instance *sgsn, const char *name)
{
struct sgsn_mme_ctx *mme;
mme = talloc_zero(tall_sgsn_ctx, struct sgsn_mme_ctx);
mme = talloc_zero(sgsn, struct sgsn_mme_ctx);
if (!mme)
return NULL;

View File

@ -1,4 +1,4 @@
/* GPRS SGSN functionality */
/* Mobility Management context */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
*
@ -27,6 +27,8 @@
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/backtrace.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/ports.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
@ -36,7 +38,7 @@
#include <osmocom/sgsn/gprs_subscriber.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_sm.h>
@ -47,22 +49,16 @@
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_sndcp.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/gtp.h>
#include <osmocom/sgsn/pdpctx.h>
#include <pdp.h>
#include <time.h>
#include "../../bscconfig.h"
#define GPRS_LLME_CHECK_TICK 30
extern struct sgsn_instance *sgsn;
extern void *tall_sgsn_ctx;
LLIST_HEAD(sgsn_mm_ctxts);
LLIST_HEAD(sgsn_ggsn_ctxts);
LLIST_HEAD(sgsn_apn_ctxts);
LLIST_HEAD(sgsn_pdp_ctxts);
#include "../../config.h"
const struct value_string sgsn_ran_type_names[] = {
{ MM_CTX_T_GERAN_Gb, "GPRS/EDGE via Gb" },
@ -95,66 +91,12 @@ static const struct rate_ctr_group_desc mmctx_ctrg_desc = {
.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
};
static const struct rate_ctr_desc pdpctx_ctr_description[] = {
{ "udata:packets:in", "User Data Messages ( In)" },
{ "udata:packets:out", "User Data Messages (Out)" },
{ "udata:bytes:in", "User Data Bytes ( In)" },
{ "udata:bytes:out", "User Data Bytes (Out)" },
};
static const struct rate_ctr_group_desc pdpctx_ctrg_desc = {
.group_name_prefix = "sgsn:pdpctx",
.group_description = "SGSN PDP Context Statistics",
.num_ctr = ARRAY_SIZE(pdpctx_ctr_description),
.ctr_desc = pdpctx_ctr_description,
.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
};
static const struct rate_ctr_desc sgsn_ctr_description[] = {
{ "llc:dl_bytes", "Count sent LLC bytes before giving it to the bssgp layer" },
{ "llc:ul_bytes", "Count successful received LLC bytes (encrypt & fcs correct)" },
{ "llc:dl_packets", "Count successful sent LLC packets before giving it to the bssgp layer" },
{ "llc:ul_packets", "Count successful received LLC packets (encrypt & fcs correct)" },
{ "gprs:attach_requested", "Received attach requests" },
{ "gprs:attach_accepted", "Sent attach accepts" },
{ "gprs:attach_rejected", "Sent attach rejects" },
{ "gprs:detach_requested", "Received detach requests" },
{ "gprs:detach_acked", "Sent detach acks" },
{ "gprs:routing_area_requested", "Received routing area requests" },
{ "gprs:routing_area_requested", "Sent routing area acks" },
{ "gprs:routing_area_requested", "Sent routing area rejects" },
{ "pdp:activate_requested", "Received activate requests" },
{ "pdp:activate_rejected", "Sent activate rejects" },
{ "pdp:activate_accepted", "Sent activate accepts" },
{ "pdp:request_activated", "unused" },
{ "pdp:request_activate_rejected", "unused" },
{ "pdp:modify_requested", "unused" },
{ "pdp:modify_accepted", "unused" },
{ "pdp:dl_deactivate_requested", "Sent deactivate requests" },
{ "pdp:dl_deactivate_accepted", "Sent deactivate accepted" },
{ "pdp:ul_deactivate_requested", "Received deactivate requests" },
{ "pdp:ul_deactivate_accepted", "Received deactivate accepts" },
};
static const struct rate_ctr_group_desc sgsn_ctrg_desc = {
"sgsn",
"SGSN Overall Statistics",
OSMO_STATS_CLASS_GLOBAL,
ARRAY_SIZE(sgsn_ctr_description),
sgsn_ctr_description,
};
void sgsn_rate_ctr_init() {
sgsn->rate_ctrs = rate_ctr_group_alloc(tall_sgsn_ctx, &sgsn_ctrg_desc, 0);
OSMO_ASSERT(sgsn->rate_ctrs);
}
/* look-up an SGSN MM context based on Iu UE context (struct ue_conn_ctx)*/
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx)
{
struct sgsn_mm_ctx *ctx;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
if (ctx->ran_type == MM_CTX_T_UTRAN_Iu
&& uectx == ctx->iu.ue_ctx)
return ctx;
@ -169,7 +111,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
{
struct sgsn_mm_ctx *ctx;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
if ((tlli == ctx->gb.tlli || tlli == ctx->gb.tlli_new) &&
gprs_ra_id_equals(raid, &ctx->ra))
return ctx;
@ -193,7 +135,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
if (tlli_type != TLLI_FOREIGN && tlli_type != TLLI_LOCAL)
return NULL;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
if ((gprs_tmsi2tlli(ctx->p_tmsi, tlli_type) == tlli ||
gprs_tmsi2tlli(ctx->p_tmsi_old, tlli_type) == tlli) &&
gprs_ra_id_equals(raid, &ctx->ra))
@ -207,7 +149,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t p_tmsi)
{
struct sgsn_mm_ctx *ctx;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
if (p_tmsi == ctx->p_tmsi ||
(ctx->p_tmsi_old && ctx->p_tmsi_old == p_tmsi))
return ctx;
@ -219,7 +161,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi)
{
struct sgsn_mm_ctx *ctx;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
llist_for_each_entry(ctx, &sgsn->mm_list, list) {
if (!strcmp(imsi, ctx->imsi))
return ctx;
}
@ -261,7 +203,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t rate_ctr_id)
INIT_LLIST_HEAD(&ctx->pdp_list);
llist_add(&ctx->list, &sgsn_mm_ctxts);
llist_add(&ctx->list, &sgsn->mm_list);
return ctx;
@ -432,288 +374,6 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
return NULL;
}
/* you don't want to use this directly, call sgsn_create_pdp_ctx() */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
struct sgsn_ggsn_ctx *ggsn,
uint8_t nsapi)
{
struct sgsn_pdp_ctx *pdp;
pdp = sgsn_pdp_ctx_by_nsapi(mm, nsapi);
if (pdp)
return NULL;
pdp = talloc_zero(tall_sgsn_ctx, struct sgsn_pdp_ctx);
if (!pdp)
return NULL;
pdp->mm = mm;
pdp->ggsn = ggsn;
pdp->nsapi = nsapi;
pdp->ctrg = rate_ctr_group_alloc(pdp, &pdpctx_ctrg_desc, nsapi);
if (!pdp->ctrg) {
LOGPDPCTXP(LOGL_ERROR, pdp, "Error allocation counter group\n");
talloc_free(pdp);
return NULL;
}
llist_add(&pdp->list, &mm->pdp_list);
sgsn_ggsn_ctx_add_pdp(pdp->ggsn, pdp);
llist_add(&pdp->g_list, &sgsn_pdp_ctxts);
return pdp;
}
/*
* This function will not trigger any GSM DEACT PDP ACK messages, so you
* probably want to call sgsn_delete_pdp_ctx() instead if the connection
* isn't detached already.
*/
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp)
{
struct sgsn_signal_data sig_data;
OSMO_ASSERT(pdp->mm != NULL);
/* There might still be pending callbacks in libgtp. So the parts of
* this object relevant to GTP need to remain intact in this case. */
LOGPDPCTXP(LOGL_INFO, pdp, "Forcing release of PDP context\n");
if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
/* Force the deactivation of the SNDCP layer */
if (pdp->mm->gb.llme)
sndcp_sm_deactivate_ind(&pdp->mm->gb.llme->lle[pdp->sapi], pdp->nsapi);
}
memset(&sig_data, 0, sizeof(sig_data));
sig_data.pdp = pdp;
osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_TERMINATE, &sig_data);
/* Detach from MM context */
pdp_ctx_detach_mm_ctx(pdp);
if (pdp->ggsn)
sgsn_delete_pdp_ctx(pdp);
}
/*
* Don't call this function directly unless you know what you are doing.
* In normal conditions use sgsn_delete_pdp_ctx and in unspecified or
* implementation dependent abnormal ones sgsn_pdp_ctx_terminate.
*/
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
{
struct sgsn_signal_data sig_data;
memset(&sig_data, 0, sizeof(sig_data));
sig_data.pdp = pdp;
osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_FREE, &sig_data);
if (osmo_timer_pending(&pdp->timer)) {
LOGPDPCTXP(LOGL_ERROR, pdp, "Freeing PDP ctx with timer %u pending\n", pdp->T);
osmo_timer_del(&pdp->timer);
}
rate_ctr_group_free(pdp->ctrg);
if (pdp->mm)
llist_del(&pdp->list);
if (pdp->ggsn)
sgsn_ggsn_ctx_remove_pdp(pdp->ggsn, pdp);
llist_del(&pdp->g_list);
/* _if_ we still have a library handle, at least set it to NULL
* to avoid any dereferences of the now-deleted PDP context from
* sgsn_libgtp:cb_data_ind() */
if (pdp->lib) {
struct pdp_t *lib = pdp->lib;
LOGPDPCTXP(LOGL_NOTICE, pdp, "freeing PDP context that still "
"has a libgtp handle attached to it, this shouldn't "
"happen!\n");
osmo_generate_backtrace();
lib->priv = NULL;
}
talloc_free(pdp);
}
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc)
{
bool pending = osmo_timer_pending(&ggc->echo_timer);
/* Only enable if allowed by policy and at least 1 pdp ctx exists against ggsn */
if (!llist_empty(&ggc->pdp_list) && ggc->echo_interval) {
if (!pending)
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
} else {
if (pending)
osmo_timer_del(&ggc->echo_timer);
}
}
/* GGSN contexts */
static void echo_timer_cb(void *data)
{
struct sgsn_ggsn_ctx *ggc = (struct sgsn_ggsn_ctx *) data;
sgsn_ggsn_echo_req(ggc);
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
}
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id)
{
struct sgsn_ggsn_ctx *ggc;
ggc = talloc_zero(tall_sgsn_ctx, struct sgsn_ggsn_ctx);
if (!ggc)
return NULL;
ggc->id = id;
ggc->gtp_version = 1;
ggc->remote_restart_ctr = -1;
/* if we are called from config file parse, this gsn doesn't exist yet */
ggc->gsn = sgsn->gsn;
INIT_LLIST_HEAD(&ggc->pdp_list);
osmo_timer_setup(&ggc->echo_timer, echo_timer_cb, ggc);
llist_add(&ggc->list, &sgsn_ggsn_ctxts);
return ggc;
}
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc)
{
OSMO_ASSERT(llist_empty(&ggc->pdp_list));
llist_del(&ggc->list);
talloc_free(ggc);
}
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id)
{
struct sgsn_ggsn_ctx *ggc;
llist_for_each_entry(ggc, &sgsn_ggsn_ctxts, list) {
if (id == ggc->id)
return ggc;
}
return NULL;
}
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr)
{
struct sgsn_ggsn_ctx *ggc;
llist_for_each_entry(ggc, &sgsn_ggsn_ctxts, list) {
if (!memcmp(addr, &ggc->remote_addr, sizeof(*addr)))
return ggc;
}
return NULL;
}
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id)
{
struct sgsn_ggsn_ctx *ggc;
ggc = sgsn_ggsn_ctx_by_id(id);
if (!ggc)
ggc = sgsn_ggsn_ctx_alloc(id);
return ggc;
}
/* APN contexts */
static struct apn_ctx *sgsn_apn_ctx_alloc(const char *ap_name, const char *imsi_prefix)
{
struct apn_ctx *actx;
actx = talloc_zero(tall_sgsn_ctx, struct apn_ctx);
if (!actx)
return NULL;
actx->name = talloc_strdup(actx, ap_name);
actx->imsi_prefix = talloc_strdup(actx, imsi_prefix);
llist_add_tail(&actx->list, &sgsn_apn_ctxts);
return actx;
}
void sgsn_apn_ctx_free(struct apn_ctx *actx)
{
llist_del(&actx->list);
talloc_free(actx);
}
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi)
{
struct apn_ctx *actx;
struct apn_ctx *found_actx = NULL;
size_t imsi_prio = 0;
size_t name_prio = 0;
size_t name_req_len = strlen(name);
llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
size_t name_ref_len, imsi_ref_len;
const char *name_ref_start, *name_match_start;
imsi_ref_len = strlen(actx->imsi_prefix);
if (strncmp(actx->imsi_prefix, imsi, imsi_ref_len) != 0)
continue;
if (imsi_ref_len < imsi_prio)
continue;
/* IMSI matches */
name_ref_start = &actx->name[0];
if (name_ref_start[0] == '*') {
/* Suffix match */
name_ref_start += 1;
name_ref_len = strlen(name_ref_start);
if (name_ref_len > name_req_len)
continue;
} else {
name_ref_len = strlen(name_ref_start);
if (name_ref_len != name_req_len)
continue;
}
name_match_start = name + (name_req_len - name_ref_len);
if (strcasecmp(name_match_start, name_ref_start) != 0)
continue;
/* IMSI and name match */
if (imsi_ref_len == imsi_prio && name_ref_len < name_prio)
/* Lower priority, skip */
continue;
imsi_prio = imsi_ref_len;
name_prio = name_ref_len;
found_actx = actx;
}
return found_actx;
}
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix)
{
struct apn_ctx *actx;
llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
if (strcasecmp(name, actx->name) == 0 &&
strcasecmp(imsi_prefix, actx->imsi_prefix) == 0)
return actx;
}
return NULL;
}
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix)
{
struct apn_ctx *actx;
actx = sgsn_apn_ctx_by_name(name, imsi_prefix);
if (!actx)
actx = sgsn_apn_ctx_alloc(name, imsi_prefix);
return actx;
}
uint32_t sgsn_alloc_ptmsi(void)
{
struct sgsn_mm_ctx *mm;
@ -749,7 +409,7 @@ restart:
goto restart;
}
llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
llist_for_each_entry(mm, &sgsn->mm_list, list) {
if (mm->p_tmsi == ptmsi) {
if (!max_retries--)
goto failed;
@ -764,64 +424,6 @@ failed:
return GSM_RESERVED_TMSI;
}
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx)
{
/* the MM context can be deleted while the GGSN is not reachable or
* if has been crashed. */
if (pctx->mm && pctx->mm->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL) {
gsm48_tx_gsm_deact_pdp_req(pctx, GSM_CAUSE_NET_FAIL, true);
sgsn_ggsn_ctx_remove_pdp(pctx->ggsn, pctx);
} else {
/* FIXME: GPRS paging in case MS is SUSPENDED */
LOGPDPCTXP(LOGL_NOTICE, pctx, "Hard-dropping PDP ctx due to GGSN "
"recovery\n");
/* FIXME: how to tell this to libgtp? */
sgsn_pdp_ctx_free(pctx);
}
}
/* 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. */
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except)
{
int num = 0;
struct sgsn_pdp_ctx *pdp, *pdp2;
llist_for_each_entry_safe(pdp, pdp2, &ggsn->pdp_list, ggsn_list) {
if (pdp == except)
continue;
sgsn_ggsn_ctx_drop_pdp(pdp);
num++;
}
return num;
}
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn)
{
return sgsn_ggsn_ctx_drop_all_pdp_except(ggsn, NULL);
}
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
{
llist_add(&pdp->ggsn_list, &ggc->pdp_list);
sgsn_ggsn_ctx_check_echo_timer(ggc);
}
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
{
llist_del(&pdp->ggsn_list);
sgsn_ggsn_ctx_check_echo_timer(ggc);
if (pdp->destroy_ggsn)
sgsn_ggsn_ctx_free(pdp->ggsn);
pdp->ggsn = NULL;
/* Drop references to libgtp since the conn is down */
if (pdp->lib)
pdp_freepdp(pdp->lib);
pdp->lib = NULL;
}
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
{
OSMO_ASSERT(mmctx != NULL);
@ -896,7 +498,7 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
continue;
}
if (!llist_empty(&sgsn_apn_ctxts)) {
if (!llist_empty(&sgsn->apn_list)) {
apn_ctx = sgsn_apn_ctx_match(req_apn_str, mmctx->imsi);
/* Not configured */
if (apn_ctx == NULL)
@ -949,13 +551,13 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
if (apn_ctx != NULL) {
ggsn = apn_ctx->ggsn;
} else if (llist_empty(&sgsn_apn_ctxts)) {
} else if (llist_empty(&sgsn->apn_list)) {
/* No configuration -> use GGSN 0 */
ggsn = sgsn_ggsn_ctx_by_id(0);
ggsn = sgsn_ggsn_ctx_by_id(sgsn, 0);
} else if (allow_any_apn &&
(selected_apn_str == NULL || strlen(selected_apn_str) == 0)) {
/* No APN given and no default configuration -> Use GGSN 0 */
ggsn = sgsn_ggsn_ctx_by_id(0);
ggsn = sgsn_ggsn_ctx_by_id(sgsn, 0);
} else {
/* No matching configuration found */
LOGMMCTXP(LOGL_NOTICE, mmctx,
@ -980,72 +582,3 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
return ggsn;
}
static void sgsn_llme_cleanup_free(struct gprs_llc_llme *llme)
{
struct sgsn_mm_ctx *mmctx = NULL;
llist_for_each_entry(mmctx, &sgsn_mm_ctxts, list) {
if (llme == mmctx->gb.llme) {
gsm0408_gprs_access_cancelled(mmctx, SGSN_ERROR_CAUSE_NONE);
return;
}
}
/* No MM context found */
LOGP(DGPRS, LOGL_INFO, "Deleting orphaned LLME, TLLI 0x%08x\n",
llme->tlli);
gprs_llgmm_unassign(llme);
}
static void sgsn_llme_check_cb(void *data_)
{
struct gprs_llc_llme *llme, *llme_tmp;
struct timespec now_tp;
time_t now, age;
time_t max_age = gprs_max_time_to_idle();
int rc;
rc = osmo_clock_gettime(CLOCK_MONOTONIC, &now_tp);
OSMO_ASSERT(rc >= 0);
now = now_tp.tv_sec;
LOGP(DGPRS, LOGL_DEBUG,
"Checking for inactive LLMEs, time = %u\n", (unsigned)now);
llist_for_each_entry_safe(llme, llme_tmp, &gprs_llc_llmes, list) {
if (llme->age_timestamp == GPRS_LLME_RESET_AGE)
llme->age_timestamp = now;
age = now - llme->age_timestamp;
if (age > max_age || age < 0) {
LOGP(DGPRS, LOGL_INFO,
"Inactivity timeout for TLLI 0x%08x, age %d\n",
llme->tlli, (int)age);
sgsn_llme_cleanup_free(llme);
}
}
osmo_timer_schedule(&sgsn->llme_timer, GPRS_LLME_CHECK_TICK, 0);
}
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx)
{
struct sgsn_instance *inst;
inst = talloc_zero(talloc_ctx, struct sgsn_instance);
inst->cfg.gtp_statedir = talloc_strdup(inst, "./");
inst->cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
inst->cfg.require_authentication = true; /* only applies if auth_policy is REMOTE */
inst->cfg.gsup_server_port = OSMO_GSUP_PORT;
INIT_LLIST_HEAD(&inst->mme_list);
return inst;
}
void sgsn_inst_init(struct sgsn_instance *sgsn)
{
osmo_timer_setup(&sgsn->llme_timer, sgsn_llme_check_cb, NULL);
osmo_timer_schedule(&sgsn->llme_timer, GPRS_LLME_CHECK_TICK, 0);
}

158
src/sgsn/pdpctx.c Normal file
View File

@ -0,0 +1,158 @@
/* PDP context functionality */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* 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/>.
*
*/
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
#include <osmocom/sgsn/pdpctx.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/signal.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/gprs_llc_xid.h>
#include <osmocom/sgsn/gprs_sndcp.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_sm.h>
#include <osmocom/sgsn/gtp.h>
static const struct rate_ctr_desc pdpctx_ctr_description[] = {
{ "udata:packets:in", "User Data Messages ( In)" },
{ "udata:packets:out", "User Data Messages (Out)" },
{ "udata:bytes:in", "User Data Bytes ( In)" },
{ "udata:bytes:out", "User Data Bytes (Out)" },
};
static const struct rate_ctr_group_desc pdpctx_ctrg_desc = {
.group_name_prefix = "sgsn:pdpctx",
.group_description = "SGSN PDP Context Statistics",
.num_ctr = ARRAY_SIZE(pdpctx_ctr_description),
.ctr_desc = pdpctx_ctr_description,
.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
};
/* you don't want to use this directly, call sgsn_create_pdp_ctx() */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
struct sgsn_ggsn_ctx *ggsn,
uint8_t nsapi)
{
struct sgsn_pdp_ctx *pdp;
pdp = sgsn_pdp_ctx_by_nsapi(mm, nsapi);
if (pdp)
return NULL;
pdp = talloc_zero(sgsn, struct sgsn_pdp_ctx);
if (!pdp)
return NULL;
pdp->mm = mm;
pdp->ggsn = ggsn;
pdp->nsapi = nsapi;
pdp->ctrg = rate_ctr_group_alloc(pdp, &pdpctx_ctrg_desc, nsapi);
if (!pdp->ctrg) {
LOGPDPCTXP(LOGL_ERROR, pdp, "Error allocation counter group\n");
talloc_free(pdp);
return NULL;
}
llist_add(&pdp->list, &mm->pdp_list);
sgsn_ggsn_ctx_add_pdp(pdp->ggsn, pdp);
llist_add(&pdp->g_list, &sgsn->pdp_list);
return pdp;
}
/*
* This function will not trigger any GSM DEACT PDP ACK messages, so you
* probably want to call sgsn_delete_pdp_ctx() instead if the connection
* isn't detached already.
*/
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp)
{
struct sgsn_signal_data sig_data;
OSMO_ASSERT(pdp->mm != NULL);
/* There might still be pending callbacks in libgtp. So the parts of
* this object relevant to GTP need to remain intact in this case. */
LOGPDPCTXP(LOGL_INFO, pdp, "Forcing release of PDP context\n");
if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
/* Force the deactivation of the SNDCP layer */
if (pdp->mm->gb.llme)
sndcp_sm_deactivate_ind(&pdp->mm->gb.llme->lle[pdp->sapi], pdp->nsapi);
}
memset(&sig_data, 0, sizeof(sig_data));
sig_data.pdp = pdp;
osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_TERMINATE, &sig_data);
/* Detach from MM context */
pdp_ctx_detach_mm_ctx(pdp);
if (pdp->ggsn)
sgsn_delete_pdp_ctx(pdp);
}
/*
* Don't call this function directly unless you know what you are doing.
* In normal conditions use sgsn_delete_pdp_ctx and in unspecified or
* implementation dependent abnormal ones sgsn_pdp_ctx_terminate.
*/
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
{
struct sgsn_signal_data sig_data;
memset(&sig_data, 0, sizeof(sig_data));
sig_data.pdp = pdp;
osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_FREE, &sig_data);
if (osmo_timer_pending(&pdp->timer)) {
LOGPDPCTXP(LOGL_ERROR, pdp, "Freeing PDP ctx with timer %u pending\n", pdp->T);
osmo_timer_del(&pdp->timer);
}
rate_ctr_group_free(pdp->ctrg);
if (pdp->mm)
llist_del(&pdp->list);
if (pdp->ggsn)
sgsn_ggsn_ctx_remove_pdp(pdp->ggsn, pdp);
llist_del(&pdp->g_list);
/* _if_ we still have a library handle, at least set it to NULL
* to avoid any dereferences of the now-deleted PDP context from
* sgsn_libgtp:cb_data_ind() */
if (pdp->lib) {
struct pdp_t *lib = pdp->lib;
LOGPDPCTXP(LOGL_NOTICE, pdp, "freeing PDP context that still "
"has a libgtp handle attached to it, this shouldn't "
"happen!\n");
osmo_generate_backtrace();
lib->priv = NULL;
}
talloc_free(pdp);
}

220
src/sgsn/sgsn.c Normal file
View File

@ -0,0 +1,220 @@
/* SGSN instance */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* 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/>.
*
*/
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/backtrace.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/ports.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/apn.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/crypt/gprs_cipher.h>
#include <osmocom/crypt/utran_cipher.h>
#include <osmocom/sgsn/gprs_subscriber.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_sm.h>
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/signal.h>
#include <osmocom/sgsn/gprs_gmm_attach.h>
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_sndcp.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/gtp.h>
#include <osmocom/sgsn/pdpctx.h>
#include <pdp.h>
#include <time.h>
#define GPRS_LLME_CHECK_TICK 30
extern struct osmo_tdef sgsn_T_defs[];
static const struct rate_ctr_desc sgsn_ctr_description[] = {
{ "llc:dl_bytes", "Count sent LLC bytes before giving it to the bssgp layer" },
{ "llc:ul_bytes", "Count successful received LLC bytes (encrypt & fcs correct)" },
{ "llc:dl_packets", "Count successful sent LLC packets before giving it to the bssgp layer" },
{ "llc:ul_packets", "Count successful received LLC packets (encrypt & fcs correct)" },
{ "gprs:attach_requested", "Received attach requests" },
{ "gprs:attach_accepted", "Sent attach accepts" },
{ "gprs:attach_rejected", "Sent attach rejects" },
{ "gprs:detach_requested", "Received detach requests" },
{ "gprs:detach_acked", "Sent detach acks" },
{ "gprs:routing_area_requested", "Received routing area requests" },
{ "gprs:routing_area_requested", "Sent routing area acks" },
{ "gprs:routing_area_requested", "Sent routing area rejects" },
{ "pdp:activate_requested", "Received activate requests" },
{ "pdp:activate_rejected", "Sent activate rejects" },
{ "pdp:activate_accepted", "Sent activate accepts" },
{ "pdp:request_activated", "unused" },
{ "pdp:request_activate_rejected", "unused" },
{ "pdp:modify_requested", "unused" },
{ "pdp:modify_accepted", "unused" },
{ "pdp:dl_deactivate_requested", "Sent deactivate requests" },
{ "pdp:dl_deactivate_accepted", "Sent deactivate accepted" },
{ "pdp:ul_deactivate_requested", "Received deactivate requests" },
{ "pdp:ul_deactivate_accepted", "Received deactivate accepts" },
};
static const struct rate_ctr_group_desc sgsn_ctrg_desc = {
"sgsn",
"SGSN Overall Statistics",
OSMO_STATS_CLASS_GLOBAL,
ARRAY_SIZE(sgsn_ctr_description),
sgsn_ctr_description,
};
static void sgsn_llme_cleanup_free(struct gprs_llc_llme *llme)
{
struct sgsn_mm_ctx *mmctx = NULL;
llist_for_each_entry(mmctx, &sgsn->mm_list, list) {
if (llme == mmctx->gb.llme) {
gsm0408_gprs_access_cancelled(mmctx, SGSN_ERROR_CAUSE_NONE);
return;
}
}
/* No MM context found */
LOGP(DGPRS, LOGL_INFO, "Deleting orphaned LLME, TLLI 0x%08x\n",
llme->tlli);
gprs_llgmm_unassign(llme);
}
static void sgsn_llme_check_cb(void *data_)
{
struct gprs_llc_llme *llme, *llme_tmp;
struct timespec now_tp;
time_t now, age;
time_t max_age = gprs_max_time_to_idle();
int rc;
rc = osmo_clock_gettime(CLOCK_MONOTONIC, &now_tp);
OSMO_ASSERT(rc >= 0);
now = now_tp.tv_sec;
LOGP(DGPRS, LOGL_DEBUG,
"Checking for inactive LLMEs, time = %u\n", (unsigned)now);
llist_for_each_entry_safe(llme, llme_tmp, &gprs_llc_llmes, list) {
if (llme->age_timestamp == GPRS_LLME_RESET_AGE)
llme->age_timestamp = now;
age = now - llme->age_timestamp;
if (age > max_age || age < 0) {
LOGP(DGPRS, LOGL_INFO,
"Inactivity timeout for TLLI 0x%08x, age %d\n",
llme->tlli, (int)age);
sgsn_llme_cleanup_free(llme);
}
}
osmo_timer_schedule(&sgsn->llme_timer, GPRS_LLME_CHECK_TICK, 0);
}
static int sgsn_instance_talloc_destructor(struct sgsn_instance *sgi)
{
sgsn_cdr_release(sgi);
osmo_timer_del(&sgi->llme_timer);
rate_ctr_group_free(sgi->rate_ctrs);
return 0;
}
struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx)
{
struct sgsn_instance *inst;
inst = talloc_zero(talloc_ctx, struct sgsn_instance);
talloc_set_destructor(inst, sgsn_instance_talloc_destructor);
inst->cfg.gtp_statedir = talloc_strdup(inst, "./");
inst->cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
inst->cfg.gea_encryption_mask = (1 << GPRS_ALGO_GEA0); /* no encryption */
inst->cfg.uea_encryption_mask = (1 << OSMO_UTRAN_UEA2) | (1 << OSMO_UTRAN_UEA1);
inst->cfg.require_authentication = true; /* only applies if auth_policy is REMOTE */
inst->cfg.gsup_server_port = OSMO_GSUP_PORT;
inst->cfg.T_defs = sgsn_T_defs;
osmo_tdefs_reset(inst->cfg.T_defs);
inst->cfg.T_defs_gtp = gtp_T_defs;
osmo_tdefs_reset(inst->cfg.T_defs_gtp);
inst->rate_ctrs = rate_ctr_group_alloc(inst, &sgsn_ctrg_desc, 0);
OSMO_ASSERT(inst->rate_ctrs);
INIT_LLIST_HEAD(&inst->apn_list);
INIT_LLIST_HEAD(&inst->ggsn_list);
INIT_LLIST_HEAD(&inst->mme_list);
INIT_LLIST_HEAD(&inst->mm_list);
INIT_LLIST_HEAD(&inst->pdp_list);
osmo_timer_setup(&inst->llme_timer, sgsn_llme_check_cb, NULL);
osmo_timer_schedule(&inst->llme_timer, GPRS_LLME_CHECK_TICK, 0);
/* These are mostly setting up stuff not related to VTY cfg, so they can be set up here: */
sgsn_auth_init(inst);
sgsn_cdr_init(inst);
return inst;
}
/* To be called after VTY config parsing: */
int sgsn_inst_init(struct sgsn_instance *sgsn)
{
int rc;
/* start control interface after reading config for
* ctrl_vty_get_bind_addr() */
sgsn->ctrlh = ctrl_interface_setup(NULL, OSMO_CTRL_PORT_SGSN, NULL);
if (!sgsn->ctrlh) {
LOGP(DGPRS, LOGL_ERROR, "Failed to create CTRL interface.\n");
return -EIO;
}
rc = sgsn_ctrl_cmds_install();
if (rc != 0) {
LOGP(DGPRS, LOGL_ERROR, "Failed to install CTRL commands.\n");
return -EFAULT;
}
rc = gprs_subscr_init(sgsn);
if (rc < 0) {
LOGP(DGPRS, LOGL_FATAL, "Cannot set up SGSN\n");
return rc;
}
return 0;
}

View File

@ -22,7 +22,7 @@
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/core/utils.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_subscriber.h>
#include <osmocom/sgsn/debug.h>

View File

@ -27,6 +27,9 @@
#include <osmocom/gsm/apn.h>
#include <osmocom/sgsn/vty.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/pdpctx.h>
#include <osmocom/sgsn/mmctx.h>
#include <gtp.h>
#include <pdp.h>
@ -38,10 +41,6 @@
#include <stdio.h>
#include <inttypes.h>
/* TODO...avoid going through a global */
extern struct sgsn_instance *sgsn;
extern struct ctrl_handle *g_ctrlh;
/**
* The CDR module will generate an entry like:
*
@ -64,7 +63,7 @@ extern struct ctrl_handle *g_ctrlh;
static void send_cdr_trap(char *value)
{
if (ctrl_cmd_send_trap(g_ctrlh, "cdr-v1", value) < 0)
if (ctrl_cmd_send_trap(sgsn->ctrlh, "cdr-v1", value) < 0)
LOGP(DGPRS, LOGL_ERROR, "Failed to create and send TRAP cdr-v1\n");
}
@ -299,3 +298,8 @@ int sgsn_cdr_init(struct sgsn_instance *sgsn)
return 0;
}
void sgsn_cdr_release(struct sgsn_instance *sgsn)
{
osmo_signal_unregister_handler(SS_SGSN, handle_sgsn_sig, sgsn);
}

View File

@ -21,20 +21,19 @@
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/pdpctx.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/debug.h>
#include <pdp.h>
extern vector ctrl_node_vec;
static int get_subscriber_list(struct ctrl_cmd *cmd, void *d)
{
struct sgsn_mm_ctx *mm;
cmd->reply = talloc_strdup(cmd, "");
llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
llist_for_each_entry(mm, &sgsn->mm_list, list) {
char *addr = NULL;
struct sgsn_pdp_ctx *pdp;

View File

@ -34,7 +34,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include "bscconfig.h"
#include "config.h"
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
@ -45,9 +45,9 @@
#include <osmocom/sgsn/signal.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_gb.h>
#include <osmocom/sgsn/gprs_ns.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_sm.h>
#include <osmocom/sgsn/gprs_subscriber.h>
@ -55,8 +55,11 @@
#include <osmocom/sgsn/gprs_ranap.h>
#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/gtp_mme.h>
#include <osmocom/sgsn/sgsn_rim.h>
#include <osmocom/sgsn/gprs_bssgp.h>
#include <osmocom/sgsn/pdpctx.h>
#include <gtp.h>
#include <pdp.h>
@ -414,7 +417,7 @@ static int create_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
}
/* Check for cause value if it was really successful */
if (cause != GTPCAUSE_ACC_REQ) {
if (!gtp_cause_successful(cause)) {
reject_cause = cause_map(gtp2sm_cause_map, cause,
GSM_CAUSE_ACT_REJ_GGSN);
goto reject;
@ -593,12 +596,12 @@ static int echo_conf(void *cbp, bool timeout)
}
/* Any message received by GGSN contains a recovery IE */
static int cb_recovery2(struct sockaddr_in *peer, struct pdp_t *pdp, uint8_t recovery)
static int cb_recovery3(struct gsn_t *gsn, struct sockaddr_in *peer, struct pdp_t *pdp, uint8_t recovery)
{
struct sgsn_ggsn_ctx *ggsn;
struct sgsn_pdp_ctx *pctx = NULL;
ggsn = sgsn_ggsn_ctx_by_addr(&peer->sin_addr);
ggsn = sgsn_ggsn_ctx_by_addr(sgsn, &peer->sin_addr);
if (!ggsn) {
LOGP(DGPRS, LOGL_NOTICE, "Received Recovery IE for unknown GGSN\n");
return -EINVAL;
@ -692,9 +695,46 @@ static int cb_gtp_ran_info_relay_ind(struct sockaddr_in *peer, union gtpie_membe
LOGMME(mme, DGTP, LOGL_INFO, "Rx GTP RAN Information Relay\n");
int rc;
unsigned int len = 0;
struct msgb *msg = msgb_alloc(4096, "gtpcv1_ran_info");
struct bssgp_ran_information_pdu pdu;
struct msgb *msg = bssgp_msgb_alloc();
uint8_t rim_ra_encoded[256];
unsigned int rim_ra_encoded_len = 0;
struct bssgp_rim_routing_info rim_ra;
unsigned int rim_ra_discr_encoded_len = 0;
uint8_t rim_ra_discr;
/* Read RIM Routing Address Discriminator (optional) */
rc = gtpie_gettlv(ie, GTPIE_RIM_RA_DISCR, 0, &rim_ra_discr_encoded_len, &rim_ra_discr,
sizeof(rim_ra_discr));
if (rc || rim_ra_discr_encoded_len <= 0) {
LOGMME(mme, DGTP, LOGL_NOTICE, "Rx GTP RAN Information Relay: No RIM Routing Address Discriminator IE found!\n");
/* It is not an error when the RIM ROUTING ADDRESS DISCRIMINATOR IE is missing. The RIM ROUTING ADDRESS
* DISCRIMINATOR IE is an optional IE. When it is missing, the RIM Routing Address shall be processed
* as an RNC address ("0001") See also: 3GPP TS 29.060 */
rim_ra_discr = BSSGP_RIM_ROUTING_INFO_UTRAN;
}
/* Read RIM Routing Address (optional) */
rc = gtpie_gettlv(ie, GTPIE_RIM_ROUT_ADDR, 0, &rim_ra_encoded_len, rim_ra_encoded, sizeof(rim_ra_encoded));
if (rc || rim_ra_encoded_len <= 0) {
LOGMME(mme, DGTP, LOGL_ERROR, "Rx GTP RAN Information Relay: No RIM Routing Address IE found!\n");
/* TODO: The (usually included) RIM ROUTING ADDRESS field is an optional field. However, we cannot
* proceed without a destination address. A possible way to fix this would be a default route that
* can be configured via the VTY. */
goto ret_error;
} else {
rc = bssgp_parse_rim_ra(&rim_ra, rim_ra_encoded, rim_ra_encoded_len, rim_ra_discr);
if (rc < 0) {
LOGMME(mme, DGTP, LOGL_ERROR,
"Rx GTP RAN Information Relay: Failed parsing RIM Routing Address/RIM Routing Address Discriminator IE!\n");
goto ret_error;
}
}
if (gtpie_gettlv(ie, GTPIE_RAN_T_CONTAIN, 0, &len, msgb_data(msg), 4096) || len <= 0) {
LOGMME(mme, DGTP, LOGL_ERROR, "Rx GTP RAN Information Relay: No Transparent Container IE found!\n");
@ -703,13 +743,8 @@ static int cb_gtp_ran_info_relay_ind(struct sockaddr_in *peer, union gtpie_membe
msgb_put(msg, len);
msgb_bssgph(msg) = msg->data;
msgb_nsei(msg) = 0;
if (bssgp_parse_rim_pdu(&pdu, msg) < 0) {
LOGMME(mme, DGTP, LOGL_ERROR, "Rx GTP RAN Information Relay: Failed parsing Transparent Container IE!\n");
goto ret_error;
}
msgb_free(msg);
return sgsn_rim_rx_from_gtp(&pdu, mme);
return sgsn_rim_rx_from_gtp(msg, &rim_ra);
ret_error:
msgb_free(msg);
@ -768,15 +803,24 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
msgb_free(msg);
return -1;
case ST_GMM_REGISTERED_NORMAL:
OSMO_ASSERT(mm->gb.mm_state_fsm->state != ST_MM_IDLE);
if (mm->gb.mm_state_fsm->state == ST_MM_STANDBY) {
switch (mm->gb.mm_state_fsm->state) {
case ST_MM_IDLE:
LOGP(DGPRS, LOGL_ERROR, "Dropping DL packet for MS in MM state %s\n",
osmo_fsm_inst_state_name(mm->gb.mm_state_fsm));
msgb_free(msg);
return -1;
case ST_MM_READY:
/* Go ahead */
break;
case ST_MM_STANDBY:
LOGMMCTXP(LOGL_INFO, mm, "Paging MS in GMM state %s, MM state %s\n",
osmo_fsm_inst_state_name(mm->gmm_fsm),
osmo_fsm_inst_state_name(mm->gb.mm_state_fsm));
gprs_gb_page_ps_ra(mm);
}
sgsn_bssgp_page_ps_ra(mm);
/* FIXME: queue the packet we received from GTP */
/* FIXME: queue the packet we received from GTP */
break;
}
break;
default:
LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state "
@ -793,12 +837,12 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
/* It is easier to have a global count */
pdp->cdr_bytes_out += len;
return sndcp_unitdata_req(msg, &mm->gb.llme->lle[pdp->sapi],
return sndcp_sn_unitdata_req(msg, &mm->gb.llme->lle[pdp->sapi],
pdp->nsapi, mm);
}
/* Called by SNDCP when it has received/re-assembled a N-PDU */
int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
int sgsn_gtp_data_req(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu)
{
struct sgsn_mm_ctx *mmctx;
@ -901,7 +945,7 @@ int sgsn_gtp_init(struct sgsn_instance *sgi)
/* Register callbackcs with libgtp */
gtp_set_cb_delete_context(gsn, cb_delete_context);
gtp_set_cb_conf(gsn, cb_conf);
gtp_set_cb_recovery2(gsn, cb_recovery2);
gtp_set_cb_recovery3(gsn, cb_recovery3);
gtp_set_cb_data_ind(gsn, cb_data_ind);
gtp_set_cb_unsup_ind(gsn, cb_unsup_ind);
gtp_set_cb_extheader_ind(gsn, cb_extheader_ind);

View File

@ -59,17 +59,18 @@
#include <osmocom/sgsn/vty.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/gprs_sndcp.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_ranap.h>
#include <osmocom/sgsn/gprs_gb.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/ports.h>
#include <osmocom/sgsn/gprs_ns.h>
#include <osmocom/sgsn/gprs_bssgp.h>
#include <osmocom/sgsn/gprs_subscriber.h>
#include <osmocom/sgsn/gtp.h>
#include <gtp.h>
#include <osmocom/sgsn/sgsn_rim.h>
#include "../../bscconfig.h"
#include "../../config.h"
#if BUILD_IU
#include <osmocom/sigtran/osmo_ss7.h>
@ -81,7 +82,6 @@
#include <getopt.h>
void *tall_sgsn_ctx;
struct ctrl_handle *g_ctrlh;
struct gprs_ns2_inst *sgsn_nsi;
static int daemonize = 0;
@ -97,34 +97,11 @@ const char *openbsc_copyright =
struct sgsn_instance *sgsn;
/* call-back function for the BSSGP protocol */
/* call-back function for the BSSGP protocol.
* Must be left here so that we can add a new one in tests/sgsn_test */
int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
{
struct osmo_bssgp_prim *bp;
bp = container_of(oph, struct osmo_bssgp_prim, oph);
switch (oph->sap) {
case SAP_BSSGP_LL:
switch (oph->primitive) {
case PRIM_BSSGP_UL_UD:
return gprs_llc_rcvmsg(oph->msg, bp->tp);
}
break;
case SAP_BSSGP_GMM:
switch (oph->primitive) {
case PRIM_BSSGP_GMM_SUSPEND:
return gprs_gmm_rx_suspend(bp->ra_id, bp->tlli);
case PRIM_BSSGP_GMM_RESUME:
return gprs_gmm_rx_resume(bp->ra_id, bp->tlli,
bp->u.resume.suspend_ref);
}
break;
case SAP_BSSGP_NM:
break;
case SAP_BSSGP_RIM:
return sgsn_rim_rx_from_gb(bp, oph->msg);
}
return 0;
return sgsn_bssgp_rx_prim(oph);
}
static void signal_handler(int signum)
@ -434,19 +411,12 @@ int main(int argc, char **argv)
exit(1);
}
sgsn->cfg.nsi = sgsn_nsi;
bssgp_set_bssgp_callback(gprs_gb_send_cb, sgsn_nsi);
gprs_llc_init("/usr/local/lib/osmocom/crypt/");
sgsn_rate_ctr_init();
sgsn_inst_init(sgsn);
bssgp_set_bssgp_callback(sgsn_bssgp_dispatch_ns_unitdata_req_cb, sgsn_nsi);
gprs_ns2_vty_init(sgsn_nsi);
bssgp_vty_init();
gprs_llc_vty_init();
gprs_sndcp_vty_init();
sgsn_auth_init(sgsn);
sgsn_cdr_init(sgsn);
handle_options(argc, argv);
@ -472,25 +442,11 @@ int main(int argc, char **argv)
}
/* start telnet after reading config for vty_get_bind_addr() */
rc = telnet_init_dynif(tall_sgsn_ctx, NULL,
vty_get_bind_addr(), OSMO_VTY_PORT_SGSN);
rc = telnet_init_default(tall_sgsn_ctx, NULL, OSMO_VTY_PORT_SGSN);
if (rc < 0)
exit(1);
/* start control interface after reading config for
* ctrl_vty_get_bind_addr() */
g_ctrlh = ctrl_interface_setup_dynip(NULL, ctrl_vty_get_bind_addr(),
OSMO_CTRL_PORT_SGSN, NULL);
if (!g_ctrlh) {
LOGP(DGPRS, LOGL_ERROR, "Failed to create CTRL interface.\n");
exit(1);
}
if (sgsn_ctrl_cmds_install() != 0) {
LOGP(DGPRS, LOGL_ERROR, "Failed to install CTRL commands.\n");
exit(1);
}
gprs_llc_init(sgsn->cfg.crypt_cipher_plugin_path);
rc = sgsn_gtp_init(sgsn);
if (rc) {
@ -499,9 +455,9 @@ int main(int argc, char **argv)
} else
LOGP(DGPRS, LOGL_NOTICE, "libGTP v%s initialized\n", gtp_version());
rc = gprs_subscr_init(sgsn);
rc = sgsn_inst_init(sgsn);
if (rc < 0) {
LOGP(DGPRS, LOGL_FATAL, "Cannot set up subscriber management\n");
LOGP(DGPRS, LOGL_FATAL, "Cannot set up SGSN\n");
exit(2);
}

View File

@ -12,6 +12,7 @@
#include <osmocom/gprs/gprs_bssgp_rim.h>
#include <osmocom/sgsn/sgsn_rim.h>
#include <osmocom/sgsn/gtp_mme.h>
#include <osmocom/sgsn/gtp.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/sgsn.h>
@ -20,6 +21,7 @@ static int sgsn_bssgp_fwd_rim_to_geran(const struct bssgp_ran_information_pdu *p
struct bssgp_bvc_ctx *bvc_ctx;
OSMO_ASSERT(pdu->routing_info_dest.discr == BSSGP_RIM_ROUTING_INFO_GERAN);
/* Resolve RIM ROUTING ADDRESS to a BVC context */
bvc_ctx = btsctx_by_raid_cid(&pdu->routing_info_dest.geran.raid, pdu->routing_info_dest.geran.cid);
if (!bvc_ctx) {
LOGP(DRIM, LOGL_ERROR, "Unable to find NSEI for destination cell %s\n",
@ -27,10 +29,27 @@ static int sgsn_bssgp_fwd_rim_to_geran(const struct bssgp_ran_information_pdu *p
return -EINVAL;
}
/* Forward PDU as it is to the correct interface */
/* Forward PDU to the NSEI of the resolved BVC context */
return bssgp_tx_rim(pdu, bvc_ctx->nsei);
}
static int sgsn_bssgp_fwd_rim_to_geran_encoded(struct msgb *msg, struct bssgp_rim_routing_info *rim_routing_address)
{
struct bssgp_bvc_ctx *bvc_ctx;
OSMO_ASSERT(rim_routing_address->discr == BSSGP_RIM_ROUTING_INFO_GERAN);
/* Resolve RIM ROUTING ADDRESS to a BVC context */
bvc_ctx = btsctx_by_raid_cid(&rim_routing_address->geran.raid, rim_routing_address->geran.cid);
if (!bvc_ctx) {
LOGP(DRIM, LOGL_ERROR, "Unable to find NSEI for destination cell %s\n",
bssgp_rim_ri_name(rim_routing_address));
return -EINVAL;
}
/* Forward PDU to the NSEI of the resolved BVC context */
return bssgp_tx_rim_encoded(msg, bvc_ctx->nsei);
}
static int sgsn_bssgp_fwd_rim_to_eutran(const struct bssgp_ran_information_pdu *pdu)
{
struct sgsn_mme_ctx *mme;
@ -88,36 +107,21 @@ err:
return -1;
}
/* Receive a RIM PDU from GTPvC1 (EUTRAN) */
int sgsn_rim_rx_from_gtp(struct bssgp_ran_information_pdu *pdu, struct sgsn_mme_ctx *mme)
/* Receive a RIM PDU from GTPv1C (EUTRAN) */
int sgsn_rim_rx_from_gtp(struct msgb *msg, struct bssgp_rim_routing_info *rim_routing_address)
{
struct sgsn_mme_ctx *mme_tmp;
if (pdu->routing_info_src.discr != BSSGP_RIM_ROUTING_INFO_EUTRAN) {
LOGMME(mme, DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: Expected src %s, got %s\n",
bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_EUTRAN),
bssgp_rim_routing_info_discr_str(pdu->routing_info_src.discr));
/* TODO: In this code path, we currently only support RIM message forwarding to GERAN (BSSGP). However, it
* technically also be possible to route a message back to GTP (BSSGP_RIM_ROUTING_INFO_EUTRAN) or to
* IuPS (BSSGP_RIM_ROUTING_INFO_UTRAN) */
if (rim_routing_address->discr != BSSGP_RIM_ROUTING_INFO_GERAN) {
LOGP(DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: Expected dst %s, got %s\n",
bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_GERAN),
bssgp_rim_routing_info_discr_str(rim_routing_address->discr));
return -EINVAL;
}
if (pdu->routing_info_dest.discr != BSSGP_RIM_ROUTING_INFO_GERAN) {
LOGMME(mme, DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: Expected dst %s, got %s\n",
bssgp_rim_routing_info_discr_str(BSSGP_RIM_ROUTING_INFO_GERAN),
bssgp_rim_routing_info_discr_str(pdu->routing_info_dest.discr));
return -EINVAL;
}
LOGP(DRIM, LOGL_INFO, "Rx GTP RAN Information Relay for dest cell %s\n",
bssgp_rim_ri_name(rim_routing_address));
mme_tmp = sgsn_mme_ctx_by_route(sgsn, &pdu->routing_info_src.eutran.tai);
if (!mme_tmp)/* See if we have a default route configured */
mme_tmp = sgsn_mme_ctx_by_default_route(sgsn);
if (mme != mme_tmp) {
LOGP(DRIM, LOGL_ERROR, "Rx GTP RAN Information Relay: "
"Source MME doesn't have RIM routing configured for TAI: %s\n",
bssgp_rim_ri_name(&pdu->routing_info_src));
return -EINVAL;
}
LOGMME(mme, DRIM, LOGL_INFO, "Rx GTP RAN Information Relay for dest cell %s\n",
bssgp_rim_ri_name(&pdu->routing_info_dest));
return sgsn_bssgp_fwd_rim_to_geran(pdu);
return sgsn_bssgp_fwd_rim_to_geran_encoded(msg, rim_routing_address);
}

View File

@ -35,11 +35,14 @@
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/sgsn/gprs_gb.h>
#include <osmocom/sgsn/gprs_ns.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/gprs_sgsn.h>
#include <osmocom/sgsn/gprs_bssgp.h>
#include <osmocom/sgsn/mmctx.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <osmocom/sgsn/gtp_mme.h>
#include <osmocom/sgsn/vty.h>
#include <osmocom/sgsn/pdpctx.h>
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/vty/tdef_vty.h>
@ -55,14 +58,12 @@
#include <pdp.h>
#include <gtp.h>
#include "../../bscconfig.h"
#include "../../config.h"
#ifdef BUILD_IU
#include <osmocom/ranap/iu_client.h>
#endif
extern void *tall_sgsn_ctx;
static struct sgsn_config *g_cfg = NULL;
const struct value_string sgsn_auth_pol_strs[] = {
@ -97,7 +98,7 @@ const struct value_string sgsn_auth_pol_strs[] = {
#define NONSPEC_X1001_SECS 5 /* wait for a RANAP Release Complete */
static struct osmo_tdef sgsn_T_defs[] = {
struct osmo_tdef sgsn_T_defs[] = {
{ .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },
{ .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },
{ .T=3314, .default_val=GSM0408_T3314_SECS, .desc="READY timer. Force to STANDBY on expiry timer (s)" },
@ -136,6 +137,26 @@ DEFUN(cfg_sgsn_timer, cfg_sgsn_timer_cmd,
return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs, argv);
}
DEFUN(show_timer_gtp, show_timer_gtp_cmd,
"show timer gtp " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
SHOW_STR "Show timers\n" "GTP (libgtp) timers\n"
OSMO_TDEF_VTY_DOC_T)
{
const char *T_arg = argc > 0 ? argv[0] : NULL;
return osmo_tdef_vty_show_cmd(vty, g_cfg->T_defs_gtp, T_arg, NULL);
}
DEFUN(cfg_sgsn_timer_gtp, cfg_sgsn_timer_gtp_cmd,
"timer gtp " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
"Configure or show timers\n" "GTP (libgtp) timers\n"
OSMO_TDEF_VTY_DOC_SET)
{
/* If any arguments are missing, redirect to 'show' */
if (argc < 2)
return show_timer(self, vty, argc, argv);
return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs_gtp, argv);
}
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6)
{
static char str[INET6_ADDRSTRLEN + 10];
@ -230,7 +251,7 @@ static int config_write_sgsn(struct vty *vty)
vty_out(vty, " gtp local-ip %s%s",
inet_ntoa(g_cfg->gtp_listenaddr.sin_addr), VTY_NEWLINE);
llist_for_each_entry(gctx, &sgsn_ggsn_ctxts, list) {
llist_for_each_entry(gctx, &sgsn->ggsn_list, list) {
if (gctx->id == UINT32_MAX)
continue;
@ -261,6 +282,17 @@ static int config_write_sgsn(struct vty *vty)
vty_out(vty, "%s", VTY_NEWLINE);
}
if (g_cfg->uea_encryption_mask != 0) {
vty_out(vty, " encryption uea");
for (i = 0; i < _OSMO_UTRAN_UEA_NUM; i++)
if (g_cfg->uea_encryption_mask >> i & 1)
vty_out(vty, " %u", i);
vty_out(vty, "%s", VTY_NEWLINE);
}
if (g_cfg->crypt_cipher_plugin_path)
vty_out(vty, " encryption cipher-plugin-path %s%s", g_cfg->crypt_cipher_plugin_path, VTY_NEWLINE);
if (g_cfg->sgsn_ipa_name)
vty_out(vty, " gsup ipa-name %s%s", g_cfg->sgsn_ipa_name, VTY_NEWLINE);
if (g_cfg->gsup_server_addr.sin_addr.s_addr)
@ -289,9 +321,9 @@ static int config_write_sgsn(struct vty *vty)
llist_for_each_entry(acl, &g_cfg->imsi_acl, list)
vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE);
if (llist_empty(&sgsn_apn_ctxts))
if (llist_empty(&sgsn->apn_list))
vty_out(vty, " ! apn * ggsn 0%s", VTY_NEWLINE);
llist_for_each_entry(actx, &sgsn_apn_ctxts, list) {
llist_for_each_entry(actx, &sgsn->apn_list, list) {
if (strlen(actx->imsi_prefix) > 0)
vty_out(vty, " apn %s imsi-prefix %s ggsn %u%s",
actx->name, actx->imsi_prefix, actx->ggsn->id,
@ -312,6 +344,7 @@ static int config_write_sgsn(struct vty *vty)
vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
osmo_tdef_vty_write(vty, g_cfg->T_defs_gtp, " timer gtp ");
if (g_cfg->pcomp_rfc1144.active) {
vty_out(vty, " compression rfc1144 active slots %d%s",
@ -399,7 +432,7 @@ DEFUN(cfg_ggsn_remote_ip, cfg_ggsn_remote_ip_cmd,
"IPv4 Address\n")
{
uint32_t id = atoi(argv[0]);
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(sgsn, id);
inet_aton(argv[1], &ggc->remote_addr);
@ -424,7 +457,7 @@ DEFUN(cfg_ggsn_gtp_version, cfg_ggsn_gtp_version_cmd,
"Version 0\n" "Version 1\n")
{
uint32_t id = atoi(argv[0]);
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(sgsn, id);
if (atoi(argv[1]))
ggc->gtp_version = 1;
@ -442,7 +475,7 @@ DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
"Interval between echo requests in seconds.\n")
{
uint32_t id = atoi(argv[0]);
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(sgsn, id);
ggc->echo_interval = atoi(argv[1]);
@ -461,7 +494,7 @@ DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
NO_STR "Send an echo request to this static GGSN every interval.\n")
{
uint32_t id = atoi(argv[0]);
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(sgsn, id);
ggc->echo_interval = 0;
sgsn_ggsn_ctx_check_echo_timer(ggc);
@ -502,7 +535,7 @@ static int add_apn_ggsn_mapping(struct vty *vty, const char *apn_str,
struct apn_ctx *actx;
struct sgsn_ggsn_ctx *ggsn;
ggsn = sgsn_ggsn_ctx_by_id(ggsn_id);
ggsn = sgsn_ggsn_ctx_by_id(sgsn, ggsn_id);
if (ggsn == NULL) {
vty_out(vty, "%% a GGSN with id %d has not been defined%s",
ggsn_id, VTY_NEWLINE);
@ -689,7 +722,7 @@ DEFUN(swow_mmctx_all, show_mmctx_all_cmd,
SHOW_STR MMCTX_STR "All MM Contexts\n" INCLUDE_PDP_STR)
{
struct sgsn_mm_ctx *mm;
llist_for_each_entry(mm, &sgsn_mm_ctxts, list)
llist_for_each_entry(mm, &sgsn->mm_list, list)
vty_dump_mmctx(vty, "", mm, (argc > 0) ? 1 : 0);
return CMD_SUCCESS;
@ -701,7 +734,7 @@ DEFUN(show_pdpctx_all, show_pdpctx_all_cmd,
{
struct sgsn_pdp_ctx *pdp;
llist_for_each_entry(pdp, &sgsn_pdp_ctxts, g_list)
llist_for_each_entry(pdp, &sgsn->pdp_list, g_list)
vty_dump_pdp(vty, "", pdp);
return CMD_SUCCESS;
@ -817,6 +850,27 @@ DEFUN(cfg_encrypt2, cfg_encrypt2_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_encrypt_cipher_plugin_path, cfg_encrypt_cipher_plugin_path_cmd,
"encryption cipher-plugin-path PATH",
ENCRYPTION_STR
"Path to gprs encryption cipher plugin directory\n"
"Plugin path\n")
{
osmo_talloc_replace_string(sgsn, &sgsn->cfg.crypt_cipher_plugin_path, argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_no_encrypt_cipher_plugin_path, cfg_no_encrypt_cipher_plugin_path_cmd,
"no encryption cipher-plugin-path PATH",
NO_STR ENCRYPTION_STR
"Path to gprs encryption cipher plugin directory\n"
"Plugin path\n")
{
TALLOC_FREE(sgsn->cfg.crypt_cipher_plugin_path);
return CMD_SUCCESS;
}
DEFUN(cfg_authentication, cfg_authentication_cmd,
"authentication (optional|required)",
"Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
@ -936,8 +990,17 @@ static void subscr_dump_full_vty(struct vty *vty, struct gprs_subscr *gsub, int
}
llist_for_each_entry(pdp, &gsub->sgsn_data->pdp_list, list) {
vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'",
pdp->context_id, pdp->pdp_type, pdp->apn_str);
char ip_str[INET6_ADDRSTRLEN] = { 0 };
vty_out(vty, " PDP info: Id: %d, Addr(Org: 0x%02x Type: 0x%02x",
pdp->context_id, pdp->pdp_type_org, pdp->pdp_type_nr);
if (pdp->pdp_address[0].u.sa.sa_family != AF_UNSPEC)
vty_out(vty, " Addr[0]: %s", osmo_sockaddr_ntop(&pdp->pdp_address[0].u.sa, ip_str));
if (pdp->pdp_address[0].u.sa.sa_family != AF_UNSPEC)
vty_out(vty, " Addr[1]: %s", osmo_sockaddr_ntop(&pdp->pdp_address[1].u.sa, ip_str));
vty_out(vty, ") APN: '%s'", pdp->apn_str);
if (pdp->qos_subscribed_len)
vty_out(vty, " QoS: %s", osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len));
@ -984,7 +1047,7 @@ DEFUN_HIDDEN(reset_sgsn_state,
struct gprs_subscr *subscr, *tmp_subscr;
struct sgsn_mm_ctx *mm, *tmp_mm;
llist_for_each_entry_safe(mm, tmp_mm, &sgsn_mm_ctxts, list)
llist_for_each_entry_safe(mm, tmp_mm, &sgsn->mm_list, list)
{
gsm0408_gprs_access_cancelled(mm, SGSN_ERROR_CAUSE_NONE);
}
@ -1263,7 +1326,7 @@ DEFUN(page_subscr, page_subscr_info_cmd,
return CMD_WARNING;
}
gprs_gb_page_ps_ra(mm);
sgsn_bssgp_page_ps_ra(mm);
return CMD_SUCCESS;
}
@ -1716,9 +1779,6 @@ int sgsn_vty_init(struct sgsn_config *cfg)
{
g_cfg = cfg;
g_cfg->T_defs = sgsn_T_defs;
osmo_tdefs_reset(g_cfg->T_defs);
install_element_ve(&show_sgsn_cmd);
//install_element_ve(&show_mmctx_tlli_cmd);
install_element_ve(&show_mmctx_imsi_cmd);
@ -1726,6 +1786,7 @@ int sgsn_vty_init(struct sgsn_config *cfg)
install_element_ve(&show_pdpctx_all_cmd);
install_element_ve(&show_subscr_cache_cmd);
install_element_ve(&show_timer_cmd);
install_element_ve(&show_timer_gtp_cmd);
install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
install_element(ENABLE_NODE, &update_subscr_create_cmd);
@ -1753,6 +1814,8 @@ int sgsn_vty_init(struct sgsn_config *cfg)
install_element(SGSN_NODE, &cfg_encrypt2_cmd);
install_element(SGSN_NODE, &cfg_encrypt_cmd);
install_element(SGSN_NODE, &cfg_encryption_uea_cmd);
install_element(SGSN_NODE, &cfg_encrypt_cipher_plugin_path_cmd);
install_element(SGSN_NODE, &cfg_no_encrypt_cipher_plugin_path_cmd);
install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
@ -1773,6 +1836,7 @@ int sgsn_vty_init(struct sgsn_config *cfg)
install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
install_element(SGSN_NODE, &cfg_sgsn_timer_gtp_cmd);
install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
@ -1804,9 +1868,6 @@ int sgsn_parse_config(const char *config_file)
/* make sure sgsn_vty_init() was called before this */
OSMO_ASSERT(g_cfg);
g_cfg->gea_encryption_mask = 0x1; /* support GEA0 by default unless specific encryption config exists */
g_cfg->uea_encryption_mask = (1 << OSMO_UTRAN_UEA0); /* support UEA0 by default unless specific encryption config exists */
rc = vty_read_config_file(config_file, NULL);
if (rc < 0) {
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);

View File

@ -42,15 +42,15 @@ DISTCLEANFILES = \
$(NULL)
if ENABLE_EXT_TESTS
python-tests: $(BUILT_SOURCES)
python-tests:
$(MAKE) vty-test
$(MAKE) ctrl-python-test
else
python-tests: $(BUILT_SOURCES)
python-tests:
echo "Not running python-based tests (determined at configure-time)"
endif
vty-python-test: $(BUILT_SOURCES)
vty-python-test: $(top_builddir)/src/sgsn/osmo-sgsn
osmotestvty.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
$(srcdir)/vty_test_runner.py -w $(abs_top_builddir) -v
@ -59,7 +59,7 @@ vty-python-test: $(BUILT_SOURCES)
# To update the VTY script from current application behavior,
# pass -u to vty_script_runner.py by doing:
# make vty-transcript-test U=-u
vty-transcript-test:
vty-transcript-test: $(top_builddir)/src/sgsn/osmo-sgsn
osmo_verify_transcript_vty.py -v \
-n OsmoSGSN -p 4245 \
-r "$(top_builddir)/src/sgsn/osmo-sgsn -c $(top_srcdir)/doc/examples/osmo-sgsn/osmo-sgsn.cfg" \
@ -71,7 +71,7 @@ vty-test:
$(MAKE) vty-python-test
$(MAKE) vty-transcript-test
ctrl-python-test: $(BUILT_SOURCES)
ctrl-python-test: $(top_builddir)/src/sgsn/osmo-sgsn
$(srcdir)/ctrl_test_runner.py -w $(abs_top_builddir) -v
rm -f $(top_builddir)/gsn_restart $(top_builddir)/gtphub_restart_count

View File

@ -1,5 +1,6 @@
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOABIS_CFLAGS)
AM_LDFLAGS = -no-install
EXTRA_DIST = gprs_test.ok

View File

@ -24,7 +24,7 @@ static int nu_is_retransmission(uint16_t nu, uint16_t vur)
return ret;
}
static void test_8_4_2()
static void test_8_4_2(void)
{
printf("Testing gprs_llc_is_retransmit.\n");
@ -48,6 +48,22 @@ static void test_8_4_2()
ASSERT_FALSE(nu_is_retransmission(479, 511)); // wrapped
}
/* GSM 04.08, 10.5.7.3 GPRS Timer */
static int gprs_tmr_to_secs(uint8_t tmr)
{
switch (tmr & GPRS_TMR_UNIT_MASK) {
case GPRS_TMR_2SECONDS:
return 2 * (tmr & GPRS_TMR_FACT_MASK);
default:
case GPRS_TMR_MINUTE:
return 60 * (tmr & GPRS_TMR_FACT_MASK);
case GPRS_TMR_6MINUTE:
return 360 * (tmr & GPRS_TMR_FACT_MASK);
case GPRS_TMR_DEACTIVATED:
return -1;
}
}
static void test_gprs_timer_enc_dec(void)
{
int i, u, secs, tmr;

View File

@ -12,6 +12,8 @@ AM_CFLAGS = \
$(LIBGTP_CFLAGS) \
$(NULL)
AM_LDFLAGS = -no-install
EXTRA_DIST = \
gtphub_test.ok \
$(NULL)
@ -28,6 +30,7 @@ gtphub_test_LDFLAGS = \
-Wl,--wrap=gtphub_resolve_ggsn_addr \
-Wl,--wrap=gtphub_ares_init \
-Wl,--wrap=gtphub_write \
$(AM_LDFLAGS) \
$(NULL)
gtphub_test_LDADD = \

View File

@ -27,10 +27,11 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/application.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gtphub.h>
#include <osmocom/gtphub/gtphub.h>
#include <gtp.h>
#include <gtpie.h>
@ -376,7 +377,7 @@ static void test_expiry(void)
}
char resolve_ggsn_got_imsi[GSM23003_IMSI_MAX_DIGITS+1];
char resolve_ggsn_got_ni[GSM_APN_LENGTH];
char resolve_ggsn_got_ni[APN_MAXLEN+1];
struct sgsn_sockaddr resolved_ggsn_addr;
static int resolve_to_ggsn(const char *addr, uint16_t port)
@ -577,7 +578,7 @@ time_t now;
static struct gtphub _hub;
static struct gtphub *hub = &_hub;
static int setup_test_hub()
static int setup_test_hub(void)
{
/* Not really needed, but to make 100% sure... */
ZERO_STRUCT(hub);
@ -613,7 +614,7 @@ static int setup_test_hub()
return 1;
}
static int clear_test_hub()
static int clear_test_hub(void)
{
/* expire all */
gtphub_gc(hub, now + (60 * GTPH_EXPIRE_SLOWLY_MINUTES) + 1);
@ -817,7 +818,7 @@ static void test_echo(void)
"87" /* 135: Quality of Service (QoS) Profile */ \
"0004" /* length */ \
"00" /* priority */ \
"0b921f" /* QoS profile data */
"0b921f" /* QoS profile data */
#define MSG_PDP_CTX_RSP(len, tei_h, seq, restart, tei_u, tei_c, gsn_c, gsn_u) \
"32" \
@ -898,7 +899,7 @@ static int msg_from_ggsn(int plane_idx,
return 1;
}
static int create_pdp_ctx()
static int create_pdp_ctx(void)
{
const char *gtp_req_from_sgsn =
MSG_PDP_CTX_REQ("0068",

View File

@ -37,6 +37,8 @@ OsmoSGSN(config-sgsn)# list
authentication (optional|required)
encryption gea <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>]
encryption uea <0-2> [<0-2>] [<0-2>]
encryption cipher-plugin-path PATH
no encryption cipher-plugin-path PATH
gsup ipa-name NAME
gsup remote-ip A.B.C.D
gsup remote-port <0-65535>
@ -55,6 +57,7 @@ OsmoSGSN(config-sgsn)# list
ggsn dynamic
grx-dns-add A.B.C.D
timer [TNNNN] [(<0-2147483647>|default)]
timer gtp [TNNNN] [(<0-2147483647>|default)]
no compression rfc1144
compression rfc1144 active slots <1-256>
compression rfc1144 passive
@ -117,3 +120,14 @@ sgsn
gtp remote-ip 5.6.7.8
...
OsmoSGSN(config-sgsn)# no mme test1
OsmoSGSN(config-sgsn)# encryption gea 0 3
OsmoSGSN(config-sgsn)# encryption uea 1 2
OsmoSGSN(config-sgsn)# encryption cipher-plugin-path /foo/bar
OsmoSGSN(config-sgsn)# show running-config
...
sgsn
...
encryption gea 0 3
encryption uea 1 2
encryption cipher-plugin-path /foo/bar
...

View File

@ -7,6 +7,7 @@ AM_CFLAGS = \
-Wall \
-ggdb3 \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOCTRL_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \
$(LIBOSMOGSUPCLIENT_CFLAGS) \
@ -21,6 +22,8 @@ AM_CFLAGS += \
$(NULL)
endif
AM_LDFLAGS = -no-install
EXTRA_DIST = \
sgsn_test.ok \
$(NULL)
@ -29,8 +32,13 @@ check_PROGRAMS = \
sgsn_test \
$(NULL)
noinst_HEADERS = \
gprs_gb_parse.h \
$(NULL)
sgsn_test_SOURCES = \
sgsn_test.c \
gprs_gb_parse.c \
$(NULL)
sgsn_test_LDFLAGS = \
@ -39,18 +47,26 @@ sgsn_test_LDFLAGS = \
-Wl,--wrap=gprs_subscr_request_update_location \
-Wl,--wrap=gprs_subscr_request_auth_info \
-Wl,--wrap=osmo_gsup_client_send \
$(AM_LDFLAGS) \
$(NULL)
sgsn_test_LDADD = \
$(top_builddir)/src/sgsn/apn.o \
$(top_builddir)/src/sgsn/gprs_bssgp.o \
$(top_builddir)/src/sgsn/gprs_llc.o \
$(top_builddir)/src/sgsn/gprs_gb.o \
$(top_builddir)/src/sgsn/gprs_ns.o \
$(top_builddir)/src/sgsn/gprs_sndcp.o \
$(top_builddir)/src/sgsn/gprs_gmm_attach.o \
$(top_builddir)/src/sgsn/gprs_gmm.o \
$(top_builddir)/src/sgsn/gprs_gmm_fsm.o \
$(top_builddir)/src/sgsn/gprs_mm_state_gb_fsm.o \
$(top_builddir)/src/sgsn/gprs_sgsn.o \
$(top_builddir)/src/sgsn/gtp_ggsn.o \
$(top_builddir)/src/sgsn/gtp_mme.o \
$(top_builddir)/src/sgsn/mmctx.o \
$(top_builddir)/src/sgsn/pdpctx.o \
$(top_builddir)/src/sgsn/sgsn.o \
$(top_builddir)/src/sgsn/sgsn_cdr.o \
$(top_builddir)/src/sgsn/sgsn_ctrl.o \
$(top_builddir)/src/sgsn/sgsn_vty.o \
$(top_builddir)/src/sgsn/sgsn_libgtp.o \
$(top_builddir)/src/sgsn/sgsn_auth.o \
@ -66,11 +82,11 @@ sgsn_test_LDADD = \
$(top_builddir)/src/sgsn/sgsn_rim.o \
$(top_builddir)/src/gprs/gprs_utils.o \
$(top_builddir)/src/gprs/gprs_llc_parse.o \
$(top_builddir)/src/gprs/gprs_gb_parse.o \
$(top_builddir)/src/gprs/crc24.o \
$(top_builddir)/src/gprs/sgsn_ares.o \
$(LIBOSMOABIS_LIBS) \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOCTRL_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(LIBOSMOGB_LIBS) \
$(LIBOSMOGSUPCLIENT_LIBS) \

View File

@ -18,10 +18,12 @@
*
*/
#include <arpa/inet.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/sgsn/gprs_gb_parse.h>
#include "gprs_gb_parse.h"
#include <osmocom/sgsn/gprs_utils.h>

View File

@ -19,44 +19,38 @@
*
*/
#include <osmocom/core/application.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/apn.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/vty/vty.h>
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/sgsn/gprs_llc.h>
#include <osmocom/sgsn/sgsn.h>
#include <osmocom/sgsn/gprs_gmm.h>
#include <osmocom/sgsn/debug.h>
#include <osmocom/sgsn/gprs_subscriber.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/gprs_gb_parse.h>
#include <osmocom/sgsn/gprs_gmm_fsm.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/core/application.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/utils.h>
#include <osmocom/vty/vty.h>
#include <osmocom/sgsn/gtp_ggsn.h>
#include <stdio.h>
#include "gprs_gb_parse.h"
void *tall_sgsn_ctx;
static struct sgsn_instance sgsn_inst = {
.config_file = "osmo_sgsn.cfg",
.cfg = {
.gtp_statedir = "./",
.auth_policy = SGSN_AUTH_POLICY_CLOSED,
.gea_encryption_mask = 0x1,
},
};
struct sgsn_instance *sgsn = &sgsn_inst;
struct sgsn_instance *sgsn;
unsigned sgsn_tx_counter = 0;
struct msgb *last_msg = NULL;
struct gprs_gb_parse_context last_dl_parse_ctx;
static void reset_last_msg()
static void reset_last_msg(void)
{
if (last_msg)
msgb_free(last_msg);
@ -65,9 +59,10 @@ static void reset_last_msg()
memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx));
}
static void cleanup_test()
static void cleanup_test(void)
{
reset_last_msg();
TALLOC_FREE(sgsn);
}
static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx)
@ -282,7 +277,7 @@ static void show_subscrs(FILE *out)
}
}
static void assert_no_subscrs()
static void assert_no_subscrs(void)
{
show_subscrs(stdout);
fflush(stdout);
@ -384,6 +379,7 @@ static void test_auth_triplets(void)
uint32_t local_tlli = 0xffeeddcc;
printf("Testing authentication triplet handling\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* Check for emptiness */
OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
@ -572,6 +568,7 @@ static void test_subscriber_gsup(void)
printf("Testing subscriber GSUP handling\n");
update_subscriber_data_cb = my_dummy_sgsn_update_subscriber_data;
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* Check for emptiness */
OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
@ -748,6 +745,7 @@ static void test_gmm_detach(void)
uint32_t local_tlli;
printf("Testing GMM detach\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* DTAP - Detach Request (MO) */
/* normal detach, power_off = 0 */
@ -789,6 +787,7 @@ static void test_gmm_detach_power_off(void)
uint32_t local_tlli;
printf("Testing GMM detach (power off)\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* DTAP - Detach Request (MO) */
/* normal detach, power_off = 1 */
@ -829,6 +828,7 @@ static void test_gmm_detach_no_mmctx(void)
uint32_t local_tlli;
printf("Testing GMM detach (no MMCTX)\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* DTAP - Detach Request (MO) */
/* normal detach, power_off = 0 */
@ -865,6 +865,7 @@ static void test_gmm_detach_accept_unexpected(void)
uint32_t local_tlli;
printf("Testing GMM detach accept (unexpected)\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* DTAP - Detach Accept (MT) */
/* normal detach */
@ -901,6 +902,7 @@ static void test_gmm_status_no_mmctx(void)
uint32_t local_tlli;
printf("Testing GMM Status (no MMCTX)\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* DTAP - GMM Status, protocol error */
static const unsigned char gmm_status[] = {
@ -1195,6 +1197,7 @@ static void test_gmm_reject(void)
};
printf("Testing GMM reject\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* reset the PRNG used by sgsn_alloc_ptmsi */
srand(1);
@ -1241,6 +1244,9 @@ static void test_gmm_cancel(void)
uint32_t foreign_tlli;
uint32_t local_tlli = 0;
struct gprs_llc_lle *lle;
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
sgsn->cfg.gea_encryption_mask = 0x1;
const enum sgsn_auth_policy saved_auth_policy = sgsn->cfg.auth_policy;
/* DTAP - Attach Request */
@ -1271,8 +1277,7 @@ static void test_gmm_cancel(void)
};
printf("Testing cancellation\n");
sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
sgsn->cfg.auth_policy = SGSN_AUTH_POLICY_OPEN;
foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN);
@ -1344,6 +1349,7 @@ static void test_apn_matching(void)
struct apn_ctx *actx, *actxs[9];
printf("Testing APN matching\n");
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
actxs[0] = sgsn_apn_ctx_find_alloc("*.test", "");
actxs[1] = sgsn_apn_ctx_find_alloc("*.def.test", "");
@ -1433,9 +1439,6 @@ static void test_apn_matching(void)
cleanup_test();
}
struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc(
struct sgsn_subscriber_data *sdata);
static void test_ggsn_selection(void)
{
struct apn_ctx *actxs[4];
@ -1454,6 +1457,7 @@ static void test_ggsn_selection(void)
printf("Testing GGSN selection\n");
osmo_gsup_client_send_cb = my_gsup_client_send_dummy;
sgsn = sgsn_instance_alloc(tall_sgsn_ctx);
/* Check for emptiness */
OSMO_ASSERT(gprs_subscr_get_by_imsi(imsi1) == NULL);
@ -1472,9 +1476,9 @@ static void test_ggsn_selection(void)
/* TODO: Add PDP info entries to s1 */
ggcs[0] = sgsn_ggsn_ctx_find_alloc(0);
ggcs[1] = sgsn_ggsn_ctx_find_alloc(1);
ggcs[2] = sgsn_ggsn_ctx_find_alloc(2);
ggcs[0] = sgsn_ggsn_ctx_find_alloc(sgsn, 0);
ggcs[1] = sgsn_ggsn_ctx_find_alloc(sgsn, 1);
ggcs[2] = sgsn_ggsn_ctx_find_alloc(sgsn, 2);
actxs[0] = sgsn_apn_ctx_find_alloc("test.apn", "123456");
actxs[0]->ggsn = ggcs[0];
@ -1485,13 +1489,14 @@ static void test_ggsn_selection(void)
pdp_data = sgsn_subscriber_pdp_data_alloc(s1->sgsn_data);
pdp_data->context_id = 1;
pdp_data->pdp_type = 0x0121;
pdp_data->pdp_type_org = PDP_TYPE_ORG_IETF;
pdp_data->pdp_type_nr = PDP_TYPE_N_IETF_IPv4;
osmo_strlcpy(pdp_data->apn_str, "*", sizeof(pdp_data->apn_str));
/* Resolve GGSNs */
tp.lv[GSM48_IE_GSM_APN].len =
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
OSMO_ASSERT(ggc != NULL);
@ -1499,7 +1504,7 @@ static void test_ggsn_selection(void)
OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
tp.lv[GSM48_IE_GSM_APN].len =
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
OSMO_ASSERT(ggc != NULL);
@ -1525,7 +1530,7 @@ static void test_ggsn_selection(void)
tp.lv[GSM48_IE_GSM_APN].val = apn_enc;
tp.lv[GSM48_IE_GSM_APN].len =
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Foo.Bar");
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Foo.Bar");
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
OSMO_ASSERT(ggc == NULL);
@ -1542,7 +1547,7 @@ static void test_ggsn_selection(void)
osmo_strlcpy(pdp_data->apn_str, "Test.Apn", sizeof(pdp_data->apn_str));
tp.lv[GSM48_IE_GSM_APN].len =
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Test.Apn");
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Test.Apn");
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
OSMO_ASSERT(ggc != NULL);
@ -1550,7 +1555,7 @@ static void test_ggsn_selection(void)
OSMO_ASSERT(strcmp(apn_str, "Test.Apn") == 0);
tp.lv[GSM48_IE_GSM_APN].len =
gprs_str_to_apn(apn_enc, sizeof(apn_enc), "Other.Apn");
osmo_apn_from_str(apn_enc, sizeof(apn_enc), "Other.Apn");
ggc = sgsn_mm_ctx_find_ggsn_ctx(ctx, &tp, &gsm_cause, apn_str);
OSMO_ASSERT(ggc == NULL);
@ -1652,11 +1657,7 @@ int main(int argc, char **argv)
tall_sgsn_ctx = talloc_named_const(osmo_sgsn_ctx, 0, "sgsn");
msgb_ctx = msgb_talloc_ctx_init(osmo_sgsn_ctx, 0);
sgsn_rate_ctr_init();
sgsn_auth_init(sgsn);
gprs_subscr_init(sgsn);
vty_init(&vty_info);
sgsn_vty_init(&sgsn->cfg);
test_llme();
test_subscriber();
@ -1676,7 +1677,7 @@ int main(int argc, char **argv)
talloc_report_full(osmo_sgsn_ctx, stderr);
OSMO_ASSERT(talloc_total_blocks(msgb_ctx) == 1);
OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 2);
OSMO_ASSERT(talloc_total_blocks(tall_sgsn_ctx) == 1);
return 0;
}

View File

@ -1,5 +1,6 @@
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
AM_LDFLAGS = -no-install
EXTRA_DIST = slhc_test.ok

View File

@ -1,5 +1,6 @@
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
AM_LDFLAGS = -no-install
EXTRA_DIST = sndcp_xid_test.ok

View File

@ -1,5 +1,6 @@
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBCARES_CFLAGS)
AM_LDFLAGS = -no-install
EXTRA_DIST = v42bis_test.ok

View File

@ -11,6 +11,8 @@ AM_CFLAGS = \
$(LIBCARES_CFLAGS) \
$(NULL)
AM_LDFLAGS = -no-install
EXTRA_DIST = \
xid_test.ok \
$(NULL)