mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn.git
synced 2025-11-02 13:13:16 +00:00
Compare commits
510 Commits
35c3
...
1fd205f0b8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fd205f0b8 | ||
|
|
b062c3647e | ||
|
|
d6c29beaf3 | ||
|
|
a24ebc7051 | ||
|
|
611b32811e | ||
|
|
7673bbd7ad | ||
|
|
b9c9271a1f | ||
|
|
dfcb514076 | ||
|
|
009c25f968 | ||
|
|
202039ed02 | ||
|
|
ecaa198fa0 | ||
|
|
eb5959f6b9 | ||
|
|
c1f2de5790 | ||
|
|
a0203ce7ff | ||
|
|
20d032bdd2 | ||
|
|
203676d047 | ||
|
|
265bc33b05 | ||
|
|
77cf72ea91 | ||
|
|
ad61ccd07b | ||
|
|
02fbdb59c2 | ||
|
|
b1444a6c11 | ||
|
|
6043666db5 | ||
|
|
6534fdbf27 | ||
|
|
2d4fe639cc | ||
|
|
4ba6638840 | ||
|
|
bae75b9a60 | ||
|
|
c156925405 | ||
|
|
2422c0375b | ||
|
|
fec2e5884a | ||
|
|
4b894f1a85 | ||
|
|
328edfd6f8 | ||
|
|
9eb1f7e006 | ||
|
|
f34503289e | ||
|
|
dda9c6780b | ||
|
|
234da0eed4 | ||
|
|
b79797d056 | ||
|
|
34182d28a4 | ||
|
|
901ca02e0e | ||
|
|
944b6dfb8d | ||
|
|
27dd6d84ec | ||
|
|
028c299bb2 | ||
|
|
d3b037ccfa | ||
|
|
921af3d428 | ||
|
|
0e8f055631 | ||
|
|
df44350b4b | ||
|
|
7a45b57485 | ||
|
|
7d94476bde | ||
|
|
6668b2b29a | ||
|
|
b69e326e69 | ||
|
|
11854f52ac | ||
|
|
61d3e3a377 | ||
|
|
d4bded987b | ||
|
|
99bc975225 | ||
|
|
7138f8eb93 | ||
|
|
5b289e83cf | ||
|
|
8a2ed97336 | ||
|
|
72283a1686 | ||
|
|
e7303adc8d | ||
|
|
e8c82d9cd1 | ||
|
|
6213201b95 | ||
|
|
3087322c3e | ||
|
|
b12c892a42 | ||
|
|
a39a564906 | ||
|
|
13592d2fa5 | ||
|
|
12ed86d17a | ||
|
|
35c178e84d | ||
|
|
868d818e6e | ||
|
|
140017e0ed | ||
|
|
c239545936 | ||
|
|
9650961c4b | ||
|
|
c05dad1035 | ||
|
|
7d5337fe80 | ||
|
|
2cd06e28f4 | ||
|
|
0bab0007c7 | ||
|
|
4ced617eb6 | ||
|
|
f8d248e2d1 | ||
|
|
bea6a0ffb5 | ||
|
|
a13cc20c98 | ||
|
|
1fd4a4c135 | ||
|
|
b3ce06058c | ||
|
|
0a6fe9727f | ||
|
|
7ba62d3061 | ||
|
|
62b28ffe1b | ||
|
|
cdf716cf9a | ||
|
|
a9c39c04de | ||
|
|
282de031f1 | ||
|
|
c3156193da | ||
|
|
cd3a8cfad6 | ||
|
|
e51b3be379 | ||
|
|
b34e0a5720 | ||
|
|
05363e0a32 | ||
|
|
a07e6d9c58 | ||
|
|
1ede89a35a | ||
|
|
647304fbe5 | ||
|
|
370d6e8b59 | ||
|
|
dc4c294f94 | ||
|
|
f2545b1b8f | ||
|
|
1f1d90f175 | ||
|
|
2a89bbf66f | ||
|
|
676777c5f9 | ||
|
|
ff9c46cc61 | ||
|
|
75a0aa78a3 | ||
|
|
20aef4de28 | ||
|
|
e746b0bef6 | ||
|
|
57567968ea | ||
|
|
7e4dbb4b34 | ||
|
|
7840375d51 | ||
|
|
429d332ece | ||
|
|
f24970a7ca | ||
|
|
2365fec0fb | ||
|
|
5df65b6c30 | ||
|
|
5f1020b963 | ||
|
|
eda1b83f75 | ||
|
|
b83aabaa95 | ||
|
|
1bebd08a4b | ||
|
|
a86056fdf3 | ||
|
|
99ec755643 | ||
|
|
d5dca3a67f | ||
|
|
3c26a1dc3c | ||
|
|
642019f288 | ||
|
|
f8a5066ad0 | ||
|
|
8c42673eba | ||
|
|
07feb06d54 | ||
|
|
86b630cfe1 | ||
|
|
93bc518b53 | ||
|
|
58101ea587 | ||
|
|
6aad14c3fa | ||
|
|
f44dfa8a0e | ||
|
|
e931b39b3c | ||
|
|
fd9e82da31 | ||
|
|
f2307c483f | ||
|
|
15a52d92c4 | ||
|
|
05190c36bb | ||
|
|
3d3c8c55f0 | ||
|
|
164a1eeb8a | ||
|
|
69569879ae | ||
|
|
fd4d435442 | ||
|
|
8ec269a0e0 | ||
|
|
4bd6f663a7 | ||
|
|
52c9b8e593 | ||
|
|
51028e2c16 | ||
|
|
e69f460ae7 | ||
|
|
0e707fc83a | ||
|
|
ffd6e37eb5 | ||
|
|
44bde6b85a | ||
|
|
e659f75cf1 | ||
|
|
67e71eac1c | ||
|
|
c1cf4af11b | ||
|
|
f37aedbf76 | ||
|
|
920c6c8c81 | ||
|
|
df203361e8 | ||
|
|
b61ab9b9ac | ||
|
|
5f4736aa85 | ||
|
|
fc1a5538d0 | ||
|
|
eb967fccb2 | ||
|
|
13c00008b4 | ||
|
|
e5614e434f | ||
|
|
b0b582bff8 | ||
|
|
bc46812bd7 | ||
|
|
4398ac073b | ||
|
|
05d5f28e93 | ||
|
|
7a74ae492e | ||
|
|
749ca7c850 | ||
|
|
e7ccfdb4aa | ||
|
|
e39ff86dd9 | ||
|
|
57b63875c7 | ||
|
|
55e3dc8ec8 | ||
|
|
acd967a177 | ||
|
|
8501126031 | ||
|
|
b43496a60d | ||
|
|
caff83e702 | ||
|
|
61f2186592 | ||
|
|
559636a4a2 | ||
|
|
13ccbc1e61 | ||
|
|
d32852664d | ||
|
|
77cdc424cb | ||
|
|
fb6cf3221e | ||
|
|
c63a8381e5 | ||
|
|
328ed94040 | ||
|
|
c230f0c283 | ||
|
|
e2b9b7ee57 | ||
|
|
199f295d36 | ||
|
|
3c7656a481 | ||
|
|
340a7e9339 | ||
|
|
938ebfb129 | ||
|
|
d06c717e30 | ||
|
|
57425a3805 | ||
|
|
f76428500a | ||
|
|
0f9966e307 | ||
|
|
245ac9501b | ||
|
|
2d0e22960c | ||
|
|
6cee1a1ded | ||
|
|
c0e146467a | ||
|
|
ab39b622cc | ||
|
|
3aba7ad2ae | ||
|
|
e9336a72a0 | ||
|
|
2f898265d0 | ||
|
|
a33f00637e | ||
|
|
c12c1a6b0c | ||
|
|
e5c8998f9c | ||
|
|
8969db7a49 | ||
|
|
0b0b59a8ff | ||
|
|
888052e71c | ||
|
|
913dbcd552 | ||
|
|
922684f318 | ||
|
|
3caa7f6d97 | ||
|
|
223754fde5 | ||
|
|
f025e582bb | ||
|
|
e8cd6856a5 | ||
|
|
c67c90b47e | ||
|
|
c26072a77f | ||
|
|
ce0a0e9beb | ||
|
|
c8ace5a03c | ||
|
|
183e6c3367 | ||
|
|
8de4be261d | ||
|
|
6fd19da165 | ||
|
|
adcf97d095 | ||
|
|
80adb30e93 | ||
|
|
ebd39830cb | ||
|
|
b05c1d0ce4 | ||
|
|
999a776b70 | ||
|
|
11ccc4305d | ||
|
|
901ed14c89 | ||
|
|
4be5ab3707 | ||
|
|
c999c223ae | ||
|
|
2ce050ba46 | ||
|
|
43e5f8a2c6 | ||
|
|
caf73b803c | ||
|
|
0018d3e0ec | ||
|
|
f955d078ed | ||
|
|
93ccc3cf5d | ||
|
|
10e0fcaae2 | ||
|
|
592eb140f0 | ||
|
|
c7b6aabac1 | ||
|
|
873c8a55e7 | ||
|
|
e0876bda26 | ||
|
|
21afdf9a32 | ||
|
|
c09cb29d78 | ||
|
|
6ad4040f55 | ||
|
|
45bf92feb4 | ||
|
|
d367b8bc78 | ||
|
|
5037b6817f | ||
|
|
d245c0e542 | ||
|
|
4380f94cf2 | ||
|
|
0d170d61aa | ||
|
|
fb5ccb468a | ||
|
|
b96d5a6ead | ||
|
|
6ff8d21fed | ||
|
|
5b1122f717 | ||
|
|
914484d561 | ||
|
|
b6343a72d8 | ||
|
|
ef0c2a4b85 | ||
|
|
02b24c5a44 | ||
|
|
cd7c7a74b7 | ||
|
|
ddb3fbb0f2 | ||
|
|
e245677cdd | ||
|
|
1c33e4af05 | ||
|
|
3844da98f8 | ||
|
|
dee0bcc8e9 | ||
|
|
51730f7a8c | ||
|
|
f23e2db752 | ||
|
|
8a33528854 | ||
|
|
00c1f91ed7 | ||
|
|
8d382c5337 | ||
|
|
ef3c9af0f9 | ||
|
|
5a21f07dff | ||
|
|
ea0b5d0df6 | ||
|
|
3054213e87 | ||
|
|
3326ba7d4c | ||
|
|
b6b2f14197 | ||
|
|
959f77e34b | ||
|
|
9e917647ae | ||
|
|
784c59f87e | ||
|
|
1aa0ae9db1 | ||
|
|
cab8588242 | ||
|
|
4b4c997dc5 | ||
|
|
c4c1db9e78 | ||
|
|
61ff273365 | ||
|
|
bf69833b6d | ||
|
|
7cb76a4321 | ||
|
|
c91f53ca0a | ||
|
|
5687ae65fa | ||
|
|
7c86a1efce | ||
|
|
453a51d1a1 | ||
|
|
a54ed46bac | ||
|
|
052d855449 | ||
|
|
11ad5713f2 | ||
|
|
d651edcce0 | ||
|
|
56f5e74d7d | ||
|
|
4bf53ef19a | ||
|
|
91bb720449 | ||
|
|
993d3f4d9a | ||
|
|
78db244b42 | ||
|
|
0e1b791c81 | ||
|
|
8cd74407ab | ||
|
|
6c4c6f08ae | ||
|
|
fb7f8c5f07 | ||
|
|
9a2fc908df | ||
|
|
e794c1f00b | ||
|
|
bd356a6d84 | ||
|
|
e8c8ec9683 | ||
|
|
55253716d2 | ||
|
|
1239cf457e | ||
|
|
ac44d6b2a2 | ||
|
|
c8d98ac8f9 | ||
|
|
6626bbc215 | ||
|
|
103a7ec033 | ||
|
|
6e8ed2784e | ||
|
|
7418797027 | ||
|
|
d97ff681c3 | ||
|
|
83142beca2 | ||
|
|
8c3d7fd263 | ||
|
|
9e583c8d89 | ||
|
|
5937dfd39f | ||
|
|
cafa3881ad | ||
|
|
447ad441e6 | ||
|
|
f7a1aed0e6 | ||
|
|
eb4233e505 | ||
|
|
2636e89ff0 | ||
|
|
bcd7709452 | ||
|
|
7ffc6603e2 | ||
|
|
826eaa327b | ||
|
|
952fbf20c9 | ||
|
|
8553f5532a | ||
|
|
3375fa4d64 | ||
|
|
e1ba4239b4 | ||
|
|
638cddd8f1 | ||
|
|
58937ce333 | ||
|
|
02f2c34f8a | ||
|
|
62fa6198ae | ||
|
|
c42331f359 | ||
|
|
15c9da226b | ||
|
|
8bca8de5cb | ||
|
|
82182d09c7 | ||
|
|
08395b3369 | ||
|
|
25998ddcc5 | ||
|
|
60581ae7c9 | ||
|
|
c70e8388c7 | ||
|
|
5ce54ba1e6 | ||
|
|
ff5b59a821 | ||
|
|
be2330fde4 | ||
|
|
8d2d7db818 | ||
|
|
92ef0c8675 | ||
|
|
68d9c5a468 | ||
|
|
ef6205ba00 | ||
|
|
86336af2a3 | ||
|
|
6d92f148aa | ||
|
|
27a0bf70e7 | ||
|
|
d3c3ddeb51 | ||
|
|
e6c5b4a970 | ||
|
|
aae7daff81 | ||
|
|
b32936d823 | ||
|
|
d5dc143001 | ||
|
|
65a5a0a27b | ||
|
|
9d16b14345 | ||
|
|
dd930a25ad | ||
|
|
b3e10aa8eb | ||
|
|
36ecddb705 | ||
|
|
90dedcb2e7 | ||
|
|
cfd307b4e8 | ||
|
|
b26a5a82db | ||
|
|
7369d449f1 | ||
|
|
5e1a486a72 | ||
|
|
627e285fd0 | ||
|
|
5e0b829884 | ||
|
|
bd6d677179 | ||
|
|
482bb07301 | ||
|
|
b63e19d7d2 | ||
|
|
c6548bbaab | ||
|
|
b2ebc59f30 | ||
|
|
9d550cb369 | ||
|
|
e6b2883f10 | ||
|
|
6528e8c1cb | ||
|
|
6e4cd085b5 | ||
|
|
91a8bbd5db | ||
|
|
d999e54aa2 | ||
|
|
394aa533e9 | ||
|
|
5997357c69 | ||
|
|
de67c001b7 | ||
|
|
ad08d17e07 | ||
|
|
118c411e81 | ||
|
|
fa2656d14e | ||
|
|
6e6347613d | ||
|
|
61557f42c1 | ||
|
|
a868e17c5e | ||
|
|
1fd50d9abe | ||
|
|
4146121cc9 | ||
|
|
85386dcfad | ||
|
|
9203da58e2 | ||
|
|
b71d2c5ddd | ||
|
|
029a70e493 | ||
|
|
de80976d94 | ||
|
|
284314ab0a | ||
|
|
4d1d2e78b1 | ||
|
|
030824e172 | ||
|
|
0e124d3131 | ||
|
|
865bf6f1bf | ||
|
|
10af11dacc | ||
|
|
afadd102bf | ||
|
|
12235310af | ||
|
|
d597ee260a | ||
|
|
743e687496 | ||
|
|
4c7609a508 | ||
|
|
62f6f9aebf | ||
|
|
3bad31bcb4 | ||
|
|
eb5aee580d | ||
|
|
e30f19542b | ||
|
|
a8f782502b | ||
|
|
324bb5a11e | ||
|
|
1cb4be9db0 | ||
|
|
6888021bf2 | ||
|
|
10b3d70fea | ||
|
|
8e3766cd38 | ||
|
|
d7276bde55 | ||
|
|
35f0e664bf | ||
|
|
31c4657c97 | ||
|
|
2e91fee1ad | ||
|
|
33ebedc3d5 | ||
|
|
ab264ebba8 | ||
|
|
a0bcfad99b | ||
|
|
762c39ccc6 | ||
|
|
ea05d5c5f8 | ||
|
|
9d016fd499 | ||
|
|
b8f22bd6c7 | ||
|
|
fd815bba12 | ||
|
|
ccd1252bd7 | ||
|
|
02514bc592 | ||
|
|
9119d50849 | ||
|
|
3b848bdc42 | ||
|
|
8b88f5f7f3 | ||
|
|
a794811416 | ||
|
|
87264e6454 | ||
|
|
0b72240799 | ||
|
|
8333ef10c9 | ||
|
|
6dfb5fef40 | ||
|
|
259e303436 | ||
|
|
6ec5dc26b3 | ||
|
|
4ec21769b2 | ||
|
|
c44af53d1e | ||
|
|
f8d3e7fe05 | ||
|
|
d8037bcedc | ||
|
|
aa89f5dffc | ||
|
|
5623eb8439 | ||
|
|
d956e16c7b | ||
|
|
2c90899bc4 | ||
|
|
1aaeea4900 | ||
|
|
99bd9d3139 | ||
|
|
39cbecd273 | ||
|
|
5ed3f67f96 | ||
|
|
a299d65114 | ||
|
|
a43fb7b8e5 | ||
|
|
f913265309 | ||
|
|
5b6c4b8ccd | ||
|
|
2179dec71d | ||
|
|
2844b5ea00 | ||
|
|
f0f596f3d9 | ||
|
|
6e3112579e | ||
|
|
05140b8dfe | ||
|
|
c21be62380 | ||
|
|
1927052de6 | ||
|
|
c488665f92 | ||
|
|
982e130144 | ||
|
|
788863cda5 | ||
|
|
404d9b8bba | ||
|
|
d723a97fae | ||
|
|
72b61e4344 | ||
|
|
39aa9ee6df | ||
|
|
dfd7c24e16 | ||
|
|
d7ef94c0bb | ||
|
|
37bc0ff580 | ||
|
|
e456e32f15 | ||
|
|
c9e8d90982 | ||
|
|
862bc62975 | ||
|
|
e18df0e28d | ||
|
|
5f0bce6636 | ||
|
|
03a2ed5b30 | ||
|
|
40fce10e46 | ||
|
|
6daac87bd2 | ||
|
|
05fee6dbee | ||
|
|
4b8e309f57 | ||
|
|
55fcf111e1 | ||
|
|
43f16ec403 | ||
|
|
43c5b7023b | ||
|
|
df9b39142f | ||
|
|
d1463bc365 | ||
|
|
794f446a28 | ||
|
|
f7afd20200 | ||
|
|
812a8bd18f | ||
|
|
eb3a8556be | ||
|
|
1825ab5bae | ||
|
|
20795e3fda | ||
|
|
ba2e500395 | ||
|
|
ef38b4c55e | ||
|
|
def0d941f9 | ||
|
|
bfd67d2f69 | ||
|
|
6c0586ac7b | ||
|
|
b72141458c | ||
|
|
aed46ec97d | ||
|
|
d3dcaf0bf2 | ||
|
|
af779d2ab2 | ||
|
|
1f60bbe8a2 | ||
|
|
3a0b772d6c | ||
|
|
37bd02121b | ||
|
|
321eb8e8c9 | ||
|
|
932ccf87a0 | ||
|
|
c42e21e81c | ||
|
|
313cf35581 | ||
|
|
b6f8b74b07 | ||
|
|
34604c26b4 | ||
|
|
319a52b577 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
open_collective: osmocom
|
||||
13
.gitignore
vendored
13
.gitignore
vendored
@@ -2,17 +2,19 @@ debian/*.log
|
||||
*.o
|
||||
*.lo
|
||||
*.a
|
||||
*.la
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
||||
bscconfig.h
|
||||
bscconfig.h.in
|
||||
config.h
|
||||
config.h.in
|
||||
*.*~
|
||||
*.sw?
|
||||
.libs
|
||||
*.pyc
|
||||
*.gcda
|
||||
*.gcno
|
||||
*~
|
||||
|
||||
#configure
|
||||
aclocal.m4
|
||||
@@ -38,9 +40,8 @@ ltmain.sh
|
||||
|
||||
|
||||
# apps and app data
|
||||
src/gprs/osmo-sgsn
|
||||
src/gprs/osmo-gbproxy
|
||||
src/gprs/osmo-gtphub
|
||||
src/sgsn/osmo-sgsn
|
||||
src/gtphub/osmo-gtphub
|
||||
src/libcommon/gsup_test_client
|
||||
|
||||
#tests
|
||||
@@ -68,3 +69,5 @@ doc/manuals/generated/
|
||||
doc/manuals/osmomsc-usermanual.xml
|
||||
doc/manuals/common
|
||||
doc/manuals/build
|
||||
|
||||
contrib/osmo-sgsn.spec
|
||||
|
||||
10
Makefile.am
10
Makefile.am
@@ -9,15 +9,21 @@ AM_CPPFLAGS = \
|
||||
$(NULL)
|
||||
|
||||
SUBDIRS = \
|
||||
doc \
|
||||
include \
|
||||
src \
|
||||
contrib \
|
||||
tests \
|
||||
doc \
|
||||
$(NULL)
|
||||
|
||||
BUILT_SOURCES = $(top_srcdir)/.version
|
||||
EXTRA_DIST = git-version-gen osmoappdesc.py .version
|
||||
EXTRA_DIST = \
|
||||
.version \
|
||||
README.md \
|
||||
debian \
|
||||
git-version-gen \
|
||||
osmoappdesc.py \
|
||||
$(NULL)
|
||||
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS = \
|
||||
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
|
||||
|
||||
17
README
17
README
@@ -1,17 +0,0 @@
|
||||
About OsmoSGSN
|
||||
==============
|
||||
|
||||
OsmoSGSN originated from the OpenBSC project, as a separate program within
|
||||
openbsc.git. In 2017, OpenBSC was split in separate repositories, and hence
|
||||
OsmoSGSN was given its own separate git repository.
|
||||
|
||||
OsmoSGSN exposes
|
||||
- GSUP towards OsmoHLR (or a MAP proxy);
|
||||
- GTP towards a GGSN (e.g. OsmoGGSN);
|
||||
- Gb towards a BSS (e.g. OsmoPCU);
|
||||
- IuPS towards an RNC or HNB-GW (e.g. OsmoHNBGW) for 3G data;
|
||||
- The Osmocom typical telnet VTY and CTRL interfaces.
|
||||
|
||||
Find OsmoSGSN issue tracker and wiki online at
|
||||
https://osmocom.org/projects/osmosgsn
|
||||
https://osmocom.org/projects/osmosgsn/wiki
|
||||
100
README.md
Normal file
100
README.md
Normal file
@@ -0,0 +1,100 @@
|
||||
osmo-sgsn - Osmocom SGSN Implementation
|
||||
=======================================
|
||||
|
||||
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](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 homepage online at <https://osmocom.org/projects/osmosgsn/wiki>.
|
||||
|
||||
|
||||
GIT Repository
|
||||
--------------
|
||||
|
||||
You can clone from the official osmo-sgsn.git repository using
|
||||
|
||||
git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
|
||||
|
||||
There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn>
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
User Manuals and VTY reference manuals are [optionally] built in PDF form
|
||||
as part of the build process.
|
||||
|
||||
Pre-rendered PDF version of the current "master" can be found at
|
||||
[User Manual](https://ftp.osmocom.org/docs/latest/osmosgsn-usermanual.pdf)
|
||||
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
|
||||
------------
|
||||
|
||||
Discussions related to osmo-sgsn are happening on the
|
||||
osmocom-net-gprs@lists.osmocom.org mailing list, please see
|
||||
<https://lists.osmocom.org/postorius/lists/osmocom-net-gprs.lists.osmocom.org/> for subscription
|
||||
options and the list archive.
|
||||
|
||||
Please observe the [Osmocom Mailing List
|
||||
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
|
||||
when posting.
|
||||
|
||||
|
||||
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
|
||||
------------
|
||||
|
||||
Our coding standards are described at
|
||||
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards>
|
||||
|
||||
We use a Gerrit based patch submission/review process for managing
|
||||
contributions. Please see
|
||||
<https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for
|
||||
more details
|
||||
|
||||
The current patch queue for osmo-sgsn can be seen at
|
||||
<https://gerrit.osmocom.org/#/q/project:osmo-sgsn+status:open>
|
||||
|
||||
|
||||
History
|
||||
-------
|
||||
|
||||
OsmoSGSN originated from the OpenBSC project, as a separate program within
|
||||
openbsc.git. In 2017, OpenBSC was split in separate repositories, and hence
|
||||
OsmoSGSN was given its own separate git repository.
|
||||
@@ -1,6 +1,6 @@
|
||||
To run the configuration parsing and output (VTY) test suite, first install
|
||||
|
||||
git://git.osmocom.org/python/osmo-python-tests
|
||||
https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests
|
||||
|
||||
and pass the following configure options here:
|
||||
|
||||
|
||||
15
TODO-RELEASE
Normal file
15
TODO-RELEASE
Normal file
@@ -0,0 +1,15 @@
|
||||
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
|
||||
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release
|
||||
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
|
||||
# LIBVERSION=c:r:a
|
||||
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
|
||||
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a.
|
||||
# If any interfaces have been added since the last public release: c:r:a + 1.
|
||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
|
||||
#library what description / commit summary line
|
||||
libgtp >1.12.0 new field dir_tun_flags in struct pdp_t
|
||||
libgtp >1.12.0 gtp_set_cb_update_context_ind(), gtp_update_context_resp()
|
||||
libosmocore >1.10.0 enum gsm48_gprs_ie_mm: GSM48_IE_GMM_UE_NET_CAP, GSM48_IE_GMM_VD_PREF_UE_USAGE
|
||||
libosmo-gsup-client >1.8.0 osmo_gsup_client_is_connected(), osmo_gsup_client_get_rem_addr(), osmo_gsup_client_get_rem_port()
|
||||
osmo-iuh >1.7.0 ranap multiple params are constified, see osmo-iuh Change-Id I667dc2ef377c1ceb5b11315458f00b282c143c81
|
||||
osmo-iuh >1.7.0 ranap_new_msg_error_ind()
|
||||
63
configure.ac
63
configure.ac
@@ -22,6 +22,11 @@ AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
LT_INIT
|
||||
|
||||
dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang
|
||||
AS_CASE(["$LD"],[*clang*],
|
||||
[AS_CASE(["${host_os}"],
|
||||
[*linux*],[archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'])])
|
||||
|
||||
dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
|
||||
AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
|
||||
if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
|
||||
@@ -29,39 +34,31 @@ if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
|
||||
fi
|
||||
PKG_PROG_PKG_CONFIG([0.20])
|
||||
|
||||
dnl check for AX_CHECK_COMPILE_FLAG
|
||||
m4_ifdef([AX_CHECK_COMPILE_FLAG], [], [
|
||||
AC_MSG_ERROR([Please install autoconf-archive; re-run 'autoreconf -fi' for it to take effect.])
|
||||
])
|
||||
dnl use a defined standard across all builds and don't depend on compiler default
|
||||
CFLAGS="$CFLAGS -std=gnu11"
|
||||
|
||||
dnl checks for libraries
|
||||
AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
|
||||
AC_SUBST(LIBRARY_DL)
|
||||
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.11.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.11.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 0.11.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.11.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.5.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 0.11.0)
|
||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.2.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 0.2.1)
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.10.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.6.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.12.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 >= 0.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBASN1C, libasn1c >= 0.9.30)
|
||||
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 0.3.0)
|
||||
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 1.6.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")
|
||||
AC_SUBST(osmo_ac_iu)
|
||||
|
||||
|
||||
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.2.0)
|
||||
PKG_CHECK_MODULES(LIBCARES, libcares)
|
||||
|
||||
dnl checks for header files
|
||||
@@ -110,15 +107,8 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])],
|
||||
CFLAGS="$saved_CFLAGS"
|
||||
AC_SUBST(SYMBOL_VISIBILITY)
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -Wall"
|
||||
CFLAGS="$CFLAGS -Wall"
|
||||
|
||||
AX_CHECK_COMPILE_FLAG([-Werror=implicit], [CFLAGS="$CFLAGS -Werror=implicit"])
|
||||
AX_CHECK_COMPILE_FLAG([-Werror=maybe-uninitialized], [CFLAGS="$CFLAGS -Werror=maybe-uninitialized"])
|
||||
AX_CHECK_COMPILE_FLAG([-Werror=memset-transposed-args], [CFLAGS="$CFLAGS -Werror=memset-transposed-args"])
|
||||
AX_CHECK_COMPILE_FLAG([-Werror=null-dereference], [CFLAGS="$CFLAGS -Werror=null-dereference"])
|
||||
AX_CHECK_COMPILE_FLAG([-Werror=sizeof-array-argument], [CFLAGS="$CFLAGS -Werror=sizeof-array-argument"])
|
||||
AX_CHECK_COMPILE_FLAG([-Werror=sizeof-pointer-memaccess], [CFLAGS="$CFLAGS -Werror=sizeof-pointer-memaccess"])
|
||||
CPPFLAGS="$CPPFLAGS -Wall -Wno-trigraphs"
|
||||
CFLAGS="$CFLAGS -Wall -Wno-trigraphs"
|
||||
|
||||
# Coverage build taken from WebKit's configure.in
|
||||
AC_MSG_CHECKING([whether to enable code coverage support])
|
||||
@@ -164,13 +154,13 @@ AC_ARG_ENABLE([external_tests],
|
||||
[Include the VTY/CTRL tests in make check [default=no]]),
|
||||
[enable_ext_tests="$enableval"],[enable_ext_tests="no"])
|
||||
if test "x$enable_ext_tests" = "xyes" ; then
|
||||
AC_CHECK_PROG(PYTHON2_AVAIL,python2,yes)
|
||||
if test "x$PYTHON2_AVAIL" != "xyes" ; then
|
||||
AC_MSG_ERROR([Please install python2 to run the VTY/CTRL tests.])
|
||||
AC_CHECK_PROG(PYTHON3_AVAIL,python3,yes)
|
||||
if test "x$PYTHON3_AVAIL" != "xyes" ; then
|
||||
AC_MSG_ERROR([Please install python3 to run the VTY/CTRL tests.])
|
||||
fi
|
||||
AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmotestvty.py,yes)
|
||||
if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then
|
||||
AC_MSG_ERROR([Please install git://osmocom.org/python/osmo-python-tests to run the VTY/CTRL tests.])
|
||||
AC_MSG_ERROR([Please install https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests to run the VTY/CTRL tests.])
|
||||
fi
|
||||
fi
|
||||
AC_MSG_CHECKING([whether to enable VTY/CTRL tests])
|
||||
@@ -239,18 +229,21 @@ 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
|
||||
src/sgsn/Makefile
|
||||
src/gtphub/Makefile
|
||||
tests/Makefile
|
||||
tests/atlocal
|
||||
tests/gprs/Makefile
|
||||
tests/gbproxy/Makefile
|
||||
tests/gprs_routing_area/Makefile
|
||||
tests/sgsn/Makefile
|
||||
tests/gtphub/Makefile
|
||||
tests/xid/Makefile
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
demonstrate a unblock bug on the GB Proxy..
|
||||
"""
|
||||
|
||||
bts_ns_reset = "\x02\x00\x81\x01\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
|
||||
ns_reset_ack = "\x03\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
|
||||
|
||||
bts_ns_unblock = "\x06"
|
||||
ns_unblock_ack = "\x07"
|
||||
|
||||
bts_bvc_reset_0 = "\x00\x00\x00\x00\x22\x04\x82\x00\x00\x07\x81\x03\x3b\x81\x02"
|
||||
ns_bvc_reset_0_ack = "\x00\x00\x00\x00\x23\x04\x82\x00\x00"
|
||||
|
||||
bts_bvc_reset_8167 = "\x00\x00\x00\x00\x22\x04\x82\x1f\xe7\x07\x81\x08\x08\x88\x72\xf4\x80\x10\x1c\x00\x9c\x40"
|
||||
|
||||
|
||||
import socket
|
||||
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
socket.bind(("0.0.0.0", 0))
|
||||
socket.setblocking(1)
|
||||
|
||||
|
||||
import sys
|
||||
port = int(sys.argv[1])
|
||||
print "Sending data to port: %d" % port
|
||||
|
||||
def send_and_receive(packet):
|
||||
socket.sendto(packet, ("127.0.0.1", port))
|
||||
|
||||
try:
|
||||
data, addr = socket.recvfrom(4096)
|
||||
except socket.error, e:
|
||||
print "ERROR", e
|
||||
import sys
|
||||
sys.exit(0)
|
||||
return data
|
||||
|
||||
#send stuff once
|
||||
|
||||
to_send = [
|
||||
(bts_ns_reset, ns_reset_ack, "reset ack"),
|
||||
(bts_ns_unblock, ns_unblock_ack, "unblock ack"),
|
||||
(bts_bvc_reset_0, ns_bvc_reset_0_ack, "BVCI=0 reset ack"),
|
||||
]
|
||||
|
||||
|
||||
for (out, inp, type) in to_send:
|
||||
res = send_and_receive(out)
|
||||
if res != inp:
|
||||
print "Failed to get the %s" % type
|
||||
sys.exit(-1)
|
||||
|
||||
import time
|
||||
time.sleep(3)
|
||||
res = send_and_receive(bts_bvc_reset_8167)
|
||||
print "Sent all messages... check wireshark for the last response"
|
||||
@@ -32,25 +32,21 @@ export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export LD_LIBRARY_PATH="$inst/lib"
|
||||
export PATH="$inst/bin:$PATH"
|
||||
|
||||
osmo-build-dep.sh libosmo-netif "" --disable-doxygen
|
||||
osmo-build-dep.sh libosmo-abis
|
||||
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 libosmo-sigtran "" --disable-doxygen
|
||||
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
|
||||
CONFIG=""
|
||||
if [ "$WITH_MANUALS" = "1" ]; then
|
||||
osmo-build-dep.sh osmo-gsm-manuals
|
||||
CONFIG="--enable-manuals"
|
||||
fi
|
||||
|
||||
@@ -64,17 +60,18 @@ 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" \
|
||||
$MAKE distcheck \
|
||||
DISTCHECK_CONFIGURE_FLAGS="--enable-werror $IU --enable-external-tests $CONFIG" \
|
||||
$MAKE $PARALLEL_MAKE distcheck \
|
||||
|| cat-testlogs.sh
|
||||
|
||||
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
|
||||
make -C "$base/doc/manuals" publish
|
||||
fi
|
||||
|
||||
$MAKE $PARALLEL_MAKE maintainer-clean
|
||||
osmo-clean-workspace.sh
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
EXTRA_DIST = \
|
||||
osmo-gbproxy.service \
|
||||
osmo-gtphub.service \
|
||||
osmo-sgsn.service
|
||||
|
||||
if HAVE_SYSTEMD
|
||||
SYSTEMD_SERVICES = \
|
||||
osmo-gbproxy.service \
|
||||
osmo-gtphub.service \
|
||||
osmo-sgsn.service
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description=Osmocom Gb proxy
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/osmo-gbproxy -c /etc/osmocom/osmo-gbproxy.cfg
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
RestartPreventExitStatus=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
721
debian/changelog
vendored
721
debian/changelog
vendored
@@ -1,3 +1,724 @@
|
||||
osmo-sgsn (1.12.0) unstable; urgency=medium
|
||||
|
||||
[ Andreas Eversberg ]
|
||||
* Use uniform log format for default config files
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* build: include README.md into the release tarball
|
||||
* gmm: cosmetic: fix preprocessor macro formatting
|
||||
* gmm: mmctx_timer_stop(): warn about timer not running
|
||||
* VTY: move default settings to sgsn_instance_alloc()
|
||||
* VTY: sync default UMTS UEA config with osmo-msc
|
||||
* README.md: cosmetic: fix a typo
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* gsup: Use new libosmogsm struct osmo_gsup_pdp_info fields
|
||||
|
||||
[ Harald Welte ]
|
||||
* Add funding link to github mirror
|
||||
* README.md: Overhaul (more links; improved formatting)
|
||||
* README.md: Add Forum and Issue Tracker sections
|
||||
|
||||
[ Max ]
|
||||
* .deb/.rpm: add osmocom user during package install
|
||||
|
||||
[ Oliver Smith ]
|
||||
* contrib/osmo-sgsn.spec: fix build for almalinux:8
|
||||
* .deb/.rpm: various fixes related to non-root
|
||||
* contrib: remove rpm spec file
|
||||
* debian/postinst: add checks, be verbose
|
||||
* sgsn/sgsn_vty: create state-dir
|
||||
* debian/osmo-gtphub.init: delete
|
||||
* doc: set state-dir to /var/lib/osmocom/osmo-sgsn
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* docs: replace legacy NS with new NS2 chapters
|
||||
* docs: update year to 2024
|
||||
* docs: front page: use https:// instead of http://
|
||||
|
||||
-- Oliver Smith <osmith@sysmocom.de> Wed, 24 Jul 2024 17:31:38 +0200
|
||||
|
||||
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 ]
|
||||
* llme_free: clean up related sndcp
|
||||
* treewide: remove FSF address
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* Drop unneeded ax_check_compile_flag.m4
|
||||
* Revert "sgsn: Handle different levels of QoS"
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
* s/cipher_support_mask/gea_encryption_mask
|
||||
* Iu: add UEA encryption
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS'
|
||||
|
||||
[ Harald Welte ]
|
||||
* update git URLs (git -> https; gitea)
|
||||
* README: Major update
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Wed, 29 Jun 2022 11:45:08 +0200
|
||||
|
||||
osmo-sgsn (1.8.0) unstable; urgency=medium
|
||||
|
||||
[ Harald Welte ]
|
||||
* Remove bogus DNS log category
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* manuals: Regenerate counters/VTY through docker
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* main: resurrect removed 'ns' logging category as deprecated
|
||||
* doc/manuals: update configuration.adoc to use new command syntax
|
||||
* tests/Makefile.am: do not try removing non-existing files
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* ranap: log ranap iu event type name instead of number
|
||||
* gmm: log GMM msg type name instead of number
|
||||
* gmm: Expect E_VLR_ANSWERED when in ST_IU_SECURITY_CMD
|
||||
* gmm_fsm: Expect E_GMM_COMMON_PROC_INIT_REQ when in ST_GMM_COMMON_PROC_INIT
|
||||
* mm_iu: Send event E_PMM_PS_CONN_ESTABLISH upon rx GMM SERVICE REQUEST
|
||||
* mm_iu: Expect E_PMM_PS_ATTACH when in ST_PMM_IDLE
|
||||
* gprs_gmm.c: State proper GMM prefix logging rx/tx of GMM messages
|
||||
* mm_state_iu_fsm: T3314 expiry must lead to PMM IDLE, not PMM DETACHED
|
||||
* Iu: Drop timer X3314
|
||||
* gprs_ranap.c: Clean up code path releasing IU conn
|
||||
* mm_state_{gb,iu}_fsm: Add missing license block, improve spec references
|
||||
* mm_state_{gb,iu}_fsm: Improve naming for detach event
|
||||
* Drop unused GBRPOXY enum field
|
||||
* gtp: Delete ctx upon receive UpdateCtxResp with cause Non-existent
|
||||
* Support forwarding RIM messages over GTPCv1 EUTRAN<->GERAN
|
||||
* Use new stat item/ctr getter APIs
|
||||
|
||||
[ Keith ]
|
||||
* vty: Fix optional display of pdp with mm-context
|
||||
* VTY: Don't display 'PDP Address: invalid' for IPv4v6
|
||||
|
||||
[ Eric ]
|
||||
* add support for multiple encryption algorithms and a5/4
|
||||
|
||||
[ Oliver Smith ]
|
||||
* gtphub: remove llist_first, llist_last macros
|
||||
* vty: add "page imsi"
|
||||
* debian/control: remove dh-systemd build-depend
|
||||
* Revert "Turn some compiler warnings into errors"
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 16 Nov 2021 17:57:50 +0100
|
||||
|
||||
osmo-sgsn (1.7.0) unstable; urgency=medium
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* gprs_gmm: Check for RAT change and ensure this only happens for RAU/ATT
|
||||
* gbproxy-usermanual: Explain BSSGP/BVC handling
|
||||
* gbproxy: Whitespace fixes
|
||||
* gbproxy: Add todo for BVC RESET logic
|
||||
* gbproxy: Get the peer if paging by BVCI on SIG_BVC
|
||||
* Let libosmocore handle VTY parent node tracking
|
||||
* osmo-gbproxy: Free msgb in ns2 prim callback
|
||||
* configure.ac: Require python3 for ext_tests
|
||||
* osmo-gbproxy: Implement nsvc-state ctrl command
|
||||
* gbproxy: Remove test testing NSVCI change
|
||||
* gbproxy: Add NSE peer that can have multiple gbproxy_peers
|
||||
* gbproxy: Ensure BVC0 is reset before handling PtP BVCs
|
||||
* gbproxy: Only send paging to each matching NSE once
|
||||
* gbproxy: Separate function to move gbproxy_peer to different nse
|
||||
* gbproxy: Add logging macros for NSE and BVC
|
||||
* gbproxy: Use LOG macros for NSE/BVC
|
||||
* gbproxy: Change generic LOG messages so BVCI/NSEI fmt is consistent
|
||||
* gbproxy: Add todos encountered while going through the code
|
||||
* gbproxy: Add BVC log filters
|
||||
* gbproxy: Add newline to log message
|
||||
* gbproxy: Allow gbproxy_nse_free(NULL)
|
||||
* gbproxy: Delete gbproxy_nse in delete-gbproxy-peer VTY command
|
||||
* mm_state_gb_fsm: Handle implicit detach from mm_standby
|
||||
* gbproxy: Fix bvci check in gbprox_rx_ptp_from_*
|
||||
* osmo-gbproxy: Initialize all hash_maps
|
||||
* gbproxy: Fix confusing log message in gbprox_relay2nse
|
||||
* gbproxy: Add SGSN NRI configuration
|
||||
* gbproxy: Add SGSN pooling support
|
||||
* gbproxy: Add comments to sgsn functions
|
||||
* gbproxy: Add config option to name an SGSN
|
||||
* gbproxy: Add VTY command to override the node selection function
|
||||
* Fix gbproxy_sgsn_by_tlli wraparound
|
||||
* gbproxy: Implement TLLI cache and use it for SUSPEND/RESUME
|
||||
* gbproxy: Increase TLLI cache timeout to 10s
|
||||
* gbproxy: Implement IMSI cache
|
||||
* gbproxy: Use IMSI cache to handle PAGING_PS_REJECT
|
||||
* gbproxy: Use C-style comments
|
||||
* gbproxy: Move helper function to a more logical place
|
||||
* gbproxy: Remove unused variable assignment
|
||||
* gbproxy: Fix VTY cmd name
|
||||
* gbproxy: Define and use help string for gbproxy
|
||||
* gbproxy: Add VTY commands to query the TLLI/IMSI cache
|
||||
* gbproxy: Use IMSI cache for PTP paging and implement DUMMY_PAGING_PS
|
||||
* gbproxy: Print the correct message type for dummy paging/paging reject
|
||||
* gbproxy: Improve log messages in gbproxy_select_sgsn
|
||||
* gbproxy: Fix radio status routing by TMSI
|
||||
* manual/gbproxy: Update overview chapter
|
||||
* Rename OsmoGbPROXY -> *Proxy
|
||||
* manuals/gbproxy: Update configuration chapter
|
||||
* manuals/gbproxy: Add osmo-bsc MSC pooling chapter from Neels as a base
|
||||
* manuals/gbproxy: MSC -> SGSN for pooling chapter
|
||||
* manuals/gbproxy: Move pooling to separate chapter
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* gprs_gmm_fsm.c: Implement RAT change between 2g and 3g
|
||||
* gtphub: rename sgsn's oww osmo_sockaddr into sgsn_sockaddr
|
||||
* gprs_llc: _bssgp_tx_dl_ud: ensure the LLME is valid before using it
|
||||
* gmm: on invalid RA id reject the MS with an implicit detach
|
||||
* gtphub_test: fix compilation error on gcc 10.2.0
|
||||
* gtphub: fix compilation with gcc 10.2.0
|
||||
* Port gbproxy to NS2
|
||||
* sgsn: check for NULL of gprs_subscr_get_or_create()
|
||||
* sgsn: Use the new NS2 api
|
||||
* gbproxy: use ns2 vty2
|
||||
* configure.ac: define a c standard instead of using the compilers default
|
||||
* follow libosmocore/gprs_ns2 API changes of GPRS enums
|
||||
* gbproxy: follow gprs_ns2 API vty changes
|
||||
* sgsn: migrate to the new gprs_ns2_vty configuration
|
||||
* follow libosmocore/gprs_ns2 API changes (gprs_ns2_dynamic_create_nse)
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
* manual: explain IuPS, add SCCP/M3UA section from common chapters
|
||||
* fix nullpointer: in gsm48_rx_gmm_ra_upd_req()
|
||||
* gsup: send RAT type on LU
|
||||
* gbproxy_test.c: fix mobile identity test data
|
||||
* use new osmo_mobile_identity API everywhere
|
||||
|
||||
[ Eric ]
|
||||
* tests: dlopen does not imply availability of dlsym..
|
||||
* configure.ac: fix libtool issue with clang and sanitizer
|
||||
|
||||
[ Harald Welte ]
|
||||
* gtphub_test: Fix compilation with gcc-10
|
||||
* Fix memory leak when SNDCP de-fragmentation is used
|
||||
* Treat RAU as implicit RESUME if GMM is suspended
|
||||
* *.spec.in: Use %config(noreplace) to retain current config file
|
||||
* Send a BVC-RESET to all persistent Gb interfaces at start-up
|
||||
* Use osmo_fd_setup() whenever applicable
|
||||
* Use osmo_fd_*_{disable,enable}
|
||||
* gbproxy: Properly implement paging to LAC/RAC
|
||||
* gbproxy: Implement paging to entire BSS area
|
||||
* gprs_gb_parse: Add function to determine TLLI from encoded BSSGP
|
||||
* gbproxy: Pass TLLI as LSP towards NS to facilitate load sharing
|
||||
* gb_proxy_peer: Add some FIXMEs regarding invalid assumptions
|
||||
* gb_proxy: More precise + readable log messages
|
||||
* gb_proxy: Broadcast SGSN-INVOKE-TRACE and OVERLOAD
|
||||
* gbproxy: Move BSS-side BVC-RESET processing to its own function
|
||||
* gb_proxy: Slightly restructure processing of BSS-originated BVC-RESET
|
||||
* gbproxy: Cosmetics: use longer lines
|
||||
* gbproxy: Send BVC-STATUS if BSS sends us BVC-RESET without mandatory IEs
|
||||
* gb_proxy: Use TLVP_PRES_LEN instead of TLVP_PRESENT
|
||||
* gb_proxy: Rename gbproxy_peer to gbproxy_bvc
|
||||
* gbproxy: Rename gbproxy_cfg.nses to gbproxy_cfg.bss_nses
|
||||
* gbproxy: convert bss_nses from llist_head to hashtable
|
||||
* gbproxy: convert nse->bvcs from llist_head to hashtable
|
||||
* gbproxy: Remove patching, TLLI-tracking and SGSN2 support
|
||||
* gb_proxy: cosmetic: Use function rather than open-coding is_sgsn
|
||||
* gbproxy: Delete gbproxy_test
|
||||
* gb_proxy: Introduce more validation / constraint checks
|
||||
* gbproxy: use gbprox_relay2peer() whenever possible
|
||||
* gb_proxy: Use osmo_tlv_prot_parse() to validate mandatory IEs
|
||||
* gbproxy: Log FSM timeouts
|
||||
* migrate to DLBSSGP as log sub-system for BSSGP
|
||||
* gbproxy major rewrite for SGSN pool support
|
||||
* gbproxy: Use "(nsei << 16) | bvci" as rate_ctr_group index
|
||||
* gbproxy: Introduce new DOBJ log category; log object allocation/release
|
||||
* gbproxy: Don't create an extra msgb copy for SGSN DL SIG
|
||||
* gbproxy: Implement handling of BVC Flow Control
|
||||
* gbproxy: Copy RA-ID from BSS side BVC to CELL and SGSN-side BVC
|
||||
* gbproxy: (Re)allocate SGSN-side PTP BVC even if CELL already exists
|
||||
* gbproxy: Fix segfault when receiving PAGING for unknown destination
|
||||
* gbproxy: Add FSM related VTY commands
|
||||
* gbproxy: Implement scaling of BVC flow control in SGSN pool
|
||||
* gbproxy: Improve VTY state introspection
|
||||
* gbproxy: rename vty command "show gbproxy ..." to "show gbproxy bvc ..."
|
||||
* gbproxy: Add "show gbproxy cell ..." VTY command
|
||||
* gbproxy: Fix build on Deiban 8
|
||||
* gb_proxy: Don't use orphan log subsystem DPCU
|
||||
* gbproxy: Avoid depending on any of the SGSN code
|
||||
* main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
|
||||
* manuals: generate vty reference xml at build time
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* Use OSMO_FD_* instead of deprecated BSC_FD_*
|
||||
* sgsn_libgtp: Improve ps-paging logging
|
||||
* gprs_gmm_fsm.c: Add missing license header
|
||||
* sgsn_libgtp: Avoid ps-paging MS on GMM Suspended state
|
||||
* configure.ac: Fix trailing whitespace
|
||||
* doc: Update VTY reference xml file
|
||||
* Support setting rt-prio and cpu-affinity mask through VTY
|
||||
* Change default SCTP conn NULL->127.0.0.1 to localhost->localhost
|
||||
* contrib/jenkins: Enable parallel make in make distcheck
|
||||
* Log error if pdp ctx is freed while holding an active timer
|
||||
* Fix crash rx DeactPdpReq while waiting for DeactPdpAck after gtp side is freed
|
||||
* sgsn_delete_pdp_ctx: Add documentation and assert assumptions
|
||||
* process_ms_ctx_status: refactor to avoid code duplication
|
||||
* process_ms_ctx_status: Fix crash deleting PDP Ctx if GTP side was already released
|
||||
* gbproxy: generate coredump and exit upon SIGABRT received
|
||||
* gtphub: generate coredump and exit upon SIGABRT received
|
||||
* sgsn: generate coredump and exit upon SIGABRT received
|
||||
* gmm: fix build without define PTMSI_ALLOC
|
||||
* gmm: Introduce comment to ease addition of Network feature support IE later
|
||||
* .gitignore: Ignore new autofoo tmp files
|
||||
* sndcp: Fix struct bit fields on big endian
|
||||
* Fix nsei+bvci not updated on rx UL SNDCP data
|
||||
|
||||
[ Oliver Smith ]
|
||||
* contrib: import RPM spec
|
||||
* contrib: integrate RPM spec
|
||||
* Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
|
||||
* contrib/jenkins: don't build osmo-gsm-manuals
|
||||
* gbproxy: remove (moved to own repository)
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* debian/control: change maintainer to the Osmocom team / mailing list
|
||||
* gb_proxy_peer: sgsn can never be NULL in gbproxy_sgsn_by_nri()
|
||||
* gb_proxy_peer: fix NULL pointer dereference in gbproxy_sgsn_alloc()
|
||||
|
||||
[ Keith ]
|
||||
* Fix Radio Priority in MM Attach and PDP Context Activation
|
||||
* VTY: Add gtp state-dir command
|
||||
|
||||
[ Philipp Maier ]
|
||||
* gprs_sndcp: fix use after free
|
||||
* sgsn_rim: Add routing for (GERAN) BSSGP RIM messages
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 23 Feb 2021 20:29:33 +0100
|
||||
|
||||
osmo-sgsn (1.6.0) unstable; urgency=medium
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* gprs_gmm: Introduce macros to access msgb's associated IU UE ctx
|
||||
* gprs_llc.h: Improve documentation of some structs
|
||||
* gprs_gmm.c: Improve doc on nullable parameters
|
||||
* gprs_gmm.c: Drop unneeded brackets
|
||||
* Introduce define TLLI_UNASSIGNED
|
||||
* gprs_sgsn.c: Warn upon llme free unexpected scenarios
|
||||
* gprs_gmm: Clarify comment during TLLI assignment
|
||||
* gprs_sgsn.c: Remove recently introduced assert
|
||||
* gprs_gmm: Introduce assert to guard against unexpected condition
|
||||
* gprs_gmm.c: Use correct function to set MM_IDLE state during cleanup
|
||||
* gprs_sgsn.h: Flag MM_CTX_T_GERAN_Iu as not supported
|
||||
* gprs_gmm.c: Flag mmctx_set_(p)mm_state() functions static
|
||||
* sgsn: use sccp_simple_client API to setup ss7 id 0 instead of 1
|
||||
* gprs_gmm.c: Fix typo in log message
|
||||
* gprs_gmm.c: Call mmctx_set_(p)mm_state only on related ran_type
|
||||
* Introduce and use log macros when no mm ctx available
|
||||
* gprs_gmm: Avoid spaces in fsm events and enum strings
|
||||
* tests: Verify that timers can be set over VTY
|
||||
* Replace own timer infra with libosmocore osmo_tdef
|
||||
* tests: Introduce vty-transcript-test tests
|
||||
* gprs_gmm.c: Use osmo_rai_name() in log line
|
||||
* examples: Add osmo-sgsn_custom-sccp.cfg
|
||||
* vty: Introduce cs7-instance-iu
|
||||
* gprs_gmm.c: Print value_string of reject cause
|
||||
* gprs_gmm.c: Add spec document to function documentation
|
||||
* gtp: make echo_interval unsigned
|
||||
* gtp: cb_delete_context(): Clarify why pdp->lib is set to NULL
|
||||
* Introduce log helper LOGGGSN and log category DGTP
|
||||
* sgsn: gtp: Drop related pdp contexts on echo timeout against GGSN
|
||||
* Move lots of Iu/ranap specific code into its own file
|
||||
* Move llc->MM/SM Gb specific glue code to its own file
|
||||
* Split enum gprs_pmm_state into Iu and Gb counterparts
|
||||
* Merge common allocation steps for Gb and Iu ctx
|
||||
* gprs_gmm.c: Replace inet_ntoa with inet_ntop
|
||||
* sgsn_cdr.c: Fix ip addr string buffer size
|
||||
* sgsn_vty: Fix mmctx rate_ctr output indentation
|
||||
* sgsn_vty: Print correct Iu mmctx id in 'show mm-context'
|
||||
* Introduce FSM mm_state_gb_fsm
|
||||
* Introduce FSM mm_state_iu_fsm
|
||||
* vty: Print MM state and RAN type in show mm-context
|
||||
* src/gprs/Makefile.am: Move build of shared .c files to an internal lib
|
||||
* Move out gbproxy to its own subdir
|
||||
* Move out gtphub to its own subdir
|
||||
* Move out sgsn to its own subdir
|
||||
* gmm: Move code handling GMM Attach Complete to its own function
|
||||
* gmm: Move code handling GMM Routing Area Update Complete to its own function
|
||||
* gmm: Move code handling GMM PTMSI Realloc Complete to its own function
|
||||
* enum gprs_gmm_state: Fix spec reference
|
||||
* Implement GMM State using osmocom FSM
|
||||
* Split out GPRS SM layer into its own file
|
||||
* sgsn: Reject PdpActReq if no GTP pdp ctx exists
|
||||
* Introduce TODO-RELEASE file
|
||||
* sgsn_libgtp.c: Drop use of deprecated libgtp APIs gtp_retrans*()
|
||||
* gmm: Fix assertion hit during RA UPD REQ before completting gmm attach
|
||||
* Improve logging in gprs_llc.c code
|
||||
* gprs_llc.c: Use enum instead of hardcoded value
|
||||
* gprs_gmm.c: Send XID reset with received TLLI
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* gprs/gprs_gmm: implement T3314. Timeout to reset MM state READY->STANDBY
|
||||
* gprs_gmm: only update gb/iu cell information when Iu/Gb present
|
||||
* gprs_gmm: clarify comment of Iu follow-on request
|
||||
* gprs_gmm: gsm48_rx_gmm_att_req(): refactor duplicated code
|
||||
* sgsn_pdp_ctx_terminate: check llme before accessing
|
||||
* gprs_ranap: send CommonId after receiving Security Mode Complete
|
||||
* mm_gb_fsm: unassign the llme when entering MM_IDLE
|
||||
* gprs_ranap: refactor REQUIRE_MM define
|
||||
* sgsn: when receiving data PDU notify the Gb GMM fsm
|
||||
* Avoid compiling unneeded files when building without Iu
|
||||
* gprs_ranap: release Iu UE Context when exiting PMM Connected
|
||||
* Iu: implement a user inactivity timer
|
||||
* gprs_ranap: on Iu release, stop the attach fsm if running
|
||||
* gprs_mm_state_gb_fsm: ensure T3350 is not running when entering IDLE
|
||||
* gprs_ranap: add missing rc = 0
|
||||
* gprs_sgsn: always allocate Gb/Iu mm fsm
|
||||
* sgsn: MM Gb Fsm: fix event handling for implicit detach
|
||||
* ranap: add non-spec X1001
|
||||
* gprs_gmm: release Iu connection on RAU failures
|
||||
* sgsn_mm_ctx_alloc(): check for unallocated fsms
|
||||
* sgsn_libgtp: refactor ps paging into gprs_gb
|
||||
* sgsn: Gb: implementing PS Paging when MS is MM_STANDBY
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* gprs_mm_state_iu_fsm.c: fix: assign timer_cb to mm_state_iu_fsm
|
||||
|
||||
[ Max ]
|
||||
* Use libosmocore constant for IMSI length in ACL entry
|
||||
|
||||
[ Harald Welte ]
|
||||
* LLC: Don't use hard-coded N201-U / N201-I values in XID
|
||||
* Initial OsmoGbPROXY user manual
|
||||
* check for osmo_fsm_register() error return values
|
||||
* check for osmo_ss7_init() error return value
|
||||
* manual: Fix copy+paste error
|
||||
* exit(2) on unsupported positional arguments on command line
|
||||
|
||||
[ Oliver Smith ]
|
||||
* gitignore: fix paths to binaries
|
||||
* doc: add OsmoGbProxy VTY reference
|
||||
* regen_doc.sh: support gbproxy, run without docker
|
||||
* osmoappdesc.py, tests: switch to python 3
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Fri, 03 Jan 2020 19:17:56 +0100
|
||||
|
||||
osmo-sgsn (1.5.0) unstable; urgency=medium
|
||||
|
||||
[ Max ]
|
||||
* Improve 'show subscriber cache' vty command
|
||||
* GMM: permit VLR_ANSWERED event in attach FSM
|
||||
* Fix IMSI padding in imsi-acl
|
||||
|
||||
[ Harald Welte ]
|
||||
* gbproxy_test: Fix test expectations of gprs_ns_rcvmsg()
|
||||
* LLC XID: Fix string representation of N201_U
|
||||
* LLC: Don't blindly assume all LLC frames have data payload
|
||||
* LLC: Avoid NOTICE message on LLC NULL
|
||||
* gprs_llc: Correctly refuse any ABM command (SABM, DISC) with DM
|
||||
* LLC: Store the XID inside the LLC Entity, not LLC Mgmg Entity
|
||||
* gb_proxy.h: Add missing comments; improve comments
|
||||
* gb_proxy: cosmetic: Use 'bool' in data structures where applicable
|
||||
|
||||
[ efistokl ]
|
||||
* gsm0408_rcv_gmm: send Iu-ReleaseCommand upon receiving Attach Complete.
|
||||
* gprs_gmm: send Service Reject when no PDP ctxs are available.
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* gprs_gmm: reintroduce calling gsm48_gmm_authorize when not handling GMM Attach Requests
|
||||
* gbproxy: parse dtap GSM48_MT_GSM_DEACT_PDP_REQ|ACK
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* gprs_sndcp_comp_free: Replace ifelse with switch and better handling of error
|
||||
* sgsn: vty: Improve log warning content with spec section
|
||||
* Document max retransmit times for T3395
|
||||
* sgsn: Fix echo timer not started upon first pdp ctx created
|
||||
* sgsn_libgtp: Use new per-GSN libgtp API instead of deprecated API
|
||||
* sgsn: Have authentication required on by default
|
||||
* Remove undefined param passed to {logging,osmo_stats}_vty_add_cmds
|
||||
* Require newer versions of dependencies
|
||||
|
||||
[ Keith ]
|
||||
* Echo zero byte XID-Field of Type L3_PAR
|
||||
|
||||
[ Oliver Smith ]
|
||||
* debian: create -doc subpackage with pdf manuals
|
||||
* contrib/jenkins.sh: run "make maintainer-clean"
|
||||
* osmo-gtphub.cfg: fix conflict with osmo-sgsn.cfg
|
||||
* osmo-gbproxy.cfg: fix conflict with osmo-sgsn.cfg
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* doc/manuals/vty: regenerate sgsn_vty_reference.xml
|
||||
* osmo-sgsn: add VTY parameter to toggle authentication
|
||||
* sgsn_mm_ctx_find_ggsn_ctx(): fix: always set gsm_cause
|
||||
|
||||
[ Eric Wild ]
|
||||
* replace magic tmsi constant with define
|
||||
* turn -Werror=null-dereference into a warning
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* manuals: Add script to regenerate vty/counter documentation
|
||||
* manuals: Update vty/counter documentation
|
||||
* Add/fix help string for version option
|
||||
* osmo-sgsn: Fix outdated information in usermanual
|
||||
* configuration.adoc: Small fixes
|
||||
* configuration.adoc: Add a section about encryption
|
||||
|
||||
[ Ruben Undheim ]
|
||||
* Spelling fixes
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Thu, 08 Aug 2019 16:46:31 +0200
|
||||
|
||||
osmo-sgsn (1.4.0) unstable; urgency=medium
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* gprs_subscriber: gsup_auth_error: reject MS in all cases
|
||||
* gprs_gmm: make functions relating to GMM Attach Request public
|
||||
* gprs_gmm: make extract_subscr_msisdn extract_subscr_hlr public
|
||||
* gprs_gmm: Cancel Location: use detach type IMSI
|
||||
* vty: add cmd "reset sgsn state"
|
||||
* tests: remove gmm unit tests
|
||||
* gprs_gmm: introduce a GMM Attach Request FSM
|
||||
* debian: add missing build dependencies
|
||||
* sgsn: use gtp_clear_queues() when reset sgsn state
|
||||
* vty: restart sgsn state: improve output message
|
||||
* sgsn_ggsn_ctx_drop_pdp: protect against nullpointer when MM is gone
|
||||
* gprs_sgsn.h: fix wrong type of re-attempts
|
||||
* GTP: refactor the echo timer
|
||||
* gprs_gmm: dont answer unknown IMSI/TMSI on Service Requests NET_FAIL
|
||||
* gprs_gmm: Fix missing Security Command for 3G when attaching
|
||||
* sgsn_libgtp: fix a potential memleak when the GGSN is not reachable
|
||||
* gprs_llc: remove the FCS from the msgb by trim'ing the msgb
|
||||
* OsmoSGSN: add rate counter documentation
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* gb_proxy: tallocate memory for gbproxy cfg so it can be a talloc ctx
|
||||
* gb_proxy: Add ctrl interface and nsvc-state, gbproxy-state commands
|
||||
* git-version-gen: Don't check for .git directory
|
||||
|
||||
[ Stefan Sperling ]
|
||||
* add a test for OS#3178 (invalid unitdata message)
|
||||
* finish gbproxy_parse_bssgp_unitdata test
|
||||
* fix bogus assertion in encode_comp_field()
|
||||
* fix bogus error check in gprs_sndcp_comp_create()
|
||||
* use enums consistently instead of falling back to int
|
||||
* update gbproxy test expected output
|
||||
* consistently check the result of osmo_shift_v_fixed()
|
||||
* remove pointless declaration of struct gsm_network
|
||||
* make gsup ipa name configurable in osmo-sgsn.cfg
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* jenkins.sh: Use --enable-werror only when iu support is disabled
|
||||
* jenkins.sh: Remove non-existent configure options
|
||||
* Drop all references of unused SMPP
|
||||
* Drop all references of unused MGCP
|
||||
* Drop unused common_vty.c
|
||||
* sgsn_libgtp.c: Log pointer of deleted context
|
||||
* Maintain per ggsn pdp ctx list
|
||||
* osmo-sgsn: ping GGSN periodically and check for restart counter
|
||||
* Disarm T3395 when dettaching mmctx from pdpctx
|
||||
* examples: Enable by default echo req towards active GGSNs
|
||||
* vty: Add cmd to disable echo loop explictly
|
||||
* Add optional TearDownInd IE in PDP DEACT REQ towards PCU
|
||||
* sgsn: Don't attempt to delete GTP pdp ctx if GGSN was restarted
|
||||
* Forward GGSN originated DEACT PDP CTX REQ
|
||||
* sgsn: Fix T3395 firing forever
|
||||
* sgsn: subscriber: Avoid calling memcpy with NULL src
|
||||
* sgsn: cdr: Fix uninitialized string access if ggsn is detached
|
||||
* sgsn: gtp: Use new API to send PDP DEL CTX REQ without freeing ctx locally
|
||||
* sgsn: Fix crash using new libgtp cb_recovery2 API
|
||||
* gbproxy: Replace '.' in counter names with ':'
|
||||
* Drop gprs_msgb_copy with libosmocore replacement
|
||||
* Drop gprs_msgb_resize_area with libosmocore replacement
|
||||
* Use osmo_clock_gettime from libosmocore
|
||||
* gbproxy: Add VTY parameter: link stored-msgs-max-length
|
||||
* gbproxy: Add new VTY-managed timer: link-list clean-stale-timer
|
||||
* gbproxy: Replace '.' in counter names with ':'
|
||||
* Add osmo-gtphub systemd service file
|
||||
* debian: Fix typo in rules preventing build with IU support
|
||||
* Install systemd services with autotools
|
||||
* Install sample cfg file to /etc/osmocom
|
||||
* Update wrong references to bsc in sgsn code
|
||||
* Allocate sgsn_instance with talloc
|
||||
* gbproxy: flag gbproxy_assign_imsi as static
|
||||
* gbproxy: Fix abort during APN patch
|
||||
* gbproxy: Remove unneeded parse_ctx param
|
||||
* gbproxy: flush_stored_messages: Move comment to func description
|
||||
* gbproxy: flush_stored_messages: Log and route using stored_msg info
|
||||
* gbproxy: flush_stored_messages: Get rid of msg param
|
||||
* Allow easily disabling GFDL references
|
||||
* OsmoSGSN: configuration: Move pdp ctx specific CDR fields to its own table
|
||||
* OsmoSGSN: configuration: Add missing pdp-periodic event
|
||||
* OsmoSGSN: configuration: Document CDR CTRL interface
|
||||
* OsmoSGSN: overview: Fix typo and reference OpenGGSN->OsmoGGSN
|
||||
|
||||
[ Harald Welte ]
|
||||
* migrate to oap_client in libosmogsm
|
||||
* remove libcommon
|
||||
* gbproxy-legacy: Ensure well-formed config file
|
||||
* Remove local libgsupclient; Use libosmo-gsup-client from osmo-hlr
|
||||
* initial checkin of manuals to public repo
|
||||
* Add link to Asciidoc source code of manual
|
||||
* OsmoSGSN: Fix formatting/cross reference in CDR section
|
||||
* Update GSUP chapter regarding UMTS AKA and other recent changes
|
||||
* GSUP: Add ladder diagrams for protocol transactions / procedures
|
||||
* share chapters/gsup.adoc from OsmoSGSN to OsmoMSC + OsmoHLR
|
||||
* vty-ref: Update URI of docbook 5.0 schema
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
* use __FILE__, not __BASE_FILE__
|
||||
* vty: fix doc str for 'reset sgsn state'
|
||||
* vty: add SCCP related vty commands
|
||||
* fix build: remove unused variable
|
||||
* Importing history from osmo-gsm-manuals.git
|
||||
* add 'make check' target
|
||||
* fix 'make clean': shell glob, ignore failure
|
||||
* refactor Makefile build rules, don't use the FORCE
|
||||
* OsmoSGSN: update VTY reference
|
||||
* sgsn: update vty reference
|
||||
|
||||
[ Oliver Smith ]
|
||||
* gtphub: Add --version cmdline option
|
||||
* build manuals moved here from osmo-gsm-manuals.git
|
||||
* Fix DISTCHECK_CONFIGURE_FLAGS override
|
||||
* contrib/jenkins.sh: build and publish manuals
|
||||
* contrib: fix makedistcheck with disabled systemd
|
||||
|
||||
[ Max ]
|
||||
* Cleanup non-existent files from debian/copyright
|
||||
* Use safer functions for IMSI ACL
|
||||
* gbproxy: fix formatting in gbproxy-state command
|
||||
* gbproxy: add number-of-peers ctrl command
|
||||
* Revert "gbproxy: fix formatting in gbproxy-state command"
|
||||
* Add OsmoSGSN control interface description
|
||||
* Remove misleading comment
|
||||
* Constify sgsn_acl_lookup() parameter
|
||||
* Drop unused osmo-sgsn.pc
|
||||
* Use explicit length check
|
||||
* Use explicit parameter for sgsn_auth_init()
|
||||
|
||||
[ Jonathan Brielmaier ]
|
||||
* fix various typos across all manuals
|
||||
|
||||
[ ikostov ]
|
||||
* SGSN: add Auth. policy, NS Statistics and BSSGP state examples, tweaks
|
||||
* GSUP, OAP: fix AUTS length to 14, not 16
|
||||
|
||||
[ Philipp Maier ]
|
||||
* osmo-sgsn: Update VTY command reference
|
||||
* osmo-sgsn: improve auth-policy explaination
|
||||
* osmo-sgsn: Explain TCP/IP header compression
|
||||
* osmo-sgsn: fix arrow tips in flow diagrams
|
||||
|
||||
[ Holger Hans Peter Freyther ]
|
||||
* sgsn: Fix numbering of QoS and add basic description for APN
|
||||
* sgsn: Add charging characteristics to GSUP
|
||||
|
||||
-- Harald Welte <laforge@gnumonks.org> Wed, 23 Jan 2019 18:32:41 +0100
|
||||
|
||||
osmo-sgsn (1.3.0) unstable; urgency=medium
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
|
||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
||||
9
|
||||
10
|
||||
|
||||
53
debian/control
vendored
53
debian/control
vendored
@@ -1,29 +1,27 @@
|
||||
Source: osmo-sgsn
|
||||
Section: net
|
||||
Priority: extra
|
||||
Maintainer: Alexander Couzens <lynxis@fe80.eu>
|
||||
Build-Depends: debhelper (>=9),
|
||||
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
|
||||
Build-Depends: debhelper (>= 10),
|
||||
dh-autoreconf,
|
||||
dh-systemd (>= 1.5),
|
||||
autotools-dev,
|
||||
autoconf,
|
||||
automake,
|
||||
libtool,
|
||||
pkg-config,
|
||||
libasn1c-dev,
|
||||
libtalloc-dev,
|
||||
libc-ares-dev,
|
||||
libgtp-dev,
|
||||
libosmocore-dev,
|
||||
libosmo-abis-dev,
|
||||
libosmo-ranap-dev,
|
||||
libosmo-sccp-dev,
|
||||
libosmo-sigtran-dev,
|
||||
libosmo-netif-dev,
|
||||
libosmo-gsup-client-dev
|
||||
libgtp-dev (>= 1.12.0),
|
||||
libosmocore-dev (>= 1.10.0),
|
||||
libosmo-abis-dev (>= 1.6.0),
|
||||
libosmo-gsup-client-dev (>= 1.8.0),
|
||||
libasn1c-dev (>= 0.9.30),
|
||||
libosmo-ranap-dev (>= 1.6.0),
|
||||
libosmo-sigtran-dev (>= 1.9.0),
|
||||
osmo-gsm-manuals-dev (>= 1.6.0)
|
||||
Standards-Version: 3.9.8
|
||||
Vcs-Git: git://git.osmocom.org/osmo-sgsn.git
|
||||
Vcs-Browser: https://git.osmocom.org/osmo-sgsn
|
||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
|
||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
|
||||
Homepage: https://projects.osmocom.org/projects/osmo-sgsn
|
||||
|
||||
|
||||
@@ -31,14 +29,14 @@ Package: osmo-sgsn
|
||||
Architecture: any
|
||||
Multi-Arch: foreign
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: OsmoSGSN: Osmocom's Serving GPRS Support Node for 2G and 3G packet-switched mobile networks
|
||||
Description: OsmoSGSN: Osmocom's Serving GPRS Support Node for 2G and 3G packet-switched mobile networks
|
||||
|
||||
Package: osmo-sgsn-dbg
|
||||
Section: debug
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Depends: osmo-sgsn (= ${binary:Version}), ${misc:Depends}
|
||||
Description: OsmoSGSN: Osmocom's Serving GPRS Support Node for 2G and 3G packet-switched mobile networks
|
||||
Description: OsmoSGSN: Osmocom's Serving GPRS Support Node for 2G and 3G packet-switched mobile networks
|
||||
|
||||
Package: osmo-gtphub
|
||||
Architecture: any
|
||||
@@ -52,18 +50,11 @@ Priority: extra
|
||||
Depends: osmo-gtphub (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Debug symbols for Osmocom GTP Hub
|
||||
|
||||
Package: osmo-gbproxy
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends}
|
||||
Recommends: osmo-sgsn
|
||||
Description: Osmocom GPRS Gb Interface Proxy
|
||||
The purpose of the Gb proxy is to aggregate the Gb links of multiple
|
||||
BSS's and present them in one Gb link to the SGSN.
|
||||
|
||||
Package: osmo-gbproxy-dbg
|
||||
Architecture: any
|
||||
Section: debug
|
||||
Priority: extra
|
||||
Depends: osmo-gbproxy (= ${binary:Version}), ${misc:Depends}
|
||||
Description: Debug symbols for Osmocom GPRS Gb Interface Proxy
|
||||
Package: osmo-sgsn-doc
|
||||
Architecture: all
|
||||
Section: doc
|
||||
Priority: optional
|
||||
Depends: ${misc:Depends}
|
||||
Description: ${misc:Package} PDF documentation
|
||||
Various manuals: user manual, VTY reference manual and/or
|
||||
protocol/interface manuals.
|
||||
|
||||
68
debian/copyright
vendored
68
debian/copyright
vendored
@@ -1,6 +1,6 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: osmo-sgsn
|
||||
Source: git://git.osmocom.org/osmo-sgsn
|
||||
Source: https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn
|
||||
|
||||
Files: .gitignore
|
||||
.gitreview
|
||||
@@ -19,13 +19,10 @@ Files: .gitignore
|
||||
contrib/ipa.py
|
||||
contrib/jenkins.sh
|
||||
contrib/soap.py
|
||||
contrib/systemd/osmo-gbproxy.service
|
||||
contrib/systemd/osmo-sgsn.service
|
||||
contrib/twisted_ipa.py
|
||||
doc/Makefile.am
|
||||
doc/examples/Makefile.am
|
||||
doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg
|
||||
doc/examples/osmo-gbproxy/osmo-gbproxy.cfg
|
||||
doc/examples/osmo-gtphub/gtphub-example.txt
|
||||
doc/examples/osmo-gtphub/osmo-gtphub-1iface.cfg
|
||||
doc/examples/osmo-gtphub/osmo-gtphub.cfg
|
||||
@@ -36,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
|
||||
@@ -51,13 +47,12 @@ Files: .gitignore
|
||||
src/gprs/osmo_sgsn.cfg
|
||||
tests/Makefile.am
|
||||
tests/atlocal.in
|
||||
tests/gbproxy/Makefile.am
|
||||
tests/gbproxy/gbproxy_test.ok
|
||||
tests/gprs/Makefile.am
|
||||
tests/gprs/gprs_test.c
|
||||
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
|
||||
@@ -79,41 +74,35 @@ 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/crc24.c
|
||||
src/gprs/gb_proxy.c
|
||||
src/gprs/gb_proxy_main.c
|
||||
src/gprs/gb_proxy_patch.c
|
||||
src/gprs/gb_proxy_peer.c
|
||||
src/gprs/gb_proxy_tlli.c
|
||||
src/gprs/gb_proxy_vty.c
|
||||
src/gprs/gprs_gb_parse.c
|
||||
src/gprs/gprs_gmm.c
|
||||
src/gprs/gprs_llc.c
|
||||
src/gprs/gprs_llc_parse.c
|
||||
src/gprs/gprs_llc_vty.c
|
||||
src/gprs/gprs_llc_xid.c
|
||||
src/gprs/gprs_sgsn.c
|
||||
src/gprs/gprs_sndcp.c
|
||||
src/gprs/gprs_sndcp_comp.c
|
||||
src/gprs/gprs_sndcp_dcomp.c
|
||||
src/gprs/gprs_sndcp_pcomp.c
|
||||
src/gprs/gprs_sndcp_vty.c
|
||||
src/gprs/gprs_sndcp_xid.c
|
||||
src/gprs/gprs_subscriber.c
|
||||
src/gprs/crc24.c
|
||||
src/gprs/gprs_utils.c
|
||||
src/gprs/gtphub.c
|
||||
src/gprs/gtphub_main.c
|
||||
src/gprs/gtphub_vty.c
|
||||
src/gprs/sgsn_ares.c
|
||||
src/gprs/sgsn_auth.c
|
||||
src/gprs/sgsn_cdr.c
|
||||
src/gprs/sgsn_ctrl.c
|
||||
src/gprs/sgsn_libgtp.c
|
||||
src/gprs/sgsn_main.c
|
||||
src/gprs/sgsn_vty.c
|
||||
src/gtphub/gtphub.c
|
||||
src/gtphub/gtphub_main.c
|
||||
src/gtphub/gtphub_vty.c
|
||||
src/sgsn/gprs_gmm.c
|
||||
src/sgsn/gprs_llc.c
|
||||
src/sgsn/gprs_llc_vty.c
|
||||
src/sgsn/gprs_llc_xid.c
|
||||
src/sgsn/gprs_sgsn.c
|
||||
src/sgsn/gprs_sndcp.c
|
||||
src/sgsn/gprs_sndcp_comp.c
|
||||
src/sgsn/gprs_sndcp_dcomp.c
|
||||
src/sgsn/gprs_sndcp_pcomp.c
|
||||
src/sgsn/gprs_sndcp_vty.c
|
||||
src/sgsn/gprs_sndcp_xid.c
|
||||
src/sgsn/gprs_subscriber.c
|
||||
src/sgsn/sgsn_auth.c
|
||||
src/sgsn/sgsn_cdr.c
|
||||
src/sgsn/sgsn_ctrl.c
|
||||
src/sgsn/sgsn_libgtp.c
|
||||
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
|
||||
@@ -140,9 +129,8 @@ License: AGPL-3.0+
|
||||
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/>.
|
||||
|
||||
Files: src/gprs/gtphub_ares.c
|
||||
src/gprs/gtphub_sock.c
|
||||
tests/gbproxy/gbproxy_test.c
|
||||
Files: src/gtphub/gtphub_ares.c
|
||||
src/gtphub/gtphub_sock.c
|
||||
Copyright: 2013 Jacob Erlbeck <jerlbeck@sysmocom.de>
|
||||
2013 sysmocom s.f.m.c. GmbH
|
||||
2014 Holger Hans Peter Freyther
|
||||
|
||||
151
debian/osmo-gbproxy.init
vendored
151
debian/osmo-gbproxy.init
vendored
@@ -1,151 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: osmo-gbproxy
|
||||
# Required-Start: $network $local_fs
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Osmocom GBproxy
|
||||
# Description: A tool to proxy the GPRS Gb interface.
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Harald Welte <laforge@gnumonks.org>
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
NAME=osmo-gbproxy # Introduce the short server's name here
|
||||
DESC="Osmocom GBProxy" # Introduce a short description here
|
||||
DAEMON=/usr/bin/osmo-gbproxy # Introduce the server's location here
|
||||
SCRIPTNAME=/etc/init.d/osmocom-gbproxy
|
||||
CONFIG_FILE=/etc/osmocom/osmocom-gbproxy.cfg
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x $DAEMON ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/osmocom-gbproxy ] && . /etc/default/osmocom-gbproxy
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
DAEMON_ARGS="-D -c $CONFIG_FILE"
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --quiet --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --exec $DAEMON -- \
|
||||
$DAEMON_ARGS \
|
||||
|| return 2
|
||||
# Add code here, if necessary, that waits for the process to be ready
|
||||
# to handle requests from services started subsequently which depend
|
||||
# on this one. As a last resort, sleep for some time.
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --name $NAME
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Wait for children to finish too if this is a daemon that forks
|
||||
# and if the daemon is only ever run from this initscript.
|
||||
# If the above conditions are not satisfied then add some other code
|
||||
# that waits for the process to drop all resources that could be
|
||||
# needed by services started subsequently. A last resort is to
|
||||
# sleep for some time.
|
||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||
[ "$?" = 2 ] && return 2
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
#
|
||||
# Function that sends a SIGHUP to the daemon/service
|
||||
#
|
||||
do_reload() {
|
||||
#
|
||||
# If the daemon can reload its configuration without
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
start-stop-daemon --stop --signal 1 --quiet $PIDFILE --name $NAME
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||
;;
|
||||
#reload|force-reload)
|
||||
#
|
||||
# If do_reload() is not implemented then leave this commented out
|
||||
# and leave 'force-reload' as an alias for 'restart'.
|
||||
#
|
||||
#log_daemon_msg "Reloading $DESC" "$NAME"
|
||||
#do_reload
|
||||
#log_end_msg $?
|
||||
#;;
|
||||
restart|force-reload)
|
||||
#
|
||||
# If the "reload" option is implemented then remove the
|
||||
# 'force-reload' alias
|
||||
#
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
:
|
||||
5
debian/osmo-gbproxy.install
vendored
5
debian/osmo-gbproxy.install
vendored
@@ -1,5 +0,0 @@
|
||||
etc/osmocom/osmo-gbproxy.cfg
|
||||
lib/systemd/system/osmo-gbproxy.service
|
||||
usr/bin/osmo-gbproxy
|
||||
usr/share/doc/osmo-sgsn/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg usr/share/doc/osmo-gbproxy/examples
|
||||
usr/share/doc/osmo-sgsn/examples/osmo-gbproxy/osmo-gbproxy.cfg usr/share/doc/osmo-gbproxy/examples
|
||||
150
debian/osmo-gtphub.init
vendored
150
debian/osmo-gtphub.init
vendored
@@ -1,150 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: osmo-gtphub
|
||||
# Required-Start: $network $local_fs
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Osmocom GTP hub
|
||||
# Description: Osmocom GTP hub
|
||||
### END INIT INFO
|
||||
|
||||
# Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
NAME=osmo-gtphub # Introduce the short server's name here
|
||||
DESC="Osmocom GTP hub" # Introduce a short description here
|
||||
DAEMON=/usr/bin/osmo-gtphub # Introduce the server's location here
|
||||
SCRIPTNAME=/etc/init.d/osmo-gtphub
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x $DAEMON ] || exit 0
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/osmo-gtphub ] && . /etc/default/osmo-gtphub
|
||||
|
||||
# Load the VERBOSE setting and other rcS variables
|
||||
. /lib/init/vars.sh
|
||||
|
||||
# Define LSB log_* functions.
|
||||
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
DAEMON_ARGS="$DAEMON_ARGS -D -c $CONFIG_FILE"
|
||||
|
||||
#
|
||||
# Function that starts the daemon/service
|
||||
#
|
||||
do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --quiet --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --exec $DAEMON -- \
|
||||
$DAEMON_ARGS \
|
||||
|| return 2
|
||||
# Add code here, if necessary, that waits for the process to be ready
|
||||
# to handle requests from services started subsequently which depend
|
||||
# on this one. As a last resort, sleep for some time.
|
||||
}
|
||||
|
||||
#
|
||||
# Function that stops the daemon/service
|
||||
#
|
||||
do_stop()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been stopped
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --name $NAME
|
||||
RETVAL="$?"
|
||||
[ "$RETVAL" = 2 ] && return 2
|
||||
# Wait for children to finish too if this is a daemon that forks
|
||||
# and if the daemon is only ever run from this initscript.
|
||||
# If the above conditions are not satisfied then add some other code
|
||||
# that waits for the process to drop all resources that could be
|
||||
# needed by services started subsequently. A last resort is to
|
||||
# sleep for some time.
|
||||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
|
||||
[ "$?" = 2 ] && return 2
|
||||
return "$RETVAL"
|
||||
}
|
||||
|
||||
#
|
||||
# Function that sends a SIGHUP to the daemon/service
|
||||
#
|
||||
do_reload() {
|
||||
#
|
||||
# If the daemon can reload its configuration without
|
||||
# restarting (for example, when it is sent a SIGHUP),
|
||||
# then implement that here.
|
||||
#
|
||||
start-stop-daemon --stop --signal 1 --quiet $PIDFILE --name $NAME
|
||||
return 0
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME"
|
||||
do_start
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
stop)
|
||||
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
||||
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
||||
esac
|
||||
;;
|
||||
status)
|
||||
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
|
||||
;;
|
||||
#reload|force-reload)
|
||||
#
|
||||
# If do_reload() is not implemented then leave this commented out
|
||||
# and leave 'force-reload' as an alias for 'restart'.
|
||||
#
|
||||
#log_daemon_msg "Reloading $DESC" "$NAME"
|
||||
#do_reload
|
||||
#log_end_msg $?
|
||||
#;;
|
||||
restart|force-reload)
|
||||
#
|
||||
# If the "reload" option is implemented then remove the
|
||||
# 'force-reload' alias
|
||||
#
|
||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
case "$?" in
|
||||
0|1)
|
||||
do_start
|
||||
case "$?" in
|
||||
0) log_end_msg 0 ;;
|
||||
1) log_end_msg 1 ;; # Old process is still running
|
||||
*) log_end_msg 1 ;; # Failed to start
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
# Failed to stop
|
||||
log_end_msg 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
:
|
||||
1
debian/osmo-sgsn-doc.install
vendored
Normal file
1
debian/osmo-sgsn-doc.install
vendored
Normal file
@@ -0,0 +1 @@
|
||||
usr/share/doc/osmo-sgsn-doc/*.pdf
|
||||
38
debian/postinst
vendored
Executable file
38
debian/postinst
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh -e
|
||||
case "$1" in
|
||||
configure)
|
||||
# Create the osmocom group and user (if it doesn't exist yet)
|
||||
if ! getent group osmocom >/dev/null; then
|
||||
groupadd --system osmocom
|
||||
fi
|
||||
if ! getent passwd osmocom >/dev/null; then
|
||||
useradd \
|
||||
--system \
|
||||
--gid osmocom \
|
||||
--home-dir /var/lib/osmocom \
|
||||
--shell /sbin/nologin \
|
||||
--comment "Open Source Mobile Communications" \
|
||||
osmocom
|
||||
fi
|
||||
|
||||
# Fix permissions of previous (root-owned) install (OS#4107)
|
||||
if dpkg --compare-versions "$2" le "1.12.0"; then
|
||||
if [ -e /etc/osmocom/osmo-sgsn.cfg ]; then
|
||||
chown -v osmocom:osmocom /etc/osmocom/osmo-sgsn.cfg
|
||||
chmod -v 0660 /etc/osmocom/osmo-sgsn.cfg
|
||||
fi
|
||||
|
||||
if [ -d /etc/osmocom ]; then
|
||||
chown -v root:osmocom /etc/osmocom
|
||||
chmod -v 2775 /etc/osmocom
|
||||
fi
|
||||
|
||||
mkdir -p /var/lib/osmocom
|
||||
chown -R -v osmocom:osmocom /var/lib/osmocom
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb(1) will replace this with shell code automatically
|
||||
# generated by other debhelper scripts.
|
||||
#DEBHELPER#
|
||||
7
debian/rules
vendored
7
debian/rules
vendored
@@ -46,7 +46,7 @@
|
||||
|
||||
# debmake generated override targets
|
||||
# Set options for ./configure
|
||||
CONFIGURE_FLAGS += --enable-iu --with-systemdsystemunitdir=/lib/systemd/system
|
||||
CONFIGURE_FLAGS += --enable-iu --with-systemdsystemunitdir=/lib/systemd/system --enable-manuals
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- $(CONFIGURE_FLAGS)
|
||||
#
|
||||
@@ -58,8 +58,11 @@ override_dh_auto_configure:
|
||||
override_dh_strip:
|
||||
dh_strip -posmo-sgsn --dbg-package=osmo-sgsn-dbg
|
||||
dh_strip -posmo-gtphub --dbg-package=osmo-gtphub-dbg
|
||||
dh_strip -posmo-gbproxy --dbg-package=osmo-gbproxy-dbg
|
||||
|
||||
# Print test results in case of a failure
|
||||
override_dh_auto_test:
|
||||
dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
|
||||
|
||||
# Don't create .pdf.gz files (barely saves space and they can't be opened directly by most pdf readers)
|
||||
override_dh_compress:
|
||||
dh_compress -X.pdf
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
OSMOCONF_FILES = \
|
||||
osmo-gtphub/osmo-gtphub.cfg \
|
||||
osmo-sgsn/osmo-sgsn.cfg \
|
||||
osmo-gbproxy/osmo-gbproxy.cfg
|
||||
$(NULL)
|
||||
|
||||
osmoconfdir = $(sysconfdir)/osmocom
|
||||
osmoconf_DATA = $(OSMOCONF_FILES)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
!
|
||||
! OsmoGbProxy (UNKNOWN) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging filter all 1
|
||||
logging color 1
|
||||
logging timestamp 0
|
||||
logging level all debug
|
||||
logging level gprs debug
|
||||
logging level ns info
|
||||
logging level bssgp debug
|
||||
logging level lglobal notice
|
||||
logging level llapd notice
|
||||
logging level linp notice
|
||||
logging level lmux notice
|
||||
logging level lmi notice
|
||||
logging level lmib notice
|
||||
logging level lsms notice
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
ns
|
||||
nse 666 nsvci 666
|
||||
nse 666 remote-role sgsn
|
||||
! nse 666 encapsulation framerelay-gre
|
||||
! nse 666 remote-ip 172.16.1.70
|
||||
! nse 666 fr-dlci 666
|
||||
timer tns-block 3
|
||||
timer tns-block-retries 3
|
||||
timer tns-reset 3
|
||||
timer tns-reset-retries 3
|
||||
timer tns-test 30
|
||||
timer tns-alive 3
|
||||
timer tns-alive-retries 10
|
||||
encapsulation udp local-port 23000
|
||||
! encapsulation framerelay-gre enabled 1
|
||||
gbproxy
|
||||
sgsn nsei 666
|
||||
core-mobile-country-code 666
|
||||
core-mobile-network-code 6
|
||||
core-access-point-name none match-imsi ^666066|^66607
|
||||
tlli-list max-length 200
|
||||
@@ -1,25 +0,0 @@
|
||||
!
|
||||
! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
gbproxy
|
||||
sgsn nsei 101
|
||||
ns
|
||||
nse 101 nsvci 101
|
||||
nse 101 remote-role sgsn
|
||||
nse 101 encapsulation udp
|
||||
nse 101 remote-ip 192.168.100.239
|
||||
nse 101 remote-port 7777
|
||||
timer tns-block 3
|
||||
timer tns-block-retries 3
|
||||
timer tns-reset 3
|
||||
timer tns-reset-retries 3
|
||||
timer tns-test 30
|
||||
timer tns-alive 3
|
||||
timer tns-alive-retries 10
|
||||
encapsulation framerelay-gre enabled 0
|
||||
encapsulation framerelay-gre local-ip 0.0.0.0
|
||||
encapsulation udp local-port 23000
|
||||
@@ -59,7 +59,7 @@ The LD_LIBRARY_PATH below may be needed if OpenGGSN installed to /usr/local.
|
||||
2. GTPHub:
|
||||
|
||||
cd <your-test-dir>
|
||||
path/to/openbsc/openbsc/src/gprs/osmo-gtphub -c gtphub.conf #-e 1 #for DEBUG level
|
||||
path/to/openbsc/openbsc/src/gtphub/osmo-gtphub -c gtphub.conf #-e 1 #for DEBUG level
|
||||
|
||||
3. SGSN tests:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -2,14 +2,22 @@
|
||||
! 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
|
||||
|
||||
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.1
|
||||
bind-to-ggsns 127.0.0.2
|
||||
bind-to-sgsns 127.0.0.10
|
||||
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
|
||||
|
||||
@@ -2,14 +2,24 @@
|
||||
! 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
|
||||
!
|
||||
sgsn
|
||||
gtp state-dir /var/lib/osmocom/osmo-sgsn
|
||||
gtp local-ip 127.0.0.1
|
||||
ggsn 0 remote-ip 127.0.0.2
|
||||
ggsn 0 gtp-version 1
|
||||
ggsn 0 echo-interval 60
|
||||
authentication optional
|
||||
auth-policy accept-all
|
||||
!
|
||||
ns
|
||||
@@ -20,9 +30,9 @@ ns
|
||||
timer tns-test 30
|
||||
timer tns-alive 3
|
||||
timer tns-alive-retries 10
|
||||
encapsulation udp local-ip 127.0.0.1
|
||||
encapsulation udp local-port 23000
|
||||
encapsulation framerelay-gre enabled 0
|
||||
bind udp local
|
||||
listen 127.0.0.1 23000
|
||||
accept-ipaccess
|
||||
!
|
||||
bssgp
|
||||
!
|
||||
|
||||
@@ -2,14 +2,24 @@
|
||||
! 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
|
||||
!
|
||||
sgsn
|
||||
gtp state-dir /var/lib/osmocom/osmo-sgsn
|
||||
gtp local-ip 127.0.0.1
|
||||
ggsn 0 remote-ip 127.0.0.2
|
||||
ggsn 0 gtp-version 1
|
||||
ggsn 0 echo-interval 60
|
||||
authentication required
|
||||
auth-policy remote
|
||||
gsup remote-ip 127.0.0.1
|
||||
gsup remote-port 4222
|
||||
@@ -22,9 +32,9 @@ ns
|
||||
timer tns-test 30
|
||||
timer tns-alive 3
|
||||
timer tns-alive-retries 10
|
||||
encapsulation udp local-ip 127.0.0.1
|
||||
encapsulation udp local-port 23000
|
||||
encapsulation framerelay-gre enabled 0
|
||||
bind udp local
|
||||
listen 127.0.0.1 23000
|
||||
accept-ipaccess
|
||||
!
|
||||
bssgp
|
||||
!
|
||||
|
||||
50
doc/examples/osmo-sgsn/osmo-sgsn_custom-sccp.cfg
Normal file
50
doc/examples/osmo-sgsn/osmo-sgsn_custom-sccp.cfg
Normal file
@@ -0,0 +1,50 @@
|
||||
!
|
||||
! 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
|
||||
!
|
||||
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
|
||||
sgsn
|
||||
gtp state-dir /var/lib/osmocom/osmo-sgsn
|
||||
gtp local-ip 127.0.0.1
|
||||
ggsn 0 remote-ip 127.0.0.2
|
||||
ggsn 0 gtp-version 1
|
||||
ggsn 0 echo-interval 60
|
||||
authentication required
|
||||
auth-policy remote
|
||||
gsup remote-ip 127.0.0.1
|
||||
gsup remote-port 4222
|
||||
cs7-instance-iu 0
|
||||
!
|
||||
ns
|
||||
timer tns-block 3
|
||||
timer tns-block-retries 3
|
||||
timer tns-reset 3
|
||||
timer tns-reset-retries 3
|
||||
timer tns-test 30
|
||||
timer tns-alive 3
|
||||
timer tns-alive-retries 10
|
||||
bind udp local
|
||||
listen 127.0.0.1 23000
|
||||
accept-ipaccess
|
||||
!
|
||||
bssgp
|
||||
!
|
||||
@@ -1,8 +1,10 @@
|
||||
EXTRA_DIST = osmosgsn-usermanual.adoc \
|
||||
osmosgsn-usermanual-docinfo.xml \
|
||||
osmosgsn-vty-reference.xml \
|
||||
regen_doc.sh \
|
||||
chapters \
|
||||
vty
|
||||
vty \
|
||||
$(NULL)
|
||||
|
||||
if BUILD_MANUALS
|
||||
ASCIIDOC = osmosgsn-usermanual.adoc
|
||||
@@ -10,7 +12,14 @@ if BUILD_MANUALS
|
||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
|
||||
|
||||
VTY_REFERENCE = osmosgsn-vty-reference.xml
|
||||
|
||||
BUILT_REFERENCE_XML = $(builddir)/vty/sgsn_vty_reference.xml
|
||||
$(builddir)/vty/sgsn_vty_reference.xml: $(top_builddir)/src/sgsn/osmo-sgsn
|
||||
mkdir -p $(builddir)/vty
|
||||
$(top_builddir)/src/sgsn/osmo-sgsn --vty-ref-xml > $@
|
||||
|
||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
|
||||
|
||||
OSMO_REPOSITORY = osmo-sgsn
|
||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
|
||||
endif
|
||||
|
||||
@@ -7,17 +7,18 @@ On the one hand, this is primary because the PCU configuration happens
|
||||
from the BSC side.
|
||||
|
||||
On the other hand, it is because the Gb interface does not need an
|
||||
explicit configuration of all each PCU connecting to the SGSN. The
|
||||
explicit configuration of each PCU connecting to the SGSN. The
|
||||
administrator only has to ensure that the NS and BSSGP layer identities
|
||||
(NSEI, NSVCI, BVCI) are unique for each PCU connecting to the SGSN.
|
||||
|
||||
=== Configuring the Gp interface
|
||||
[[gp-if-ggsn]]
|
||||
=== Configuring the Gp interface (towards GGSN)
|
||||
|
||||
The Gp interface is the GTP-C and GTP-U based interface between the SGSN
|
||||
and the GGSNs. It is implemented via UDP on well-known source and
|
||||
destination ports.
|
||||
|
||||
When a MS requests establishment of a PDP context, it specifies the APN
|
||||
When an MS requests establishment of a PDP context, it specifies the APN
|
||||
(Access Point Name) to which the context shall be established. This APN
|
||||
determines which GGSN shall be used, and that in turn determines which
|
||||
external IP network the MS will be connected to.
|
||||
@@ -67,6 +68,58 @@ OsmoSGSN(config-sgsn)# grx-dns-add 1.2.3.4 <3>
|
||||
<2> Enable the dynamic GGSN resolving mode
|
||||
<3> Specify the IP address of a DNS server for APN resolution
|
||||
|
||||
[[gp-if-mme]]
|
||||
=== Configuring the Gp interface (towards MME)
|
||||
|
||||
The Gp interface also contains the GTP-C v1 based interface between the SGSN
|
||||
and the MMEs. This interface between SGSN and MMEs is used to transfer _RAN
|
||||
Information Relay_ GTP-C messages between them, which are used as containers to
|
||||
allow PCUs under the SGSN and eNodeBs under MMEs to exchange cell information
|
||||
(RIM).
|
||||
|
||||
In the SGSN, this interface re-uses the same socket local configuration as per
|
||||
the GGSN connections (see _gtp local-ip_ VTY command in <<gp-if-ggsn>>).
|
||||
|
||||
Similarly as with GGSNs, (again see <<gp-if-ggsn>>), selection of destination
|
||||
peers for the _RAN Information Relay_ message can be configured statically or
|
||||
dynamically over GRX.
|
||||
|
||||
|
||||
==== Static MME/TAI configuration
|
||||
|
||||
In this mode, there is a static list of MMEs and TAIs configured in
|
||||
OsmoSGSN via the VTY / config file. One MME in the list can be configured as the
|
||||
_default route_, where all unspecified TAIs are routed too.
|
||||
|
||||
This is a non-standard method outside of the 3GPP specifications for the
|
||||
SGSN, and is typically only used in private/small GPRS networks without
|
||||
any access to a GRX.
|
||||
|
||||
.Example: Static MME/TAI configuration (single catch-all GGSN)
|
||||
----
|
||||
sgsn
|
||||
...
|
||||
gtp local-ip 192.168.0.10 <1>
|
||||
mme test-mme0 <2>
|
||||
gtp remote-ip 192.168.0.20 <3>
|
||||
gtp ran-info-relay 262 42 3 <4>
|
||||
gtp ran-info-relay 262 42 4
|
||||
mme test-mme1 <5>
|
||||
gtp remote-ip 192.168.0.30
|
||||
gtp ran-info-relay default <6>
|
||||
----
|
||||
<1> Configure the local IP address at the SGSN used for Gp/GTP
|
||||
<2> Configure an MME named "test-mme0"
|
||||
<3> Specify the remote IP address of the MME (for MME "test-mme0")
|
||||
<4> Route specified TAIs towards this MME
|
||||
<5> Configure an MME named "test-mme1"
|
||||
<6> Route all TAIs with an unspecified MME towards MM "test-mme1"
|
||||
|
||||
==== Dynamic MME/TAI configuration
|
||||
|
||||
Dynamic MME/TAI peer look up over GRX is not yet supported by OsmoSGSN.
|
||||
|
||||
|
||||
[[auth-pol]]
|
||||
=== Authorization Policy
|
||||
|
||||
@@ -100,7 +153,7 @@ NOTE: The policy mode *closed* must not be confused with the equally named
|
||||
policy that is defined for osmo-nitb!
|
||||
|
||||
|
||||
.Example: Assign or change authorization policy:
|
||||
.Example: Assign or change authorization policy
|
||||
----
|
||||
OsmoSGSN> enable
|
||||
OsmoSGSN# configure terminal
|
||||
@@ -116,7 +169,7 @@ OsmoSGSN>
|
||||
<2> Saves current changes to cofiguration to make this policy
|
||||
persistent
|
||||
|
||||
.Example: Access control list:
|
||||
.Example: Access control list
|
||||
----
|
||||
sgsn
|
||||
auth-policy acl-only <1>
|
||||
@@ -153,7 +206,7 @@ simplified by use of a binary TLV encoding similar to Layer 3 of
|
||||
GSM/GPRS.
|
||||
|
||||
GSUP performs a challenge-response authentication protocol called OAP,
|
||||
which uses the standard MILEAGE algorithm for mutual authentication
|
||||
which uses the standard MILENAGE algorithm for mutual authentication
|
||||
between OsmoSGSN and the HLR/HLR-GW.
|
||||
|
||||
[[sgsn-ex-gsup]]
|
||||
@@ -251,9 +304,8 @@ _pdp-_), then the following extra CSV fields are appended to the line:
|
||||
|
||||
=== User traffic compression
|
||||
|
||||
In order to save optimize GPRS bandwith, OsmoSGSN implements header and data
|
||||
compression schemes. The compression will reduce the packet length in order
|
||||
to save radio bandwith.
|
||||
In order to save GPRS bandwith, OsmoSGSN implements header and data
|
||||
compression schemes which will reduce the packet length.
|
||||
|
||||
==== Header compression
|
||||
|
||||
@@ -278,18 +330,24 @@ actively request different compression parameters or reject the offered
|
||||
compression parameters entirely. The number of slots is the maximum number
|
||||
of packet headers per subscriber that can be stored in the codebook.
|
||||
|
||||
.Example: Accept compression if requested:
|
||||
.Example: Accept compression if requested
|
||||
----
|
||||
sgsn
|
||||
compression rfc1144 passive
|
||||
----
|
||||
|
||||
.Example: Actively promote compression:
|
||||
.Example: Actively promote compression
|
||||
----
|
||||
sgsn
|
||||
compression rfc1144 active slots 8
|
||||
----
|
||||
|
||||
.Example: Turn off compression
|
||||
----
|
||||
sgsn
|
||||
no compression rfc1144
|
||||
----
|
||||
|
||||
NOTE: The usage of TCP/IP options may disturb the RFC1144 header compression
|
||||
scheme. TCP/IP options may render RFC1144 ineffective if variable data is
|
||||
encoded into the option section of the TCP/IP packet. (e.g. TCP option 8,
|
||||
@@ -299,10 +357,10 @@ Timestamp)
|
||||
==== Data compression
|
||||
|
||||
Data compression works on the raw packet data, including the header part of the
|
||||
packet. If enabled, header compression is applied before first data compression
|
||||
packet. If enabled, header compression is applied first before data compression
|
||||
is applied. OsmoSGSN implements the V.42bis data compression scheme.
|
||||
|
||||
*compression rfc1144 passive*::
|
||||
*compression v42bis passive*::
|
||||
V42bis data compression has to be actively requested by the modem. The network
|
||||
will not promote compression by itself. This is the recommended mode of
|
||||
operation.
|
||||
@@ -316,14 +374,59 @@ directions will be the preferred option. The following to parameters configure
|
||||
the codebook size by the maxium number ('codewords') and size ('strlen') of
|
||||
entries.
|
||||
|
||||
.Example: Accept compression if requested:
|
||||
.Example: Accept compression if requested
|
||||
----
|
||||
sgsn
|
||||
compression v42bis passive
|
||||
----
|
||||
|
||||
.Example: Actively promote compression:
|
||||
.Example: Actively promote compression
|
||||
----
|
||||
sgsn
|
||||
compression v42bis active direction both codewords 512 strlen 20
|
||||
----
|
||||
|
||||
.Example: Turn off compression
|
||||
----
|
||||
sgsn
|
||||
no compression v42bis
|
||||
----
|
||||
|
||||
=== Encryption
|
||||
|
||||
Encryption can be enabled if the auth-policy is set to remote and the
|
||||
HLR subscriber entries contain the keys of the SIM card. See
|
||||
<<sgsn-ex-gsup>> on how to connect to an external HLR.
|
||||
|
||||
.Example: Turn on encryption (GEA3 and GEA4)
|
||||
----
|
||||
sgsn
|
||||
encryption gea 3 4
|
||||
----
|
||||
|
||||
.Example: Turn off encryption (GEA0)
|
||||
----
|
||||
sgsn
|
||||
encryption gea 0
|
||||
----
|
||||
|
||||
=== Configure SCCP/M3UA to accept _IuPS_ links
|
||||
|
||||
OsmoSGSN acts as client to contact an STP instance and establish an SCCP/M3UA
|
||||
link.
|
||||
|
||||
An example configuration of OsmoSGSN's SCCP link:
|
||||
|
||||
----
|
||||
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
|
||||
routing-key 0 0.23.4
|
||||
----
|
||||
|
||||
This configuration is explained in detail in <<cs7_config>>.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
|
||||
// autogenerated by show asciidoc counters
|
||||
These counters and their description based on OsmoSGSN UNKNOWN (OsmoSGSN).
|
||||
These counters and their description based on OsmoSGSN 1.4.0.31-05fe (OsmoSGSN).
|
||||
|
||||
=== Rate Counters
|
||||
|
||||
// generating tables for rate_ctr_group
|
||||
// rate_ctr_group table BSSGP Peer Statistics
|
||||
@@ -15,46 +18,15 @@ These counters and their description based on OsmoSGSN UNKNOWN (OsmoSGSN).
|
||||
| discarded | <<bssgp:bss_ctx_discarded>> | BVC LLC Discarded count
|
||||
| status | <<bssgp:bss_ctx_status>> | BVC Status count
|
||||
|===
|
||||
// rate_ctr_group table BSSGP Peer Statistics
|
||||
.bssgp:bss_ctx - BSSGP Peer Statistics
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
| packets:in | <<bssgp:bss_ctx_packets:in>> | Packets at BSSGP Level ( In)
|
||||
| packets:out | <<bssgp:bss_ctx_packets:out>> | Packets at BSSGP Level (Out)
|
||||
| bytes:in | <<bssgp:bss_ctx_bytes:in>> | Bytes at BSSGP Level ( In)
|
||||
| bytes:out | <<bssgp:bss_ctx_bytes:out>> | Bytes at BSSGP Level (Out)
|
||||
| blocked | <<bssgp:bss_ctx_blocked>> | BVC Blocking count
|
||||
| discarded | <<bssgp:bss_ctx_discarded>> | BVC LLC Discarded count
|
||||
| status | <<bssgp:bss_ctx_status>> | BVC Status count
|
||||
|===
|
||||
// rate_ctr_group table NSVC Peer Statistics
|
||||
.ns:nsvc - NSVC Peer Statistics
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
| packets:in | <<ns:nsvc_packets:in>> | Packets at NS Level ( In)
|
||||
| packets:out | <<ns:nsvc_packets:out>> | Packets at NS Level (Out)
|
||||
| bytes:in | <<ns:nsvc_bytes:in>> | Bytes at NS Level ( In)
|
||||
| bytes:out | <<ns:nsvc_bytes:out>> | Bytes at NS Level (Out)
|
||||
| blocked | <<ns:nsvc_blocked>> | NS-VC Block count
|
||||
| dead | <<ns:nsvc_dead>> | NS-VC gone dead count
|
||||
| replaced | <<ns:nsvc_replaced>> | NS-VC replaced other count
|
||||
| nsei-chg | <<ns:nsvc_nsei-chg>> | NS-VC changed NSEI count
|
||||
| inv-nsvci | <<ns:nsvc_inv-nsvci>> | NS-VCI was invalid count
|
||||
| inv-nsei | <<ns:nsvc_inv-nsei>> | NSEI was invalid count
|
||||
| lost:alive | <<ns:nsvc_lost:alive>> | ALIVE ACK missing count
|
||||
| lost:reset | <<ns:nsvc_lost:reset>> | RESET ACK missing count
|
||||
|===
|
||||
// rate_ctr_group table SGSN Overall Statistics
|
||||
.sgsn - SGSN Overall Statistics
|
||||
.sgsn - SGSN Overall Statistics
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
| llc:dl_bytes | <<sgsn_llc:dl_bytes>> | Count sent LLC bytes before giving it to the bssgp layer
|
||||
| llc:ul_bytes | <<sgsn_llc:ul_bytes>> | Count sucessful received LLC bytes (encrypt & fcs correct)
|
||||
| llc:dl_packets | <<sgsn_llc:dl_packets>> | Count sucessful sent LLC packets before giving it to the bssgp layer
|
||||
| llc:ul_packets | <<sgsn_llc:ul_packets>> | Count sucessful received LLC packets (encrypt & fcs correct)
|
||||
| llc:ul_bytes | <<sgsn_llc:ul_bytes>> | Count successful received LLC bytes (encrypt & fcs correct)
|
||||
| llc:dl_packets | <<sgsn_llc:dl_packets>> | Count successful sent LLC packets before giving it to the bssgp layer
|
||||
| llc:ul_packets | <<sgsn_llc:ul_packets>> | Count successful received LLC packets (encrypt & fcs correct)
|
||||
| gprs:attach_requested | <<sgsn_gprs:attach_requested>> | Received attach requests
|
||||
| gprs:attach_accepted | <<sgsn_gprs:attach_accepted>> | Sent attach accepts
|
||||
| gprs:attach_rejected | <<sgsn_gprs:attach_rejected>> | Sent attach rejects
|
||||
@@ -76,7 +48,7 @@ These counters and their description based on OsmoSGSN UNKNOWN (OsmoSGSN).
|
||||
| pdp:ul_deactivate_accepted | <<sgsn_pdp:ul_deactivate_accepted>> | Received deactivate accepts
|
||||
|===
|
||||
// rate_ctr_group table NSVC Peer Statistics
|
||||
.ns:nsvc - NSVC Peer Statistics
|
||||
.ns:nsvc - NSVC Peer Statistics
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
@@ -84,38 +56,27 @@ These counters and their description based on OsmoSGSN UNKNOWN (OsmoSGSN).
|
||||
| packets:out | <<ns:nsvc_packets:out>> | Packets at NS Level (Out)
|
||||
| bytes:in | <<ns:nsvc_bytes:in>> | Bytes at NS Level ( In)
|
||||
| bytes:out | <<ns:nsvc_bytes:out>> | Bytes at NS Level (Out)
|
||||
| blocked | <<ns:nsvc_blocked>> | NS-VC Block count
|
||||
| dead | <<ns:nsvc_dead>> | NS-VC gone dead count
|
||||
| blocked | <<ns:nsvc_blocked>> | NS-VC Block count
|
||||
| dead | <<ns:nsvc_dead>> | NS-VC gone dead count
|
||||
| replaced | <<ns:nsvc_replaced>> | NS-VC replaced other count
|
||||
| nsei-chg | <<ns:nsvc_nsei-chg>> | NS-VC changed NSEI count
|
||||
| inv-nsvci | <<ns:nsvc_inv-nsvci>> | NS-VCI was invalid count
|
||||
| inv-nsei | <<ns:nsvc_inv-nsei>> | NSEI was invalid count
|
||||
| lost:alive | <<ns:nsvc_lost:alive>> | ALIVE ACK missing count
|
||||
| lost:reset | <<ns:nsvc_lost:reset>> | RESET ACK missing count
|
||||
| nsei-chg | <<ns:nsvc_nsei-chg>> | NS-VC changed NSEI count
|
||||
| inv-nsvci | <<ns:nsvc_inv-nsvci>> | NS-VCI was invalid count
|
||||
| inv-nsei | <<ns:nsvc_inv-nsei>> | NSEI was invalid count
|
||||
| lost:alive | <<ns:nsvc_lost:alive>> | ALIVE ACK missing count
|
||||
| lost:reset | <<ns:nsvc_lost:reset>> | RESET ACK missing count
|
||||
|===
|
||||
== Osmo Stat Items
|
||||
|
||||
// generating tables for osmo_stat_items
|
||||
NSVC Peer Statistics
|
||||
// osmo_stat_item_group table NSVC Peer Statistics
|
||||
.ns.nsvc - NSVC Peer Statistics
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description | Unit
|
||||
| alive.delay | <<ns.nsvc_alive.delay>> | ALIVE response time | ms
|
||||
|===
|
||||
NSVC Peer Statistics
|
||||
// osmo_stat_item_group table NSVC Peer Statistics
|
||||
.ns.nsvc - NSVC Peer Statistics
|
||||
.ns.nsvc - NSVC Peer Statistics
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description | Unit
|
||||
| alive.delay | <<ns.nsvc_alive.delay>> | ALIVE response time | ms
|
||||
|===
|
||||
== Osmo Counters
|
||||
|
||||
// generating tables for osmo_counters
|
||||
// ungrouped osmo_counters
|
||||
.ungrouped osmo counters
|
||||
[options="header"]
|
||||
|===
|
||||
| Name | Reference | Description
|
||||
|===
|
||||
|
||||
|
||||
// there are no ungrouped osmo_counters
|
||||
|
||||
@@ -74,14 +74,13 @@ The LLC (Logical Link Control) implementation of OsmoSGSN only supports
|
||||
non-acknowledged mode, as this is the most common use case in real-world
|
||||
GPRS networks.
|
||||
|
||||
Furthermore, it does not support IP header nor payload compression at
|
||||
this point. Addition of those features is subject to customer demand or
|
||||
user/customer contributions.
|
||||
|
||||
The LLC implementation does support LLC encryption. However, as no HLR
|
||||
access is implemented yet, there is no way to enable/configure
|
||||
per-subscriber specific keys.
|
||||
It does support both TCP/IP header compression according to RFC1144 and
|
||||
payload compression according to V.42bis
|
||||
|
||||
The LLC implementation does support LLC encryption with ciphers GEA3 and GEA4.
|
||||
For encryption to work the auth policy needs to be set to remote and the SGSN
|
||||
connected to an HLR containing the subscriber data including key material.
|
||||
Other auth policys will not work with encryption.
|
||||
|
||||
==== Session Management Implementation
|
||||
|
||||
@@ -93,11 +92,8 @@ networks while skipping the more esoteric features.
|
||||
|
||||
Multiple PDP contexts can be attached by a single MS.
|
||||
|
||||
Currently, all PDP contexts are routed to the same GGSN, irrespective of
|
||||
the APN used/configured in the MS. This is sufficient (and actually
|
||||
desirable) for small autonomous networks, but of course not suitable for
|
||||
real networks in roaming scenarios. Please contact sysmocom in case you
|
||||
require additional features such as DNS-based APN resolving.
|
||||
Multiple GGSNs can be configured and routing to a GGSN can be configured based
|
||||
on APN. Dynamic lookup of GGSNs though DNS-based APN resolving is also possible.
|
||||
|
||||
=== Limitations
|
||||
|
||||
@@ -109,10 +105,5 @@ performing that work.
|
||||
|
||||
Known Limitations include:
|
||||
|
||||
* No LLC encryption support
|
||||
* No interface to the OsmoNITB HLR
|
||||
* No paging coordination between SGSN and MSC
|
||||
* No SMS over Ps support
|
||||
* No IuPS interface for 3G (in progress)
|
||||
* No IP header compression
|
||||
* No payload compression
|
||||
|
||||
@@ -14,7 +14,7 @@ options:
|
||||
*-h, --help*::
|
||||
Print a short help message about the supported options
|
||||
*-V, --version*::
|
||||
Print the compile-time version number of the OsmoBTS program
|
||||
Print the compile-time version number of the OsmoSGSN program
|
||||
*-d, --debug 'DBGMASK','DBGLEVELS'*::
|
||||
Set the log subsystems and levels for logging to stderr. This
|
||||
has mostly been superseded by VTY-based logging configuration,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -19,7 +19,9 @@ include::./common/chapters/logging.adoc[]
|
||||
|
||||
include::{srcdir}/chapters/configuration.adoc[]
|
||||
|
||||
include::./common/chapters/gb.adoc[]
|
||||
include::./common/chapters/cs7-config.adoc[]
|
||||
|
||||
include::./common/chapters/gb-ns2.adoc[]
|
||||
|
||||
include::./common/chapters/control_if.adoc[]
|
||||
|
||||
|
||||
17
doc/manuals/regen_doc.sh
Executable file
17
doc/manuals/regen_doc.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
if [ -z "$DOCKER_PLAYGROUND" ]; then
|
||||
echo "You need to set DOCKER_PLAYGROUND"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPT=$(realpath "$0")
|
||||
MANUAL_DIR=$(dirname "$SCRIPT")
|
||||
|
||||
COMMIT=${COMMIT:-$(git log -1 --format=format:%H)}
|
||||
|
||||
cd "$DOCKER_PLAYGROUND/scripts" || exit 1
|
||||
|
||||
OSMO_BSC_BRANCH=$COMMIT ./regen_doc.sh osmo-sgsn 4245 \
|
||||
"$MANUAL_DIR/chapters/counters_generated.adoc" \
|
||||
"$MANUAL_DIR/vty/sgsn_vty_reference.xml"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
SUBDIRS = \
|
||||
gtphub \
|
||||
sgsn \
|
||||
$(NULL)
|
||||
|
||||
3
include/osmocom/gtphub/Makefile.am
Normal file
3
include/osmocom/gtphub/Makefile.am
Normal file
@@ -0,0 +1,3 @@
|
||||
noinst_HEADERS = \
|
||||
gtphub.h \
|
||||
$(NULL)
|
||||
@@ -27,22 +27,20 @@
|
||||
#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 */
|
||||
|
||||
/* TODO move to osmocom/core/socket.c ? */
|
||||
#include <netdb.h> /* for IPPROTO_* etc */
|
||||
struct osmo_sockaddr {
|
||||
struct sgsn_sockaddr {
|
||||
struct sockaddr_storage a;
|
||||
socklen_t l;
|
||||
};
|
||||
|
||||
/* TODO move to osmocom/core/socket.c ? */
|
||||
/*! \brief Initialize a sockaddr
|
||||
* \param[out] addr Valid osmo_sockaddr pointer to write result to
|
||||
* \param[out] addr Valid sgsn_sockaddr pointer to write result to
|
||||
* \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
|
||||
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
|
||||
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
|
||||
@@ -53,16 +51,16 @@ struct osmo_sockaddr {
|
||||
* Copy the first result from a getaddrinfo() call with the given parameters to
|
||||
* *addr and *addr_len. On error, do not change *addr and return nonzero.
|
||||
*/
|
||||
int osmo_sockaddr_init(struct osmo_sockaddr *addr,
|
||||
int sgsn_sockaddr_init(struct sgsn_sockaddr *addr,
|
||||
uint16_t family, uint16_t type, uint8_t proto,
|
||||
const char *host, uint16_t port);
|
||||
|
||||
/* Conveniently pass AF_UNSPEC, SOCK_DGRAM and IPPROTO_UDP to
|
||||
* osmo_sockaddr_init(). */
|
||||
static inline int osmo_sockaddr_init_udp(struct osmo_sockaddr *addr,
|
||||
* sgsn_sockaddr_init(). */
|
||||
static inline int sgsn_sockaddr_init_udp(struct sgsn_sockaddr *addr,
|
||||
const char *host, uint16_t port)
|
||||
{
|
||||
return osmo_sockaddr_init(addr, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
|
||||
return sgsn_sockaddr_init(addr, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
|
||||
host, port);
|
||||
}
|
||||
|
||||
@@ -71,25 +69,25 @@ static inline int osmo_sockaddr_init_udp(struct osmo_sockaddr *addr,
|
||||
* \param[in] addr_str_len Size of buffer addr_str points at.
|
||||
* \param[out] port_str Valid pointer to a buffer of length port_str_len.
|
||||
* \param[in] port_str_len Size of buffer port_str points at.
|
||||
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
|
||||
* \param[in] addr Binary representation as returned by sgsn_sockaddr_init().
|
||||
* \param[in] flags flags as passed to getnameinfo().
|
||||
* \returns 0 on success, an error code on error.
|
||||
*
|
||||
* Return the IPv4 or IPv6 address string and the port (a.k.a. service) string
|
||||
* representations of the given struct osmo_sockaddr in two caller provided
|
||||
* representations of the given struct sgsn_sockaddr in two caller provided
|
||||
* char buffers. Flags of (NI_NUMERICHOST | NI_NUMERICSERV) return numeric
|
||||
* address and port. Either one of addr_str or port_str may be NULL, in which
|
||||
* case nothing is returned there.
|
||||
*
|
||||
* See also osmo_sockaddr_to_str() (less flexible, but much more convenient). */
|
||||
int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
|
||||
* See also sgsn_sockaddr_to_str() (less flexible, but much more convenient). */
|
||||
int sgsn_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
|
||||
char *port_str, size_t port_str_len,
|
||||
const struct osmo_sockaddr *addr,
|
||||
const struct sgsn_sockaddr *addr,
|
||||
int flags);
|
||||
|
||||
|
||||
/*! \brief concatenate the parts returned by osmo_sockaddr_to_strs().
|
||||
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
|
||||
/*! \brief concatenate the parts returned by sgsn_sockaddr_to_strs().
|
||||
* \param[in] addr Binary representation as returned by sgsn_sockaddr_init().
|
||||
* \param[in] buf A buffer to use for string operations.
|
||||
* \param[in] buf_len Length of the buffer.
|
||||
* \returns Address string (in buffer).
|
||||
@@ -98,33 +96,33 @@ int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
|
||||
* the form "<ip-addr> port <port>". The returned string is valid until the
|
||||
* next invocation of this function.
|
||||
*/
|
||||
const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
|
||||
const char *sgsn_sockaddr_to_strb(const struct sgsn_sockaddr *addr,
|
||||
char *buf, size_t buf_len);
|
||||
|
||||
/*! \brief conveniently return osmo_sockaddr_to_strb() in a static buffer.
|
||||
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
|
||||
/*! \brief conveniently return sgsn_sockaddr_to_strb() in a static buffer.
|
||||
* \param[in] addr Binary representation as returned by sgsn_sockaddr_init().
|
||||
* \returns Address string in static buffer.
|
||||
*
|
||||
* See osmo_sockaddr_to_strb().
|
||||
* See sgsn_sockaddr_to_strb().
|
||||
*
|
||||
* Note: only one osmo_sockaddr_to_str() call will work per print/log
|
||||
* statement. For two or more, use osmo_sockaddr_to_strb() with a separate
|
||||
* Note: only one sgsn_sockaddr_to_str() call will work per print/log
|
||||
* statement. For two or more, use sgsn_sockaddr_to_strb() with a separate
|
||||
* buffer each.
|
||||
*/
|
||||
const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr);
|
||||
const char *sgsn_sockaddr_to_str(const struct sgsn_sockaddr *addr);
|
||||
|
||||
/*! \brief compare two osmo_sockaddr.
|
||||
/*! \brief compare two sgsn_sockaddr.
|
||||
* \param[in] a The first address to compare.
|
||||
* \param[in] b The other address to compare.
|
||||
* \returns 0 if equal, otherwise -1 or 1.
|
||||
*/
|
||||
int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
|
||||
const struct osmo_sockaddr *b);
|
||||
int sgsn_sockaddr_cmp(const struct sgsn_sockaddr *a,
|
||||
const struct sgsn_sockaddr *b);
|
||||
|
||||
/*! \brief Overwrite *dst with *src.
|
||||
* Like memcpy(), but copy only the valid bytes. */
|
||||
void osmo_sockaddr_copy(struct osmo_sockaddr *dst,
|
||||
const struct osmo_sockaddr *src);
|
||||
void sgsn_sockaddr_copy(struct sgsn_sockaddr *dst,
|
||||
const struct sgsn_sockaddr *src);
|
||||
|
||||
|
||||
/* general */
|
||||
@@ -179,7 +177,7 @@ int gsn_addr_same(const struct gsn_addr *a, const struct gsn_addr *b);
|
||||
/* Decode sa to gsna. Return 0 on success. If port is non-NULL, the port number
|
||||
* from sa is also returned. */
|
||||
int gsn_addr_from_sockaddr(struct gsn_addr *gsna, uint16_t *port,
|
||||
const struct osmo_sockaddr *sa);
|
||||
const struct sgsn_sockaddr *sa);
|
||||
|
||||
/* expiry */
|
||||
|
||||
@@ -389,7 +387,7 @@ struct gtphub_peer_port {
|
||||
struct gtphub_peer_addr *peer_addr;
|
||||
uint16_t port;
|
||||
unsigned int ref_count; /* references from other peers' seq_maps */
|
||||
struct osmo_sockaddr sa; /* a "cache" for (peer_addr->addr, port) */
|
||||
struct sgsn_sockaddr sa; /* a "cache" for (peer_addr->addr, port) */
|
||||
int last_restart_count; /* 0..255 = valid, all else means unknown */
|
||||
|
||||
struct rate_ctr_group *counters_io;
|
||||
@@ -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;
|
||||
@@ -496,13 +494,13 @@ int gtphub_tunnel_complete(struct gtphub_tunnel *tun);
|
||||
int gtphub_handle_buf(struct gtphub *hub,
|
||||
unsigned int side_idx,
|
||||
unsigned int port_idx,
|
||||
const struct osmo_sockaddr *from_addr,
|
||||
const struct sgsn_sockaddr *from_addr,
|
||||
uint8_t *buf,
|
||||
size_t received,
|
||||
time_t now,
|
||||
uint8_t **reply_buf,
|
||||
struct osmo_fd **to_ofd,
|
||||
struct osmo_sockaddr *to_addr);
|
||||
struct sgsn_sockaddr *to_addr);
|
||||
|
||||
struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
|
||||
struct gtphub_bind *bind,
|
||||
@@ -510,7 +508,7 @@ struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
|
||||
uint16_t port);
|
||||
|
||||
struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind,
|
||||
const struct osmo_sockaddr *addr);
|
||||
const struct sgsn_sockaddr *addr);
|
||||
|
||||
void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str,
|
||||
struct gsn_addr *resolved_addr,
|
||||
@@ -519,5 +517,5 @@ void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str,
|
||||
const char *gtphub_port_str(struct gtphub_peer_port *port);
|
||||
|
||||
int gtphub_write(const struct osmo_fd *to,
|
||||
const struct osmo_sockaddr *to_addr,
|
||||
const struct sgsn_sockaddr *to_addr,
|
||||
const uint8_t *buf, size_t buf_len);
|
||||
@@ -1,14 +1,22 @@
|
||||
noinst_HEADERS = \
|
||||
apn.h \
|
||||
auth.h \
|
||||
common.h \
|
||||
crc24.h \
|
||||
debug.h \
|
||||
gb_proxy.h \
|
||||
gprs_gb_parse.h \
|
||||
gprs_bssgp.h \
|
||||
gprs_gmm.h \
|
||||
gprs_gmm_fsm.h \
|
||||
gprs_gmm_attach.h \
|
||||
gprs_gmm_util.h \
|
||||
gprs_mm_state_gb_fsm.h \
|
||||
gprs_mm_state_iu_fsm.h \
|
||||
gprs_ns.h \
|
||||
gprs_llc.h \
|
||||
gprs_llc_xid.h \
|
||||
gprs_sgsn.h \
|
||||
gprs_ranap.h \
|
||||
gprs_routing_area.h \
|
||||
gprs_sm.h \
|
||||
gprs_sndcp_comp.h \
|
||||
gprs_sndcp_dcomp.h \
|
||||
gprs_sndcp.h \
|
||||
@@ -16,8 +24,17 @@ noinst_HEADERS = \
|
||||
gprs_sndcp_xid.h \
|
||||
gprs_subscriber.h \
|
||||
gprs_utils.h \
|
||||
gtphub.h \
|
||||
gtp.h \
|
||||
gtp_ggsn.h \
|
||||
gtp_mme.h \
|
||||
iu_client.h \
|
||||
iu_rnc.h \
|
||||
iu_rnc_fsm.h \
|
||||
mmctx.h \
|
||||
pdpctx.h \
|
||||
sccp.h \
|
||||
sgsn.h \
|
||||
sgsn_rim.h \
|
||||
signal.h \
|
||||
slhc.h \
|
||||
v42bis.h \
|
||||
|
||||
20
include/osmocom/sgsn/apn.h
Normal file
20
include/osmocom/sgsn/apn.h
Normal 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);
|
||||
39
include/osmocom/sgsn/auth.h
Normal file
39
include/osmocom/sgsn/auth.h
Normal 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);
|
||||
@@ -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
|
||||
|
||||
@@ -8,37 +8,25 @@
|
||||
|
||||
/* Debug Areas of the code */
|
||||
enum {
|
||||
DRLL,
|
||||
DCC,
|
||||
DMM,
|
||||
DRR,
|
||||
DRSL,
|
||||
DNM,
|
||||
DMNCC,
|
||||
DPAG,
|
||||
DMEAS,
|
||||
DSCCP,
|
||||
DMSC,
|
||||
DHO,
|
||||
DDB,
|
||||
DREF,
|
||||
DGPRS,
|
||||
DNS,
|
||||
DBSSGP,
|
||||
DLLC,
|
||||
DSNDCP,
|
||||
DSLHC,
|
||||
DNAT,
|
||||
DCTRL,
|
||||
DFILTER,
|
||||
DGTPHUB,
|
||||
DRANAP,
|
||||
DSUA,
|
||||
DV42BIS,
|
||||
DPCU,
|
||||
DVLR,
|
||||
DIUCS,
|
||||
DSIGTRAN,
|
||||
DGTP,
|
||||
DOBJ,
|
||||
DRIM,
|
||||
DRA, /* Routing Area handling */
|
||||
Debug_LastEntry,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,300 +0,0 @@
|
||||
#ifndef _GB_PROXY_H
|
||||
#define _GB_PROXY_H
|
||||
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gsm/gsm23003.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
|
||||
#define GBPROXY_INIT_VU_GEN_TX 256
|
||||
|
||||
struct rate_ctr_group;
|
||||
struct gprs_gb_parse_context;
|
||||
struct tlv_parsed;
|
||||
|
||||
enum gbproxy_global_ctr {
|
||||
GBPROX_GLOB_CTR_INV_BVCI,
|
||||
GBPROX_GLOB_CTR_INV_LAI,
|
||||
GBPROX_GLOB_CTR_INV_RAI,
|
||||
GBPROX_GLOB_CTR_INV_NSEI,
|
||||
GBPROX_GLOB_CTR_PROTO_ERR_BSS,
|
||||
GBPROX_GLOB_CTR_PROTO_ERR_SGSN,
|
||||
GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS,
|
||||
GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN,
|
||||
GBPROX_GLOB_CTR_RESTART_RESET_SGSN,
|
||||
GBPROX_GLOB_CTR_TX_ERR_SGSN,
|
||||
GBPROX_GLOB_CTR_OTHER_ERR,
|
||||
GBPROX_GLOB_CTR_PATCH_PEER_ERR,
|
||||
};
|
||||
|
||||
enum gbproxy_peer_ctr {
|
||||
GBPROX_PEER_CTR_BLOCKED,
|
||||
GBPROX_PEER_CTR_UNBLOCKED,
|
||||
GBPROX_PEER_CTR_DROPPED,
|
||||
GBPROX_PEER_CTR_INV_NSEI,
|
||||
GBPROX_PEER_CTR_TX_ERR,
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_APN_PATCHED,
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_PATCH_CRYPT_ERR,
|
||||
GBPROX_PEER_CTR_PATCH_ERR,
|
||||
GBPROX_PEER_CTR_ATTACH_REQS,
|
||||
GBPROX_PEER_CTR_ATTACH_REJS,
|
||||
GBPROX_PEER_CTR_ATTACH_ACKS,
|
||||
GBPROX_PEER_CTR_ATTACH_COMPLS,
|
||||
GBPROX_PEER_CTR_RA_UPD_REQS,
|
||||
GBPROX_PEER_CTR_RA_UPD_REJS,
|
||||
GBPROX_PEER_CTR_RA_UPD_ACKS,
|
||||
GBPROX_PEER_CTR_RA_UPD_COMPLS,
|
||||
GBPROX_PEER_CTR_GMM_STATUS_BSS,
|
||||
GBPROX_PEER_CTR_GMM_STATUS_SGSN,
|
||||
GBPROX_PEER_CTR_DETACH_REQS,
|
||||
GBPROX_PEER_CTR_DETACH_ACKS,
|
||||
GBPROX_PEER_CTR_PDP_ACT_REQS,
|
||||
GBPROX_PEER_CTR_PDP_ACT_REJS,
|
||||
GBPROX_PEER_CTR_PDP_ACT_ACKS,
|
||||
GBPROX_PEER_CTR_PDP_DEACT_REQS,
|
||||
GBPROX_PEER_CTR_PDP_DEACT_ACKS,
|
||||
GBPROX_PEER_CTR_TLLI_UNKNOWN,
|
||||
GBPROX_PEER_CTR_TLLI_CACHE_SIZE,
|
||||
GBPROX_PEER_CTR_LAST,
|
||||
};
|
||||
|
||||
enum gbproxy_keep_mode {
|
||||
GBPROX_KEEP_NEVER,
|
||||
GBPROX_KEEP_REATTACH,
|
||||
GBPROX_KEEP_IDENTIFIED,
|
||||
GBPROX_KEEP_ALWAYS,
|
||||
};
|
||||
|
||||
enum gbproxy_match_id {
|
||||
GBPROX_MATCH_PATCHING,
|
||||
GBPROX_MATCH_ROUTING,
|
||||
GBPROX_MATCH_LAST
|
||||
};
|
||||
|
||||
struct gbproxy_match {
|
||||
int enable;
|
||||
char *re_str;
|
||||
regex_t re_comp;
|
||||
};
|
||||
|
||||
struct gbproxy_config {
|
||||
/* parsed from config file */
|
||||
uint16_t nsip_sgsn_nsei;
|
||||
|
||||
/* misc */
|
||||
struct gprs_ns_inst *nsi;
|
||||
|
||||
/* Linked list of all Gb peers (except SGSN) */
|
||||
struct llist_head bts_peers;
|
||||
|
||||
/* Counter */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
/* force mcc/mnc */
|
||||
struct osmo_plmn_id core_plmn;
|
||||
uint8_t* core_apn;
|
||||
size_t core_apn_size;
|
||||
/* Frequency (sec) at which timer to clean stale links is fired (0 disabled) */
|
||||
unsigned int clean_stale_timer_freq;
|
||||
/* If !0, Max age to consider a struct gbproxy_link_info as stale */
|
||||
int tlli_max_age;
|
||||
/* If !0, Max len of gbproxy_peer->list (list of struct gbproxy_link_info) */
|
||||
int tlli_max_len;
|
||||
/* If !0, Max len of gbproxy_link_info->stored_msgs (list of msgb) */
|
||||
uint32_t stored_msgs_max_len;
|
||||
|
||||
/* Experimental config */
|
||||
int patch_ptmsi;
|
||||
int acquire_imsi;
|
||||
int route_to_sgsn2;
|
||||
uint16_t nsip_sgsn2_nsei;
|
||||
enum gbproxy_keep_mode keep_link_infos;
|
||||
|
||||
/* IMSI checking/matching */
|
||||
struct gbproxy_match matches[GBPROX_MATCH_LAST];
|
||||
};
|
||||
|
||||
struct gbproxy_patch_state {
|
||||
struct osmo_plmn_id local_plmn;
|
||||
|
||||
/* List of TLLIs for which patching is enabled */
|
||||
struct llist_head logical_links;
|
||||
int logical_link_count;
|
||||
};
|
||||
|
||||
struct gbproxy_peer {
|
||||
struct llist_head list;
|
||||
|
||||
/* point back to the config */
|
||||
struct gbproxy_config *cfg;
|
||||
|
||||
/* NSEI of the peer entity */
|
||||
uint16_t nsei;
|
||||
|
||||
/* BVCI used for Point-to-Point to this peer */
|
||||
uint16_t bvci;
|
||||
int blocked;
|
||||
|
||||
/* Routeing Area that this peer is part of (raw 04.08 encoding) */
|
||||
uint8_t ra[6];
|
||||
|
||||
/* Counter */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
struct gbproxy_patch_state patch_state;
|
||||
|
||||
/* Fired periodically to clean up stale links from list */
|
||||
struct osmo_timer_list clean_stale_timer;
|
||||
};
|
||||
|
||||
struct gbproxy_tlli_state {
|
||||
uint32_t current;
|
||||
uint32_t assigned;
|
||||
int bss_validated;
|
||||
int net_validated;
|
||||
|
||||
uint32_t ptmsi;
|
||||
};
|
||||
|
||||
struct gbproxy_link_info {
|
||||
struct llist_head list;
|
||||
|
||||
struct gbproxy_tlli_state tlli;
|
||||
struct gbproxy_tlli_state sgsn_tlli;
|
||||
uint32_t sgsn_nsei;
|
||||
|
||||
time_t timestamp;
|
||||
uint8_t *imsi;
|
||||
size_t imsi_len;
|
||||
|
||||
int imsi_acq_pending;
|
||||
struct llist_head stored_msgs;
|
||||
uint32_t stored_msgs_len;
|
||||
unsigned vu_gen_tx_bss;
|
||||
|
||||
int is_deregistered;
|
||||
|
||||
int is_matching[GBPROX_MATCH_LAST];
|
||||
};
|
||||
|
||||
|
||||
/* gb_proxy_vty .c */
|
||||
|
||||
int gbproxy_vty_init(void);
|
||||
int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg);
|
||||
|
||||
/* gb_proxy_ctrl.c */
|
||||
int gb_ctrl_cmds_install(void);
|
||||
|
||||
|
||||
/* gb_proxy.c */
|
||||
int gbproxy_init_config(struct gbproxy_config *cfg);
|
||||
|
||||
/* Main input function for Gb proxy */
|
||||
int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t nsvci);
|
||||
|
||||
int gbprox_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data);
|
||||
|
||||
/* Reset all persistent NS-VC's */
|
||||
int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
|
||||
|
||||
void gbprox_reset(struct gbproxy_config *cfg);
|
||||
|
||||
/* TLLI info handling */
|
||||
void gbproxy_delete_link_infos(struct gbproxy_peer *peer);
|
||||
struct gbproxy_link_info *gbproxy_update_link_state_ul(
|
||||
struct gbproxy_peer *peer, time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
struct gbproxy_link_info *gbproxy_update_link_state_dl(
|
||||
struct gbproxy_peer *peer, time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
int gbproxy_update_link_state_after(
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
|
||||
time_t now, struct gprs_gb_parse_context *parse_ctx);
|
||||
int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now);
|
||||
void gbproxy_delete_link_info(struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info);
|
||||
void gbproxy_link_info_discard_messages(struct gbproxy_link_info *link_info);
|
||||
|
||||
void gbproxy_attach_link_info(struct gbproxy_peer *peer, time_t now,
|
||||
struct gbproxy_link_info *link_info);
|
||||
void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
|
||||
const uint8_t *imsi, size_t imsi_len);
|
||||
void gbproxy_detach_link_info(struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info);
|
||||
struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_peer *peer);
|
||||
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_tlli(
|
||||
struct gbproxy_peer *peer, uint32_t tlli);
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_imsi(
|
||||
struct gbproxy_peer *peer, const uint8_t *imsi, size_t imsi_len);
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_any_sgsn_tlli(
|
||||
struct gbproxy_peer *peer, uint32_t tlli);
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_sgsn_tlli(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t tlli, uint32_t sgsn_nsei);
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_ptmsi(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t ptmsi);
|
||||
|
||||
int gbproxy_imsi_matches(
|
||||
struct gbproxy_config *cfg,
|
||||
enum gbproxy_match_id match_id,
|
||||
struct gbproxy_link_info *link_info);
|
||||
uint32_t gbproxy_map_tlli(
|
||||
uint32_t other_tlli, struct gbproxy_link_info *link_info, int to_bss);
|
||||
|
||||
/* needed by gb_proxy_tlli.h */
|
||||
uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer, uint32_t sgsn_ptmsi);
|
||||
uint32_t gbproxy_make_sgsn_tlli(
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
|
||||
uint32_t bss_tlli);
|
||||
void gbproxy_reset_link(struct gbproxy_link_info *link_info);
|
||||
int gbproxy_check_imsi(
|
||||
struct gbproxy_match *match, const uint8_t *imsi, size_t imsi_len);
|
||||
|
||||
/* Message patching */
|
||||
void gbproxy_patch_bssgp(
|
||||
struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
|
||||
int *len_change, struct gprs_gb_parse_context *parse_ctx);
|
||||
|
||||
int gbproxy_patch_llc(
|
||||
struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
|
||||
int *len_change, struct gprs_gb_parse_context *parse_ctx);
|
||||
|
||||
int gbproxy_set_patch_filter(
|
||||
struct gbproxy_match *match, const char *filter, const char **err_msg);
|
||||
void gbproxy_clear_patch_filter(struct gbproxy_match *match);
|
||||
|
||||
/* Peer handling */
|
||||
struct gbproxy_peer *gbproxy_peer_by_bvci(
|
||||
struct gbproxy_config *cfg, uint16_t bvci);
|
||||
struct gbproxy_peer *gbproxy_peer_by_nsei(
|
||||
struct gbproxy_config *cfg, uint16_t nsei);
|
||||
struct gbproxy_peer *gbproxy_peer_by_rai(
|
||||
struct gbproxy_config *cfg, const uint8_t *ra);
|
||||
struct gbproxy_peer *gbproxy_peer_by_lai(
|
||||
struct gbproxy_config *cfg, const uint8_t *la);
|
||||
struct gbproxy_peer *gbproxy_peer_by_lac(
|
||||
struct gbproxy_config *cfg, const uint8_t *la);
|
||||
struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(
|
||||
struct gbproxy_config *cfg, struct tlv_parsed *tp);
|
||||
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci);
|
||||
void gbproxy_peer_free(struct gbproxy_peer *peer);
|
||||
int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci);
|
||||
|
||||
#endif
|
||||
15
include/osmocom/sgsn/gprs_bssgp.h
Normal file
15
include/osmocom/sgsn/gprs_bssgp.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
struct osmo_prim_hdr;
|
||||
struct sgsn_mm_ctx;
|
||||
|
||||
/* 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 a single cell */
|
||||
int sgsn_bssgp_page_ps_bvci(struct sgsn_mm_ctx *mmctx, uint16_t nsei, uint16_t bvci);
|
||||
@@ -1,24 +1,27 @@
|
||||
#ifndef _GPRS_GMM_H
|
||||
#define _GPRS_GMM_H
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/crypt/auth.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
struct gprs_llc_llme;
|
||||
struct osmo_routing_area_id;
|
||||
|
||||
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,
|
||||
uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
|
||||
int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
|
||||
int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
|
||||
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);
|
||||
|
||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
|
||||
bool drop_cipherable);
|
||||
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id,
|
||||
uint16_t *sai);
|
||||
int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
|
||||
struct gprs_llc_llme *llme, bool drop_cipherable);
|
||||
int gsm48_gmm_sendmsg(struct msgb *msg, int command,
|
||||
struct sgsn_mm_ctx *mm, bool encryptable);
|
||||
int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx);
|
||||
int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
|
||||
struct gprs_llc_llme *llme);
|
||||
@@ -27,24 +30,33 @@ void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *mmctx, int gmm_cause);
|
||||
void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *mmctx, int gmm_cause);
|
||||
void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *mmctx);
|
||||
|
||||
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,
|
||||
int gprs_gmm_rx_suspend(struct osmo_routing_area_id *raid, uint32_t tlli);
|
||||
int gprs_gmm_rx_resume(struct osmo_routing_area_id *raid, uint32_t tlli,
|
||||
uint8_t suspend_ref);
|
||||
|
||||
time_t gprs_max_time_to_idle(void);
|
||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
|
||||
bool drop_cipherable);
|
||||
#ifdef BUILD_IU
|
||||
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id, uint16_t *sai);
|
||||
#endif /* ifdef BUILD_IU */
|
||||
|
||||
int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp);
|
||||
/* 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);
|
||||
int gsm48_tx_gmm_att_rej(struct sgsn_mm_ctx *mm,
|
||||
uint8_t gmm_cause);
|
||||
int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm);
|
||||
|
||||
int gprs_gmm_attach_req_ies(struct msgb *a, struct msgb *b);
|
||||
int gprs_gmm_msg_cmp(struct msgb *a, struct msgb *b);
|
||||
|
||||
int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx);
|
||||
/* TODO: move extract_subscr_* when gsm48_gmm_authorize() got removed */
|
||||
void extract_subscr_msisdn(struct sgsn_mm_ctx *ctx);
|
||||
void extract_subscr_hlr(struct sgsn_mm_ctx *ctx);
|
||||
|
||||
void pdp_ctx_detach_mm_ctx(struct sgsn_pdp_ctx *pdp);
|
||||
void msgid2mmctx(struct sgsn_mm_ctx *mm, const struct msgb *msg);
|
||||
void mmctx2msgid(struct msgb *msg, const struct sgsn_mm_ctx *mm);
|
||||
#endif /* _GPRS_GMM_H */
|
||||
|
||||
44
include/osmocom/sgsn/gprs_gmm_fsm.h
Normal file
44
include/osmocom/sgsn/gprs_gmm_fsm.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/fsm.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 {
|
||||
ST_GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
|
||||
ST_GMM_COMMON_PROC_INIT, /* 4.1.3.3.1.2 */
|
||||
ST_GMM_REGISTERED_NORMAL, /* 4.1.3.3.2.1 */
|
||||
ST_GMM_REGISTERED_SUSPENDED, /* 4.1.3.3.2.2 */
|
||||
ST_GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */
|
||||
};
|
||||
|
||||
enum gmm_fsm_events {
|
||||
E_GMM_COMMON_PROC_INIT_REQ,
|
||||
/* E_GMM_COMMON_PROC_FAILED, NOT USED */
|
||||
/* E_GMM_LOWER_LAYER_FAILED, NOT USED */
|
||||
E_GMM_COMMON_PROC_SUCCESS,
|
||||
E_GMM_ATTACH_SUCCESS,
|
||||
/* E_GMM_NET_INIT_DETACH_REQ, NOT USED */
|
||||
/* E_GMM_MS_INIT_DETACH_REQ, NOT USED */
|
||||
/* E_GMM_DETACH_ACCEPTED, */
|
||||
E_GMM_SUSPEND,
|
||||
E_GMM_RESUME,
|
||||
E_GMM_CLEANUP,
|
||||
E_GMM_RAT_CHANGE,
|
||||
};
|
||||
|
||||
struct gmm_rat_change_data {
|
||||
enum sgsn_ran_type new_ran_type;
|
||||
struct gprs_llc_llme *llme;
|
||||
};
|
||||
|
||||
static inline bool gmm_fsm_is_registered(struct osmo_fsm_inst *fi)
|
||||
{
|
||||
return fi->state == ST_GMM_REGISTERED_NORMAL ||
|
||||
fi->state == ST_GMM_REGISTERED_SUSPENDED;
|
||||
}
|
||||
|
||||
extern struct osmo_fsm gmm_fsm;
|
||||
42
include/osmocom/sgsn/gprs_gmm_util.h
Normal file
42
include/osmocom/sgsn/gprs_gmm_util.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/gsm/gsm23003.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
|
||||
struct msgb;
|
||||
|
||||
extern const struct tlv_definition gsm48_gmm_ie_tlvdef;
|
||||
|
||||
/* 9.4.14 RAU Request */
|
||||
struct gprs_gmm_ra_upd_req {
|
||||
uint8_t skip_ind; /* 10.3.1 */
|
||||
uint8_t update_type; /* 10.5.5.18 */
|
||||
bool follow_up_req; /* 10.5.5.18 */
|
||||
uint8_t cksq; /* 10.5.1.2 */
|
||||
struct osmo_routing_area_id old_rai; /* 10.5.5.15 */
|
||||
uint8_t *ms_radio_cap; /* 10.5.5.12a */
|
||||
uint8_t ms_radio_cap_len;
|
||||
struct tlv_parsed tlv;
|
||||
};
|
||||
|
||||
struct gprs_gmm_att_req {
|
||||
uint8_t skip_ind; /* 10.3.1 */
|
||||
uint8_t attach_type; /* 10.5.5.2 */
|
||||
bool follow_up_req; /* 10.5.5.2 */
|
||||
uint8_t cksq; /* 10.5.1.2 */
|
||||
uint16_t drx_parms; /* 10.5.5.6 */
|
||||
struct osmo_mobile_identity mi; /* 10.5.1.4 */
|
||||
struct osmo_routing_area_id old_rai; /* 10.5.5.15 */
|
||||
uint8_t *ms_network_cap; /* 10.5.5.12 */
|
||||
uint8_t ms_network_cap_len;
|
||||
uint8_t *ms_radio_cap; /* 10.5.5.12a */
|
||||
uint8_t ms_radio_cap_len;
|
||||
struct tlv_parsed tlv;
|
||||
};
|
||||
|
||||
int gprs_gmm_parse_ra_upd_req(const struct msgb *msg, struct gprs_gmm_ra_upd_req *rau_req);
|
||||
int gprs_gmm_parse_att_req(const struct msgb *msg, struct gprs_gmm_att_req *att_req);
|
||||
@@ -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,11 +96,13 @@ 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 */
|
||||
GPRS_LLMS_ASSIGNED = 2, /* TLLI assigned */
|
||||
};
|
||||
extern const struct value_string gprs_llc_llme_state_names[];
|
||||
|
||||
/* Section 8.9.9 LLC layer parameter default values */
|
||||
struct gprs_llc_params {
|
||||
@@ -110,13 +117,13 @@ struct gprs_llc_params {
|
||||
uint16_t kU;
|
||||
};
|
||||
|
||||
/* Section 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */
|
||||
/* 3GPP TS 44.064 § 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */
|
||||
struct gprs_llc_lle {
|
||||
struct llist_head list;
|
||||
|
||||
uint32_t sapi;
|
||||
|
||||
struct gprs_llc_llme *llme;
|
||||
struct gprs_llc_llme *llme; /* backpointer to the Logical Link Management Entity */
|
||||
|
||||
enum gprs_llc_lle_state state;
|
||||
|
||||
@@ -145,10 +152,18 @@ struct gprs_llc_lle {
|
||||
unsigned int retrans_ctr;
|
||||
|
||||
struct gprs_llc_params params;
|
||||
|
||||
/* Copy of the XID fields we have sent with the last
|
||||
* network originated XID-Request. Since the phone
|
||||
* may strip the optional fields in the confirmation
|
||||
* we need to remeber those fields in order to be
|
||||
* able to create the compression entity. */
|
||||
struct llist_head *xid;
|
||||
};
|
||||
|
||||
#define NUM_SAPIS 16
|
||||
|
||||
/* 3GPP TS 44.064 § 4.7.3: Logical Link Management Entity: One per TLLI */
|
||||
struct gprs_llc_llme {
|
||||
struct llist_head list;
|
||||
|
||||
@@ -169,13 +184,6 @@ struct gprs_llc_llme {
|
||||
uint16_t nsei;
|
||||
struct gprs_llc_lle lle[NUM_SAPIS];
|
||||
|
||||
/* Copy of the XID fields we have sent with the last
|
||||
* network originated XID-Request. Since the phone
|
||||
* may strip the optional fields in the confirmation
|
||||
* we need to remeber those fields in order to be
|
||||
* able to create the compression entity. */
|
||||
struct llist_head *xid;
|
||||
|
||||
/* Compression entities */
|
||||
struct {
|
||||
/* In these two list_heads we will store the
|
||||
@@ -191,6 +199,9 @@ struct gprs_llc_llme {
|
||||
|
||||
#define GPRS_LLME_RESET_AGE (0)
|
||||
|
||||
/* 3GPP TS 44.064 § 8.3 TLLI assignment procedures */
|
||||
#define TLLI_UNASSIGNED (0xffffffff)
|
||||
|
||||
extern struct llist_head gprs_llc_llmes;
|
||||
|
||||
/* LLC low level types */
|
||||
@@ -267,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
|
||||
|
||||
25
include/osmocom/sgsn/gprs_mm_state_gb_fsm.h
Normal file
25
include/osmocom/sgsn/gprs_mm_state_gb_fsm.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
|
||||
|
||||
/* TS 23.060 § 6.1.1 Mobility Management States (A/Gb mode) */
|
||||
enum mm_state_gb_fsm_states {
|
||||
ST_MM_IDLE,
|
||||
ST_MM_READY,
|
||||
ST_MM_STANDBY
|
||||
};
|
||||
|
||||
enum mm_state_gb_fsm_events {
|
||||
E_MM_GPRS_ATTACH,
|
||||
E_MM_GPRS_DETACH, /* MS becomes detached: due to Detach Req, RAU reject, implicit detach, etc. */
|
||||
E_MM_PDU_RECEPTION,
|
||||
E_MM_READY_TIMER_EXPIRY,
|
||||
/* E_FORCE_TO_STANDBY, TODO: not used */
|
||||
/* E_ABNSORMAL_RLC_CONDITION, TODO: not used */
|
||||
E_MM_RA_UPDATE,
|
||||
};
|
||||
|
||||
extern struct osmo_fsm mm_state_gb_fsm;
|
||||
23
include/osmocom/sgsn/gprs_mm_state_iu_fsm.h
Normal file
23
include/osmocom/sgsn/gprs_mm_state_iu_fsm.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
|
||||
/* TS 23.060 § 6.1.2 Mobility Management States (Iu mode) */
|
||||
enum mm_state_iu_fsm_states {
|
||||
ST_PMM_DETACHED,
|
||||
ST_PMM_CONNECTED,
|
||||
ST_PMM_IDLE
|
||||
};
|
||||
|
||||
enum mm_state_iu_fsm_events {
|
||||
E_PMM_PS_ATTACH,
|
||||
E_PMM_PS_DETACH, /* UE becomes detached: due to Detach Req, RAU reject, implicit detach, etc. */
|
||||
E_PMM_PS_CONN_RELEASE,
|
||||
E_PMM_PS_CONN_ESTABLISH,
|
||||
E_PMM_RA_UPDATE, /* = Serving RNC relocation */
|
||||
E_PMM_RX_GGSN_GTPU_DT_EI, /* param: struct sgsn_pdp_ctx *pctx */
|
||||
};
|
||||
|
||||
extern struct osmo_fsm mm_state_iu_fsm;
|
||||
9
include/osmocom/sgsn/gprs_ns.h
Normal file
9
include/osmocom/sgsn/gprs_ns.h
Normal 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);
|
||||
71
include/osmocom/sgsn/gprs_ranap.h
Normal file
71
include/osmocom/sgsn/gprs_ranap.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
#ifdef BUILD_IU
|
||||
#include <osmocom/ranap/ranap_ies_defs.h>
|
||||
#include <osmocom/ranap/ranap_msg_factory.h>
|
||||
#include <osmocom/sgsn/iu_client.h>
|
||||
#include <osmocom/sgsn/sccp.h>
|
||||
|
||||
struct sgsn_mm_ctx;
|
||||
struct sgsn_pdp_ctx;
|
||||
|
||||
/* struct RANAP_GlobalRNC_ID with a coupled buffer where .buf points to.
|
||||
* Used to easily generate a struct RANAP_GlobalRNC_ID to encode,
|
||||
* see sgsn_ranap_iu_grnc_id_compose(). */
|
||||
struct iu_grnc_id {
|
||||
uint8_t plmn_buf[3];
|
||||
struct RANAP_GlobalRNC_ID grnc_id;
|
||||
};
|
||||
int sgsn_ranap_iu_grnc_id_compose(struct iu_grnc_id *dst, const struct osmo_rnc_id *src);
|
||||
|
||||
int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data);
|
||||
|
||||
int sgsn_ranap_iu_tx(struct msgb *msg, uint8_t sapi);
|
||||
int sgsn_ranap_iu_tx_rab_ps_ass_req(struct ranap_ue_conn_ctx *ue_ctx,
|
||||
uint8_t rab_id, uint32_t gtp_ip, uint32_t gtp_tei);
|
||||
int sgsn_ranap_iu_tx_sec_mode_cmd(struct ranap_ue_conn_ctx *uectx, struct osmo_auth_vector *vec,
|
||||
int send_ck, int new_key);
|
||||
int sgsn_ranap_iu_tx_common_id(struct ranap_ue_conn_ctx *ue_ctx, const char *imsi);
|
||||
|
||||
int sgsn_ranap_iu_tx_release(struct ranap_ue_conn_ctx *ctx, const struct RANAP_Cause *cause);
|
||||
/* Transmit a Iu Release Command and submit event RANAP_IU_EVENT_IU_RELEASE upon
|
||||
* Release Complete or timeout. Caller is responsible to free the context and
|
||||
* closing the SCCP connection (sgsn_ranap_iu_free_ue) upon recieval of the event. */
|
||||
void sgsn_ranap_iu_tx_release_free(struct ranap_ue_conn_ctx *ctx,
|
||||
const struct RANAP_Cause *cause,
|
||||
int timeout);
|
||||
|
||||
int sgsn_ranap_iu_tx_cl(struct sgsn_sccp_user_iups *scu_iups,
|
||||
const struct osmo_sccp_addr *dst_addr,
|
||||
struct msgb *msg);
|
||||
int sgsn_ranap_iu_tx_error_ind(struct sgsn_sccp_user_iups *scu_iups,
|
||||
const struct osmo_sccp_addr *dst_addr,
|
||||
const RANAP_Cause_t *cause);
|
||||
|
||||
void sgsn_ranap_iu_handle_co_initial(struct ranap_iu_rnc *iu_rnc,
|
||||
uint32_t conn_id,
|
||||
const ranap_message *message);
|
||||
void sgsn_ranap_iu_handle_co(struct ranap_ue_conn_ctx *ue_ctx, const ranap_message *message);
|
||||
|
||||
/* Entry points from rx SCCP: */
|
||||
int sgsn_ranap_iu_rx_cl_msg(struct sgsn_sccp_user_iups *scu_iups,
|
||||
const struct osmo_scu_unitdata_param *ud_prim,
|
||||
const uint8_t *data, size_t len);
|
||||
int sgsn_ranap_iu_rx_co_initial_msg(struct sgsn_sccp_user_iups *scu_iups,
|
||||
const struct osmo_sccp_addr *rem_sccp_addr,
|
||||
uint32_t conn_id,
|
||||
const uint8_t *data, size_t len);
|
||||
int sgsn_ranap_iu_rx_co_msg(struct ranap_ue_conn_ctx *ue_ctx, const uint8_t *data, size_t len);
|
||||
|
||||
#endif /* ifdef BUILD_IU */
|
||||
|
||||
struct ranap_ue_conn_ctx;
|
||||
/* On RANAP, Returns pointer to he associated ranap_ue_conn_ctx in msg, filled
|
||||
* in by osmo-iuh's iu_recv_cb().
|
||||
* On Gb, returns NULL */
|
||||
#define MSG_IU_UE_CTX(msg) ((struct ranap_ue_conn_ctx *)(msg)->dst)
|
||||
#define MSG_IU_UE_CTX_SET(msg, val) (msg)->dst = (val)
|
||||
140
include/osmocom/sgsn/gprs_routing_area.h
Normal file
140
include/osmocom/sgsn/gprs_routing_area.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/*! \file gprs_routing_area.h */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/gsm/gsm23003.h>
|
||||
|
||||
/* rai -> struct osmo_routing_area_id * */
|
||||
#define LOGRAI(level, rai, fmt, args...) \
|
||||
do {\
|
||||
char __log_rai_buf[32]; \
|
||||
LOGP(DRA, level, "RA(%s) " fmt, \
|
||||
osmo_rai_name2_buf(__log_rai_buf, sizeof(__log_rai_buf), rai), \
|
||||
## args); \
|
||||
} while (0)
|
||||
|
||||
/* ra -> struct sgsn_ra * */
|
||||
#define LOGRA(level, ra, fmt, args...) \
|
||||
LOGRAI(level, (&(ra)->rai), fmt, ## args)
|
||||
|
||||
struct sgsn_instance;
|
||||
struct sgsn_mm_ctx;
|
||||
|
||||
struct sgsn_ra_global {
|
||||
/* list of struct sgsn_ra */
|
||||
struct llist_head ra_list;
|
||||
};
|
||||
|
||||
enum sgsn_ra_ran_type {
|
||||
RA_TYPE_GERAN_Gb,
|
||||
RA_TYPE_UTRAN_Iu,
|
||||
};
|
||||
|
||||
extern const struct value_string sgsn_ra_ran_type_names[];
|
||||
|
||||
struct sgsn_ra {
|
||||
/* Entry in sgsn_ra_global->ra_list */
|
||||
struct llist_head list;
|
||||
|
||||
struct osmo_routing_area_id rai;
|
||||
|
||||
/* For GERAN: every PCU is connected to the SGSN. It allows the SGSN to know every single cell.
|
||||
* For routing, the SGSN must know to which PCU a given cell is connected.
|
||||
* It is possible that more than one PCU serves the same Routing Area.
|
||||
*
|
||||
* For UTRAN: only the RNC (HNB via HNBGW) is communicating with the SGSN.
|
||||
* The SGSN doesn't know every cell, because they aren't accepted individually by the SGSN.
|
||||
* The SGSN only "knows" RAI/SAI if they have been used. In the future it would be a good idea to
|
||||
* allow configuring RA in the vty/config as well.
|
||||
* Similar to the GERAN Cell, but iu_client doesn't notify us for every given SAI, only for RAC.
|
||||
* Further the SGSN doesn't get informed about Service Area and can't relate the SAI to a given UE.
|
||||
* For UTRAN only do a LAC/RAC <> RNC relation and don't have a specific cell relation.
|
||||
*/
|
||||
enum sgsn_ra_ran_type ran_type;
|
||||
union {
|
||||
struct {
|
||||
/* the RNC id must be the same for a given Routing Area */
|
||||
struct osmo_rnc_id rnc_id;
|
||||
} utran;
|
||||
} u;
|
||||
|
||||
/* GERAN/UTRAN: cells contains a list of sgsn_ra_cells which are alive */
|
||||
struct llist_head cells_alive_list;
|
||||
};
|
||||
|
||||
struct sgsn_ra_cell {
|
||||
/* Entry in sgsn_ra->cells */
|
||||
struct llist_head list;
|
||||
|
||||
/*! link back to the parent */
|
||||
struct sgsn_ra *ra;
|
||||
|
||||
enum sgsn_ra_ran_type ran_type;
|
||||
union {
|
||||
struct {
|
||||
uint16_t nsei;
|
||||
uint16_t bvci;
|
||||
uint16_t cell_id;
|
||||
} geran;
|
||||
|
||||
struct {
|
||||
/* the RNC id must be the same for a given Routing Area */
|
||||
uint16_t sac;
|
||||
} utran;
|
||||
} u;
|
||||
};
|
||||
|
||||
void sgsn_ra_init(struct sgsn_instance *inst);
|
||||
|
||||
struct sgsn_ra *sgsn_ra_alloc(const struct osmo_routing_area_id *rai, enum sgsn_ra_ran_type ran_type);
|
||||
struct sgsn_ra *sgsn_ra_find_or_create(const struct osmo_routing_area_id *rai, enum sgsn_ra_ran_type ran_type);
|
||||
struct sgsn_ra *sgsn_ra_get_ra(const struct osmo_routing_area_id *rai);
|
||||
void sgsn_ra_free(struct sgsn_ra *ra);
|
||||
struct sgsn_ra_cell *sgsn_ra_cell_alloc_geran(struct sgsn_ra *ra, uint16_t cell_id, uint16_t nsei, uint16_t bvci);
|
||||
void sgsn_ra_cell_free(struct sgsn_ra_cell *cell);
|
||||
|
||||
/* GERAN */
|
||||
/* Called by BSSGP layer to inform about a reset on a PtP BVCI */
|
||||
int sgsn_ra_geran_bvc_cell_reset_ind(uint16_t nsei, uint16_t bvci, struct osmo_cell_global_id_ps *cgi_ps);
|
||||
/* Called by BSSGP layer to inform about a reset on a Signal BVCI */
|
||||
void sgsn_ra_geran_bvc_sign_reset_ind(uint16_t nsei);
|
||||
/* FIXME: handle BVC BLOCK/UNBLOCK/UNAVAILABLE */
|
||||
/* Called by NS-VC layer to inform about an unavailable NSEI (and all BVCI on them) */
|
||||
int sgsn_ra_geran_nsei_failure_ind(uint16_t nsei);
|
||||
|
||||
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_cgi_ps(const struct osmo_cell_global_id_ps *cgi_ps);
|
||||
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_lai(const struct osmo_location_area_id *lai, uint16_t cell_id);
|
||||
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_cgi(const struct osmo_cell_global_id *cgi);
|
||||
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_ra(const struct sgsn_ra *ra, uint16_t cell_id);
|
||||
struct sgsn_ra_cell *sgsn_ra_geran_get_cell_by_gb(uint16_t nsei, uint16_t bvci);
|
||||
|
||||
/* UTRAN */
|
||||
int sgsn_ra_utran_register(const struct osmo_routing_area_id *rai, const struct osmo_rnc_id *rnc_id);
|
||||
|
||||
struct sgsn_ra *sgsn_ra_geran_get_ra(const struct osmo_routing_area_id *rai);
|
||||
|
||||
/* Page the whole routing area for this mmctx */
|
||||
int sgsn_ra_geran_page_ra(const struct osmo_routing_area_id *rai, struct sgsn_mm_ctx *mmctx);
|
||||
struct sgsn_ra *sgsn_ra_utran_get_ra(const struct osmo_routing_area_id *rai);
|
||||
|
||||
/*
|
||||
* return value for callbacks.
|
||||
* STOP: stop calling the callback for the remaining cells, sgsn_ra_foreach_ra() returns 0
|
||||
* CONT: continue to call the callback for remaining cells
|
||||
* ABORT: stop calling the callback for the remaining cells, sgsn_ra_foreach_ra() returns -1
|
||||
*/
|
||||
#define SGSN_RA_CB_STOP 1
|
||||
#define SGSN_RA_CB_CONT 0
|
||||
#define SGSN_RA_CB_ERROR -1
|
||||
|
||||
typedef int (sgsn_ra_cb_t)(struct sgsn_ra_cell *ra_cell, void *cb_data);
|
||||
int sgsn_ra_foreach_cell(struct sgsn_ra *ra, sgsn_ra_cb_t *cb, void *cb_data);
|
||||
int sgsn_ra_foreach_cell2(struct osmo_routing_area_id *rai, sgsn_ra_cb_t *cb, void *cb_data);
|
||||
|
||||
/* Page the whole routing area for this mmctx */
|
||||
int sgsn_ra_utran_page_ra(const struct osmo_routing_area_id *rai, const struct sgsn_mm_ctx *mmctx);
|
||||
@@ -1,509 +0,0 @@
|
||||
#ifndef _GPRS_SGSN_H
|
||||
#define _GPRS_SGSN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/core/timer.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>
|
||||
|
||||
#define GSM_EXTENSION_LENGTH 15
|
||||
#define GSM_APN_LENGTH 102
|
||||
|
||||
struct gprs_llc_lle;
|
||||
struct ctrl_handle;
|
||||
struct gprs_subscr;
|
||||
|
||||
enum gsm48_gsm_cause;
|
||||
|
||||
/* TS 04.08 4.1.3.3 GMM mobility management states on the network side */
|
||||
enum gprs_gmm_state {
|
||||
GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
|
||||
GMM_COMMON_PROC_INIT, /* 4.1.3.3.1.2 */
|
||||
GMM_REGISTERED_NORMAL, /* 4.1.3.3.2.1 */
|
||||
GMM_REGISTERED_SUSPENDED, /* 4.1.3.3.2.2 */
|
||||
GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */
|
||||
};
|
||||
|
||||
/* TS 23.060 6.1.1 and 6.1.2 Mobility management states A/Gb and Iu mode */
|
||||
enum gprs_pmm_state {
|
||||
PMM_DETACHED,
|
||||
PMM_CONNECTED,
|
||||
PMM_IDLE,
|
||||
MM_IDLE,
|
||||
MM_READY,
|
||||
MM_STANDBY,
|
||||
};
|
||||
|
||||
enum gprs_mm_ctr {
|
||||
GMM_CTR_PKTS_SIG_IN,
|
||||
GMM_CTR_PKTS_SIG_OUT,
|
||||
GMM_CTR_PKTS_UDATA_IN,
|
||||
GMM_CTR_PKTS_UDATA_OUT,
|
||||
GMM_CTR_BYTES_UDATA_IN,
|
||||
GMM_CTR_BYTES_UDATA_OUT,
|
||||
GMM_CTR_PDP_CTX_ACT,
|
||||
GMM_CTR_SUSPEND,
|
||||
GMM_CTR_PAGING_PS,
|
||||
GMM_CTR_PAGING_CS,
|
||||
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,
|
||||
GMM_T3350_MODE_RAU,
|
||||
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,
|
||||
};
|
||||
|
||||
struct sgsn_ggsn_lookup {
|
||||
int state;
|
||||
|
||||
struct sgsn_mm_ctx *mmctx;
|
||||
|
||||
/* APN string */
|
||||
char apn_str[GSM_APN_LENGTH];
|
||||
|
||||
/* the original data */
|
||||
struct msgb *orig_msg;
|
||||
struct tlv_parsed tp;
|
||||
|
||||
/* for dealing with re-transmissions */
|
||||
uint8_t nsapi;
|
||||
uint8_t sapi;
|
||||
uint8_t ti;
|
||||
};
|
||||
|
||||
enum sgsn_ran_type {
|
||||
/* GPRS/EDGE via Gb */
|
||||
MM_CTX_T_GERAN_Gb,
|
||||
/* UMTS via Iu */
|
||||
MM_CTX_T_UTRAN_Iu,
|
||||
/* GPRS/EDGE via Iu */
|
||||
MM_CTX_T_GERAN_Iu,
|
||||
};
|
||||
|
||||
struct service_info {
|
||||
uint8_t type;
|
||||
uint16_t pdp_status;
|
||||
};
|
||||
|
||||
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 {
|
||||
struct llist_head list;
|
||||
|
||||
enum sgsn_ran_type ran_type;
|
||||
|
||||
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
|
||||
enum gprs_gmm_state gmm_state;
|
||||
enum gprs_pmm_state pmm_state; /* Iu: page when in PMM-IDLE mode */
|
||||
uint32_t p_tmsi;
|
||||
uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
|
||||
uint32_t p_tmsi_sig;
|
||||
char imei[GSM23003_IMEISV_NUM_DIGITS+1];
|
||||
/* Opt: Software Version Numbber / TS 23.195 */
|
||||
char msisdn[GSM_EXTENSION_LENGTH];
|
||||
struct gprs_ra_id ra;
|
||||
struct {
|
||||
uint16_t cell_id; /* Gb only */
|
||||
uint32_t cell_id_age; /* Gb only */
|
||||
uint8_t radio_prio_sms;
|
||||
|
||||
/* Additional bits not present in the GSM TS */
|
||||
uint16_t nsei;
|
||||
uint16_t bvci;
|
||||
struct gprs_llc_llme *llme;
|
||||
uint32_t tlli;
|
||||
uint32_t tlli_new;
|
||||
} gb;
|
||||
struct {
|
||||
int new_key;
|
||||
uint16_t sac; /* Iu: Service Area Code */
|
||||
uint32_t sac_age; /* Iu: Service Area Code age */
|
||||
/* CSG ID */
|
||||
/* CSG Membership */
|
||||
/* Access Mode */
|
||||
/* Seelected CN Operator ID (TS 23.251) */
|
||||
/* CSG Subscription Data */
|
||||
/* LIPA Allowed */
|
||||
/* Voice Support Match Indicator */
|
||||
struct ranap_ue_conn_ctx *ue_ctx;
|
||||
struct service_info service;
|
||||
} iu;
|
||||
struct {
|
||||
struct osmo_fsm_inst *fsm;
|
||||
|
||||
/* when a second attach req arrives while in this procedure,
|
||||
* the fsm needs to compare it against old to decide what to do */
|
||||
struct msgb *attach_req;
|
||||
uint32_t id_type;
|
||||
unsigned int auth_reattempt; /* tracking UMTS resync auth attempts */
|
||||
} gmm_att_req;
|
||||
/* VLR number */
|
||||
uint32_t new_sgsn_addr;
|
||||
/* Authentication Triplet */
|
||||
struct gsm_auth_tuple auth_triplet;
|
||||
/* Kc */
|
||||
/* Iu: CK, IK, KSI */
|
||||
/* CKSN */
|
||||
enum gprs_ciph_algo ciph_algo;
|
||||
/* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
|
||||
uint8_t ac_ref_nr_used;
|
||||
|
||||
struct {
|
||||
uint8_t len;
|
||||
uint8_t buf[50]; /* GSM 04.08 10.5.5.12a, extended in TS 24.008 */
|
||||
} ms_radio_access_capa;
|
||||
/* Supported Codecs (SRVCC) */
|
||||
struct {
|
||||
uint8_t len;
|
||||
uint8_t buf[8]; /* GSM 04.08 10.5.5.12, extended in TS 24.008 */
|
||||
} ms_network_capa;
|
||||
/* UE Netowrk Capability (E-UTRAN) */
|
||||
uint16_t drx_parms;
|
||||
/* Active Time value for PSM */
|
||||
int mnrg; /* MS reported to HLR? */
|
||||
int ngaf; /* MS reported to MSC/VLR? */
|
||||
int ppf; /* paging for GPRS + non-GPRS? */
|
||||
/* Subscribed Charging Characteristics */
|
||||
/* Trace Reference */
|
||||
/* Trace Type */
|
||||
/* Trigger ID */
|
||||
/* OMC Identity */
|
||||
/* SMS Parameters */
|
||||
int recovery;
|
||||
/* Access Restriction */
|
||||
/* GPRS CSI (CAMEL) */
|
||||
/* MG-CSI (CAMEL) */
|
||||
/* Subscribed UE-AMBR */
|
||||
/* UE-AMBR */
|
||||
/* APN Subscribed */
|
||||
|
||||
struct llist_head pdp_list;
|
||||
|
||||
struct rate_ctr_group *ctrg;
|
||||
struct osmo_timer_list timer;
|
||||
unsigned int T; /* Txxxx number */
|
||||
unsigned int num_T_exp; /* number of consecutive T expirations */
|
||||
|
||||
enum gprs_t3350_mode t3350_mode;
|
||||
uint8_t t3370_id_type;
|
||||
uint8_t pending_req; /* the request's message type */
|
||||
/* TODO: There isn't much semantic difference between t3350_mode
|
||||
* (refers to the timer) and pending_req (refers to the procedure),
|
||||
* where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
|
||||
* whether one of them can be dropped. */
|
||||
|
||||
enum sgsn_auth_state auth_state;
|
||||
enum osmo_sub_auth_type sec_ctx;
|
||||
|
||||
/* the string representation of the current hlr */
|
||||
char hlr[GSM_EXTENSION_LENGTH];
|
||||
|
||||
/* the current GGSN look-up operation */
|
||||
struct sgsn_ggsn_lookup *ggsn_lookup;
|
||||
|
||||
struct gprs_subscr *subscr;
|
||||
};
|
||||
|
||||
static inline bool sgsn_mm_ctx_is_authenticated(struct sgsn_mm_ctx *ctx)
|
||||
{
|
||||
switch (ctx->sec_ctx) {
|
||||
case OSMO_AUTH_TYPE_GSM:
|
||||
case OSMO_AUTH_TYPE_UMTS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define LOGMMCTXP(level, mm, fmt, args...) \
|
||||
LOGP(DMM, level, "MM(%s/%08x) " fmt, (mm) ? (mm)->imsi : "---", \
|
||||
(mm) ? (mm)->p_tmsi : GSM_RESERVED_TMSI, ## args)
|
||||
|
||||
/* look-up a SGSN MM context based on TLLI + RAI */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx);
|
||||
|
||||
/* look-up by matching TLLI and P-TMSI (think twice before using this) */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid);
|
||||
|
||||
/* Allocate a new SGSN MM context */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx);
|
||||
|
||||
void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx);
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
|
||||
struct tlv_parsed *tp,
|
||||
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);
|
||||
/* look up PDP context by MM context and transaction ID */
|
||||
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;
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* ctrl interface related work
|
||||
*/
|
||||
int sgsn_ctrl_cmds_install(void);
|
||||
|
||||
/*
|
||||
* Authorization/ACL handling
|
||||
*/
|
||||
struct imsi_acl_entry {
|
||||
struct llist_head list;
|
||||
char imsi[16+1];
|
||||
};
|
||||
|
||||
/* 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 */
|
||||
18
include/osmocom/sgsn/gprs_sm.h
Normal file
18
include/osmocom/sgsn/gprs_sm.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.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,
|
||||
uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
|
||||
int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
|
||||
int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
|
||||
|
||||
void pdp_ctx_detach_mm_ctx(struct sgsn_pdp_ctx *pdp);
|
||||
|
||||
int gsm0408_rcv_gsm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
|
||||
struct gprs_llc_llme *llme);
|
||||
@@ -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 {
|
||||
@@ -44,7 +47,7 @@ struct gprs_sndcp_entity {
|
||||
struct llist_head list;
|
||||
|
||||
/* FIXME: move this RA_ID up to the LLME or even higher */
|
||||
struct gprs_ra_id ra_id;
|
||||
struct osmo_routing_area_id rai;
|
||||
/* reference to the LLC Entity below this SNDCP entity */
|
||||
struct gprs_llc_lle *lle;
|
||||
/* The NSAPI we shall use on top of LLC */
|
||||
@@ -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) */
|
||||
@@ -76,4 +81,21 @@ int sndcp_sn_xid_conf(struct gprs_llc_xid_field *xid_field_conf,
|
||||
struct gprs_llc_xid_field *xid_field_request,
|
||||
struct gprs_llc_lle *lle);
|
||||
|
||||
/* Clean up all gprs_sndcp_entities related to llme (OS#4824) */
|
||||
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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
29
include/osmocom/sgsn/gtp.h
Normal file
29
include/osmocom/sgsn/gtp.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#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 osmo_routing_area_id *rai, 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);
|
||||
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx);
|
||||
41
include/osmocom/sgsn/gtp_ggsn.h
Normal file
41
include/osmocom/sgsn/gtp_ggsn.h
Normal 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)
|
||||
46
include/osmocom/sgsn/gtp_mme.h
Normal file
46
include/osmocom/sgsn/gtp_mme.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/gprs/protocol/gsm_24_301.h>
|
||||
#include <osmocom/gsm/gsm23003.h>
|
||||
|
||||
struct gsn_t;
|
||||
|
||||
struct mme_rim_route {
|
||||
struct llist_head list; /* item in struct sgsn_mme_ctx */
|
||||
struct osmo_eutran_tai tai;
|
||||
};
|
||||
|
||||
struct sgsn_mme_ctx {
|
||||
struct llist_head list; /* item in sgsn_mme_ctxts */
|
||||
struct llist_head routes; /* list of struct mme_rim_route */
|
||||
struct sgsn_instance *sgsn; /* backpointer */
|
||||
char *name;
|
||||
struct in_addr remote_addr;
|
||||
|
||||
struct osmo_gummei gummei;
|
||||
bool gummei_valid;
|
||||
|
||||
/* is it the default route for outgoing message? are all incoming messages accepted? */
|
||||
bool default_route;
|
||||
};
|
||||
struct sgsn_mme_ctx *sgsn_mme_ctx_alloc(struct sgsn_instance *sgsn, const char *name);
|
||||
struct sgsn_mme_ctx *sgsn_mme_ctx_find_alloc(struct sgsn_instance *sgsn, const char *name);
|
||||
void sgsn_mme_ctx_free(struct sgsn_mme_ctx *mme);
|
||||
|
||||
struct sgsn_mme_ctx *sgsn_mme_ctx_by_name(const struct sgsn_instance *sgsn, const char *name);
|
||||
struct sgsn_mme_ctx *sgsn_mme_ctx_by_addr(const struct sgsn_instance *sgsn, const struct in_addr *addr);
|
||||
struct sgsn_mme_ctx *sgsn_mme_ctx_by_route(const struct sgsn_instance *sgsn, const struct osmo_eutran_tai *tai);
|
||||
struct sgsn_mme_ctx *sgsn_mme_ctx_by_gummei(const struct sgsn_instance *sgsn, const struct osmo_gummei *gummei);
|
||||
struct sgsn_mme_ctx *sgsn_mme_ctx_by_default_route(const struct sgsn_instance *sgsn);
|
||||
|
||||
void sgsn_mme_ctx_route_add(struct sgsn_mme_ctx *mme, const struct osmo_eutran_tai *tai);
|
||||
void sgsn_mme_ctx_route_del(struct sgsn_mme_ctx *mme, const struct osmo_eutran_tai *tai);
|
||||
|
||||
#define LOGMME(mme, cat, level, fmt, args...) { \
|
||||
char _buf[INET_ADDRSTRLEN]; \
|
||||
LOGP(cat, level, "MME(%s:%s): " fmt, (mme)->name, inet_ntop(AF_INET, &(mme)->remote_addr, _buf, sizeof(_buf)), ## args); \
|
||||
} while (0)
|
||||
95
include/osmocom/sgsn/iu_client.h
Normal file
95
include/osmocom/sgsn/iu_client.h
Normal file
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/defs.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/iuh/common.h>
|
||||
#include <osmocom/ranap/ranap_common.h>
|
||||
#include <osmocom/ranap/vty.h>
|
||||
#include <osmocom/sigtran/sccp_sap.h>
|
||||
|
||||
struct msgb;
|
||||
struct osmo_auth_vector;
|
||||
|
||||
struct RANAP_RAB_SetupOrModifiedItemIEs_s;
|
||||
|
||||
struct ranap_iu_rnc;
|
||||
|
||||
struct ranap_ue_conn_ctx {
|
||||
struct llist_head list; /* item in sgsn_sccp->ue_conn_ctx_list */
|
||||
struct ranap_iu_rnc *rnc;
|
||||
uint32_t conn_id;
|
||||
int integrity_active;
|
||||
struct gprs_ra_id ra_id;
|
||||
enum ranap_nsap_addr_enc rab_assign_addr_enc;
|
||||
bool notification; /* send notification to the upstream user */
|
||||
/* if true the ue_ctx will be free on Iu release complete */
|
||||
bool free_on_release;
|
||||
/* Will be set when the Iu Release Command has been sent */
|
||||
struct osmo_timer_list release_timeout;
|
||||
};
|
||||
|
||||
enum ranap_iu_event_new_area_type {
|
||||
RANAP_IU_NEW_LAC,
|
||||
RANAP_IU_NEW_RAC,
|
||||
};
|
||||
|
||||
struct ranap_iu_event_new_area {
|
||||
const struct osmo_rnc_id *rnc_id;
|
||||
enum ranap_iu_event_new_area_type cell_type;
|
||||
union {
|
||||
const struct osmo_location_area_id *lai;
|
||||
const struct osmo_routing_area_id *rai;
|
||||
} u;
|
||||
};
|
||||
|
||||
enum ranap_iu_event_type {
|
||||
RANAP_IU_EVENT_RAB_ASSIGN,
|
||||
RANAP_IU_EVENT_SECURITY_MODE_COMPLETE,
|
||||
RANAP_IU_EVENT_IU_RELEASE, /* An actual Iu Release message was received */
|
||||
RANAP_IU_EVENT_LINK_INVALIDATED, /* A SUA link was lost or closed down */
|
||||
RANAP_IU_EVENT_NEW_AREA, /* Either a new LAC/RAC has been detected */
|
||||
};
|
||||
|
||||
extern const struct value_string iu_client_event_type_names[];
|
||||
static inline const char *iu_client_event_type_str(enum ranap_iu_event_type e)
|
||||
{
|
||||
return get_value_string(iu_client_event_type_names, e);
|
||||
}
|
||||
|
||||
/* Implementations of iu_recv_cb_t shall find the ranap_ue_conn_ctx in msg->dst. */
|
||||
typedef int (*ranap_iu_recv_cb_t)(struct msgb *msg, struct gprs_ra_id *ra_id,
|
||||
uint16_t *sai);
|
||||
|
||||
typedef int (*ranap_iu_event_cb_t)(struct ranap_ue_conn_ctx *ue_ctx,
|
||||
enum ranap_iu_event_type type, void *data);
|
||||
|
||||
typedef int (*ranap_iu_rab_ass_resp_cb_t)(struct ranap_ue_conn_ctx *ue_ctx, uint8_t rab_id,
|
||||
struct RANAP_RAB_SetupOrModifiedItemIEs_s *setup_ies);
|
||||
|
||||
int global_iu_event(struct ranap_ue_conn_ctx *ue_ctx,
|
||||
enum ranap_iu_event_type type,
|
||||
void *data);
|
||||
|
||||
|
||||
int ranap_iu_init(void *ctx);
|
||||
|
||||
int ranap_iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac)
|
||||
OSMO_DEPRECATED("Use ranap_iu_page_cs2 instead");
|
||||
|
||||
int ranap_iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac)
|
||||
OSMO_DEPRECATED("Use ranap_iu_page_ps2 instead");
|
||||
|
||||
int ranap_iu_page_cs2(const char *imsi, const uint32_t *tmsi, const struct osmo_location_area_id *lai);
|
||||
int ranap_iu_page_ps2(const char *imsi, const uint32_t *ptmsi, const struct osmo_routing_area_id *rai);
|
||||
|
||||
|
||||
struct ranap_ue_conn_ctx *ue_conn_ctx_alloc(struct ranap_iu_rnc *rnc, uint32_t conn_id);
|
||||
|
||||
void ue_conn_ctx_link_invalidated_free(struct ranap_ue_conn_ctx *ue);
|
||||
|
||||
/* freeing the UE will release all resources
|
||||
* This will close the SCCP connection connected to the UE */
|
||||
void sgsn_ranap_iu_free_ue(struct ranap_ue_conn_ctx *ue_ctx);
|
||||
57
include/osmocom/sgsn/iu_rnc.h
Normal file
57
include/osmocom/sgsn/iu_rnc.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/defs.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/iuh/common.h>
|
||||
#include <osmocom/sigtran/sccp_sap.h>
|
||||
|
||||
struct iu_lac_rac_entry {
|
||||
struct llist_head entry;
|
||||
struct osmo_routing_area_id rai;
|
||||
};
|
||||
|
||||
/* A remote RNC (Radio Network Controller, like BSC but for UMTS) that has
|
||||
* called us and is currently reachable at the given osmo_sccp_addr. So, when we
|
||||
* know a LAC for a subscriber, we can page it at the RNC matching that LAC or
|
||||
* RAC. An HNB-GW typically presents itself as if it were a single RNC, even
|
||||
* though it may have several RNCs in hNodeBs connected to it. Those will then
|
||||
* share the same RNC id, which they actually receive and adopt from the HNB-GW
|
||||
* in the HNBAP HNB REGISTER ACCEPT message. */
|
||||
struct ranap_iu_rnc {
|
||||
struct llist_head entry;
|
||||
|
||||
struct osmo_rnc_id rnc_id;
|
||||
struct sgsn_sccp_user_iups *scu_iups;
|
||||
struct osmo_sccp_addr sccp_addr;
|
||||
struct osmo_fsm_inst *fi;
|
||||
|
||||
/* A list of struct iu_lac_rac_entry */
|
||||
struct llist_head lac_rac_list;
|
||||
};
|
||||
|
||||
struct ranap_iu_rnc *iu_rnc_find_or_create(const struct osmo_rnc_id *rnc_id,
|
||||
struct sgsn_sccp_user_iups *scu_iups,
|
||||
const struct osmo_sccp_addr *addr);
|
||||
|
||||
struct ranap_iu_rnc *iu_rnc_find_by_addr(const struct osmo_sccp_addr *rnc_sccp_addr);
|
||||
|
||||
void iu_rnc_update_rai_seen(struct ranap_iu_rnc *rnc, const struct osmo_routing_area_id *rai);
|
||||
|
||||
void iu_rnc_discard_all_ue_ctx(struct ranap_iu_rnc *rnc);
|
||||
|
||||
int iu_rnc_tx_paging_cmd(struct ranap_iu_rnc *rnc,
|
||||
const char *imsi,
|
||||
const uint32_t *tmsi,
|
||||
bool is_ps,
|
||||
uint32_t paging_cause);
|
||||
|
||||
#define LOG_RNC_CAT(IU_RNC, subsys, loglevel, fmt, args ...) \
|
||||
LOGPFSMSL((IU_RNC)->fi, subsys, loglevel, fmt, ## args)
|
||||
|
||||
#define LOG_RNC(IU_RNC, loglevel, fmt, args ...) \
|
||||
LOG_RNC_CAT(IU_RNC, DRANAP, loglevel, fmt, ## args)
|
||||
37
include/osmocom/sgsn/iu_rnc_fsm.h
Normal file
37
include/osmocom/sgsn/iu_rnc_fsm.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
|
||||
#include <osmocom/ranap/ranap_ies_defs.h>
|
||||
|
||||
struct ranap_iu_rnc;
|
||||
|
||||
enum iu_rnc_state {
|
||||
IU_RNC_ST_WAIT_RX_RESET = 0,
|
||||
IU_RNC_ST_WAIT_RX_RESET_ACK,
|
||||
IU_RNC_ST_READY,
|
||||
IU_RNC_ST_DISCARDING,
|
||||
};
|
||||
|
||||
struct iu_rnc_ev_msg_up_co_initial_ctx {
|
||||
struct ranap_iu_rnc *rnc;
|
||||
uint32_t conn_id;
|
||||
ranap_message message;
|
||||
};
|
||||
|
||||
struct iu_rnc_ev_msg_up_co_ctx {
|
||||
struct ranap_ue_conn_ctx *ue_ctx;
|
||||
ranap_message message;
|
||||
};
|
||||
|
||||
enum iu_rnc_event {
|
||||
IU_RNC_EV_MSG_UP_CO_INITIAL, /* struct iu_rnc_ev_msg_up_co_initial_ctx* */
|
||||
IU_RNC_EV_MSG_UP_CO, /* struct iu_rnc_ev_msg_up_co_ctx* */
|
||||
IU_RNC_EV_RX_RESET, /* no param */
|
||||
IU_RNC_EV_RX_RESET_ACK, /* no param */
|
||||
IU_RNC_EV_MSG_DOWN_CL, /* struct msgb* */
|
||||
IU_RNC_EV_AVAILABLE,
|
||||
IU_RNC_EV_UNAVAILABLE
|
||||
};
|
||||
|
||||
extern struct osmo_fsm iu_rnc_fsm;
|
||||
301
include/osmocom/sgsn/mmctx.h
Normal file
301
include/osmocom/sgsn/mmctx.h
Normal file
@@ -0,0 +1,301 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/core/timer.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/auth.h>
|
||||
#include <osmocom/sgsn/gprs_subscriber.h>
|
||||
|
||||
#define GSM_EXTENSION_LENGTH 15
|
||||
|
||||
struct gprs_llc_lle;
|
||||
struct ctrl_handle;
|
||||
struct gprs_subscr;
|
||||
struct sgsn_ggsn_ctx;
|
||||
struct sgsn_pdp_ctx;
|
||||
|
||||
enum gsm48_gsm_cause;
|
||||
|
||||
enum gprs_mm_ctr {
|
||||
GMM_CTR_PKTS_SIG_IN,
|
||||
GMM_CTR_PKTS_SIG_OUT,
|
||||
GMM_CTR_PKTS_UDATA_IN,
|
||||
GMM_CTR_PKTS_UDATA_OUT,
|
||||
GMM_CTR_BYTES_UDATA_IN,
|
||||
GMM_CTR_BYTES_UDATA_OUT,
|
||||
GMM_CTR_PDP_CTX_ACT,
|
||||
GMM_CTR_SUSPEND,
|
||||
GMM_CTR_PAGING_PS,
|
||||
GMM_CTR_PAGING_CS,
|
||||
GMM_CTR_RA_UPDATE,
|
||||
};
|
||||
|
||||
enum gprs_t3350_mode {
|
||||
GMM_T3350_MODE_NONE,
|
||||
GMM_T3350_MODE_ATT,
|
||||
GMM_T3350_MODE_RAU,
|
||||
GMM_T3350_MODE_PTMSI_REALL,
|
||||
};
|
||||
|
||||
enum sgsn_ggsn_lookup_state {
|
||||
SGSN_GGSN_2DIGIT,
|
||||
SGSN_GGSN_3DIGIT,
|
||||
};
|
||||
|
||||
struct sgsn_ggsn_lookup {
|
||||
int state;
|
||||
|
||||
struct sgsn_mm_ctx *mmctx;
|
||||
|
||||
/* APN string */
|
||||
char apn_str[GSM_APN_LENGTH];
|
||||
|
||||
/* the original data */
|
||||
struct msgb *orig_msg;
|
||||
struct tlv_parsed tp;
|
||||
|
||||
/* for dealing with re-transmissions */
|
||||
uint8_t nsapi;
|
||||
uint8_t sapi;
|
||||
uint8_t ti;
|
||||
};
|
||||
|
||||
enum sgsn_ran_type {
|
||||
/* GPRS/EDGE via Gb */
|
||||
MM_CTX_T_GERAN_Gb,
|
||||
/* UMTS via Iu */
|
||||
MM_CTX_T_UTRAN_Iu,
|
||||
#if 0
|
||||
/* GPRS/EDGE via Iu, not supported */
|
||||
MM_CTX_T_GERAN_Iu,
|
||||
#endif
|
||||
};
|
||||
extern const struct value_string sgsn_ran_type_names[];
|
||||
|
||||
struct service_info {
|
||||
uint8_t type;
|
||||
uint16_t pdp_status;
|
||||
};
|
||||
|
||||
struct ranap_ue_conn_ctx;
|
||||
|
||||
/* 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 {
|
||||
struct llist_head list;
|
||||
|
||||
enum sgsn_ran_type ran_type;
|
||||
|
||||
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
|
||||
struct osmo_fsm_inst *gmm_fsm;
|
||||
uint32_t p_tmsi;
|
||||
uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
|
||||
uint32_t p_tmsi_sig;
|
||||
char imei[GSM23003_IMEISV_NUM_DIGITS+1];
|
||||
/* Opt: Software Version Numbber / TS 23.195 */
|
||||
char msisdn[GSM_EXTENSION_LENGTH];
|
||||
struct osmo_routing_area_id ra;
|
||||
struct {
|
||||
uint16_t cell_id; /* Gb only */
|
||||
uint32_t cell_id_age; /* Gb only */
|
||||
uint8_t radio_prio_sms;
|
||||
|
||||
/* Additional bits not present in the GSM TS */
|
||||
uint16_t nsei;
|
||||
uint16_t bvci;
|
||||
struct gprs_llc_llme *llme;
|
||||
uint32_t tlli;
|
||||
uint32_t tlli_new;
|
||||
|
||||
/* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
|
||||
struct osmo_fsm_inst *mm_state_fsm;
|
||||
} gb;
|
||||
struct {
|
||||
int new_key;
|
||||
uint16_t sac; /* Iu: Service Area Code */
|
||||
uint32_t sac_age; /* Iu: Service Area Code age */
|
||||
/* CSG ID */
|
||||
/* CSG Membership */
|
||||
/* Access Mode */
|
||||
/* Seelected CN Operator ID (TS 23.251) */
|
||||
/* CSG Subscription Data */
|
||||
/* LIPA Allowed */
|
||||
/* Voice Support Match Indicator */
|
||||
struct ranap_ue_conn_ctx *ue_ctx;
|
||||
struct service_info service;
|
||||
/* TS 23.060 6.1.2 Mobility Management States (Iu mode) */
|
||||
struct osmo_fsm_inst *mm_state_fsm;
|
||||
} iu;
|
||||
struct {
|
||||
struct osmo_fsm_inst *fsm;
|
||||
|
||||
/* when a second attach req arrives while in this procedure,
|
||||
* the fsm needs to compare it against old to decide what to do */
|
||||
struct msgb *attach_req;
|
||||
uint32_t id_type;
|
||||
unsigned int auth_reattempt; /* tracking UMTS resync auth attempts */
|
||||
} gmm_att_req;
|
||||
/* VLR number */
|
||||
uint32_t new_sgsn_addr;
|
||||
/* Authentication Triplet */
|
||||
struct gsm_auth_tuple auth_triplet;
|
||||
/* Kc */
|
||||
/* Iu: CK, IK, KSI */
|
||||
/* CKSN */
|
||||
enum gprs_ciph_algo ciph_algo;
|
||||
uint8_t ue_cipher_mask;
|
||||
/* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
|
||||
uint8_t ac_ref_nr_used;
|
||||
|
||||
struct {
|
||||
uint8_t len;
|
||||
uint8_t buf[50]; /* GSM 04.08 10.5.5.12a, extended in TS 24.008 */
|
||||
} ms_radio_access_capa;
|
||||
/* Supported Codecs (SRVCC) */
|
||||
struct {
|
||||
uint8_t len;
|
||||
uint8_t buf[8]; /* GSM 04.08 10.5.5.12, extended in TS 24.008 */
|
||||
} ms_network_capa;
|
||||
/* UE Netowrk Capability (E-UTRAN) */
|
||||
uint16_t drx_parms;
|
||||
/* Active Time value for PSM */
|
||||
int mnrg; /* MS reported to HLR? */
|
||||
int ngaf; /* MS reported to MSC/VLR? */
|
||||
int ppf; /* paging for GPRS + non-GPRS? */
|
||||
/* Subscribed Charging Characteristics */
|
||||
/* Trace Reference */
|
||||
/* Trace Type */
|
||||
/* Trigger ID */
|
||||
/* OMC Identity */
|
||||
/* SMS Parameters */
|
||||
int recovery;
|
||||
/* Access Restriction */
|
||||
/* GPRS CSI (CAMEL) */
|
||||
/* MG-CSI (CAMEL) */
|
||||
/* Subscribed UE-AMBR */
|
||||
/* UE-AMBR */
|
||||
/* APN Subscribed */
|
||||
|
||||
struct llist_head pdp_list;
|
||||
|
||||
struct rate_ctr_group *ctrg;
|
||||
struct osmo_timer_list timer;
|
||||
unsigned int T; /* Txxxx number */
|
||||
unsigned int num_T_exp; /* number of consecutive T expirations */
|
||||
|
||||
enum gprs_t3350_mode t3350_mode;
|
||||
uint8_t t3370_id_type;
|
||||
uint8_t pending_req; /* the request's message type */
|
||||
/* TODO: There isn't much semantic difference between t3350_mode
|
||||
* (refers to the timer) and pending_req (refers to the procedure),
|
||||
* where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
|
||||
* whether one of them can be dropped. */
|
||||
|
||||
enum sgsn_auth_state auth_state;
|
||||
enum osmo_sub_auth_type sec_ctx;
|
||||
|
||||
/* the string representation of the current hlr */
|
||||
char hlr[GSM_EXTENSION_LENGTH];
|
||||
|
||||
/* the current GGSN look-up operation */
|
||||
struct sgsn_ggsn_lookup *ggsn_lookup;
|
||||
|
||||
struct gprs_subscr *subscr;
|
||||
};
|
||||
|
||||
static inline bool sgsn_mm_ctx_is_authenticated(struct sgsn_mm_ctx *ctx)
|
||||
{
|
||||
switch (ctx->sec_ctx) {
|
||||
case OSMO_AUTH_TYPE_GSM:
|
||||
case OSMO_AUTH_TYPE_UMTS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#define LOGMMCTXP(level, mm, fmt, args...) \
|
||||
LOGP(DMM, level, "MM(%s/%08x) " fmt, (mm) ? (mm)->imsi : "---", \
|
||||
(mm) ? (mm)->p_tmsi : GSM_RESERVED_TMSI, ## args)
|
||||
|
||||
#ifdef BUILD_IU
|
||||
#define LOGIUP(ue, level, fmt, args...) \
|
||||
LOGP(DMM, level, "UE(0x%x){%s} " fmt, (ue) ? (ue)->conn_id : 0xffffffff, \
|
||||
(ue) ? osmo_rai_name(&(ue)->ra_id) : "", ## args)
|
||||
#else
|
||||
#define LOGIUP(ue, level, fmt, args...) \
|
||||
LOGP(DMM, level, "UE(%p){NOTSUPPORTED} " fmt, ue, ## args)
|
||||
#endif
|
||||
|
||||
#define LOGGBP(llme, category, level, fmt, args...) \
|
||||
LOGP(category, level, "LLME(%08x/%08x){%s} " fmt, (llme)->old_tlli, \
|
||||
(llme)->tlli, get_value_string_or_null(gprs_llc_llme_state_names, (llme)->state), ## args);
|
||||
|
||||
#define LOGGBIUP(llme, msg, level, fmt, args...) \
|
||||
do { \
|
||||
struct ranap_ue_conn_ctx * _ue; \
|
||||
if (llme) { \
|
||||
LOGGBP(llme, DMM, level, fmt, ## args); \
|
||||
} else if ((msg) && (_ue = MSG_IU_UE_CTX(msg))) { \
|
||||
LOGIUP(_ue, level, fmt, ## args); \
|
||||
} else { OSMO_ASSERT(0); } \
|
||||
} while (0)
|
||||
|
||||
/* look-up a SGSN MM context based on TLLI + RAI */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
|
||||
const struct osmo_routing_area_id *raid);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_llme(const struct gprs_llc_llme *llme);
|
||||
|
||||
/* look-up by matching TLLI and P-TMSI (think twice before using this) */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
|
||||
const struct osmo_routing_area_id *raid);
|
||||
|
||||
/* Allocate a new SGSN MM context */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
|
||||
const struct osmo_routing_area_id *raid);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx);
|
||||
|
||||
void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx);
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
|
||||
struct tlv_parsed *tp,
|
||||
enum gsm48_gsm_cause *gsm_cause,
|
||||
char *apn_str);
|
||||
|
||||
/* 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);
|
||||
/* look up PDP context by MM context and transaction ID */
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
|
||||
uint8_t tid);
|
||||
|
||||
bool sgsn_mm_ctx_is_r99(const struct sgsn_mm_ctx *mm);
|
||||
|
||||
uint32_t sgsn_alloc_ptmsi(void);
|
||||
|
||||
/* Called on subscriber data updates */
|
||||
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);
|
||||
|
||||
#ifdef BUILD_IU
|
||||
struct RANAP_Cause;
|
||||
void sgsn_mm_ctx_iu_activate_rabs(struct sgsn_mm_ctx *ctx);
|
||||
void sgsn_mm_ctx_iu_ranap_release_free(struct sgsn_mm_ctx *ctx,
|
||||
const struct RANAP_Cause *cause);
|
||||
void sgsn_mm_ctx_iu_ranap_free(struct sgsn_mm_ctx *ctx);
|
||||
#endif /* ifdef BUILD_IU */
|
||||
105
include/osmocom/sgsn/pdpctx.h
Normal file
105
include/osmocom/sgsn/pdpctx.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#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;
|
||||
bool ue_pdp_active; /* PDP Context is active for this NSAPI? */
|
||||
/* Keeps original SGSN local TEID when lib->teid_own is updated with
|
||||
* RNC's TEID upon use of Direct Tunnel feature: */
|
||||
uint32_t sgsn_teid_own;
|
||||
|
||||
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);
|
||||
|
||||
#ifdef BUILD_IU
|
||||
int sgsn_pdp_ctx_iu_rab_activate(struct sgsn_pdp_ctx *pdp, uint8_t rab_id);
|
||||
int sgsn_pdp_ctx_iu_rab_deactivate(struct sgsn_pdp_ctx *pdp, uint8_t rab_id);
|
||||
#endif /* ifdef BUILD_IU */
|
||||
|
||||
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len, bool return_ipv6);
|
||||
|
||||
46
include/osmocom/sgsn/sccp.h
Normal file
46
include/osmocom/sgsn/sccp.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* SCCP Handling */
|
||||
/* (C) 2025 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/sigtran/sccp_sap.h>
|
||||
|
||||
struct sgsn_instance;
|
||||
struct ranap_ue_conn_ctx;
|
||||
|
||||
struct sgsn_sccp_user_iups {
|
||||
struct sgsn_instance *sgsn; /* backpointer */
|
||||
struct osmo_sccp_instance *sccp; /* backpointer */
|
||||
struct osmo_sccp_user *scu; /* IuPS */
|
||||
struct osmo_sccp_addr local_sccp_addr;
|
||||
struct llist_head ue_conn_ctx_list; /* list of "struct ranap_ue_conn_ctx" */
|
||||
struct llist_head ue_conn_sccp_addr_list; /* list of "struct iu_new_ctx_entry" */
|
||||
};
|
||||
|
||||
struct sgsn_sccp_user_iups *sgsn_scu_iups_inst_alloc(struct sgsn_instance *sgsn, struct osmo_sccp_instance *sccp);
|
||||
void sgsn_scu_iups_free(struct sgsn_sccp_user_iups *scu_iups);
|
||||
|
||||
int sgsn_scu_iups_tx_data_req(struct sgsn_sccp_user_iups *scu_iups, uint32_t conn_id, struct msgb *ranap_msg);
|
||||
|
||||
struct ranap_ue_conn_ctx *sgsn_scu_iups_ue_conn_ctx_find(struct sgsn_sccp_user_iups *scu_iups, uint32_t conn_id);
|
||||
|
||||
int sgsn_sccp_init(struct sgsn_instance *sgsn);
|
||||
void sgsn_sccp_release(struct sgsn_instance *sgsn);
|
||||
|
||||
@@ -1,26 +1,36 @@
|
||||
#ifndef _SGSN_H
|
||||
#define _SGSN_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/stat_item.h>
|
||||
#include <osmocom/crypt/gprs_cipher.h>
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.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"
|
||||
|
||||
#if BUILD_IU
|
||||
#include <osmocom/ranap/iu_client.h>
|
||||
#include <osmocom/sigtran/sccp_sap.h>
|
||||
#include <osmocom/sgsn/iu_client.h>
|
||||
#endif
|
||||
|
||||
#include <ares.h>
|
||||
#include <gtp.h>
|
||||
#include <osmocom/gtp/gtp.h>
|
||||
|
||||
struct hostent;
|
||||
|
||||
#define SGSN_ERROR_CAUSE_NONE (-1)
|
||||
|
||||
/* This rac will be used internally. RAC with 0xff will be rejected */
|
||||
#define OSMO_RESERVED_RAC 0xff
|
||||
|
||||
enum sgsn_auth_policy {
|
||||
SGSN_AUTH_POLICY_OPEN,
|
||||
SGSN_AUTH_POLICY_CLOSED,
|
||||
@@ -69,35 +79,28 @@ struct sgsn_config {
|
||||
struct sockaddr_in gtp_listenaddr;
|
||||
|
||||
/* misc */
|
||||
struct gprs_ns_inst *nsi;
|
||||
struct gprs_ns2_inst *nsi;
|
||||
|
||||
char *crypt_cipher_plugin_path;
|
||||
enum sgsn_auth_policy auth_policy;
|
||||
enum gprs_ciph_algo cipher;
|
||||
uint8_t gea_encryption_mask;
|
||||
uint8_t uea_encryption_mask;
|
||||
struct llist_head imsi_acl;
|
||||
|
||||
struct sockaddr_in gsup_server_addr;
|
||||
int gsup_server_port;
|
||||
|
||||
/* Only meaningful if auth_policy is SGSN_AUTH_POLICY_REMOTE */
|
||||
int require_authentication;
|
||||
|
||||
int require_update_location;
|
||||
|
||||
/* CDR configuration */
|
||||
struct sgsn_cdr cdr;
|
||||
|
||||
struct {
|
||||
int T3312;
|
||||
int T3322;
|
||||
int T3350;
|
||||
int T3360;
|
||||
int T3370;
|
||||
int T3313;
|
||||
int T3314;
|
||||
int T3316;
|
||||
int T3385;
|
||||
int T3386;
|
||||
int T3395;
|
||||
int T3397;
|
||||
} timers;
|
||||
/* Timer defintions */
|
||||
struct osmo_tdef *T_defs;
|
||||
struct osmo_tdef *T_defs_gtp;
|
||||
|
||||
int dynamic_lookup;
|
||||
|
||||
@@ -122,6 +125,7 @@ struct sgsn_config {
|
||||
#if BUILD_IU
|
||||
struct {
|
||||
enum ranap_nsap_addr_enc rab_assign_addr_enc;
|
||||
uint32_t cs7_instance;
|
||||
} iu;
|
||||
#endif
|
||||
|
||||
@@ -139,8 +143,6 @@ struct sgsn_instance {
|
||||
struct osmo_fd gtp_fd0;
|
||||
struct osmo_fd gtp_fd1c;
|
||||
struct osmo_fd gtp_fd1u;
|
||||
/* Timer for libGTP */
|
||||
struct osmo_timer_list gtp_timer;
|
||||
/* GSN instance for libgtp */
|
||||
struct gsn_t *gsn;
|
||||
/* Subscriber */
|
||||
@@ -154,10 +156,55 @@ struct sgsn_instance {
|
||||
ares_channel ares_channel;
|
||||
struct ares_addr_node *ares_servers;
|
||||
|
||||
/* Routing areas */
|
||||
struct sgsn_ra_global *routing_area;
|
||||
|
||||
struct rate_ctr_group *rate_ctrs;
|
||||
struct osmo_stat_item_group *statg;
|
||||
|
||||
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 */
|
||||
#if BUILD_IU
|
||||
struct llist_head rnc_list; /* list of struct ranap_iu_rnc */
|
||||
#endif /* if BUILD_IU */
|
||||
|
||||
struct ctrl_handle *ctrlh;
|
||||
|
||||
#if BUILD_IU
|
||||
/* SCCP (Iu) */
|
||||
struct {
|
||||
struct osmo_sccp_instance *sccp;
|
||||
struct sgsn_sccp_user_iups *scu_iups;
|
||||
} sccp;
|
||||
#endif /* if BUILD_IU */
|
||||
};
|
||||
|
||||
extern struct osmo_tdef sgsn_T_defs[];
|
||||
extern struct sgsn_instance *sgsn;
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
enum {
|
||||
SGSN_STAT_IU_PEERS_TOTAL,
|
||||
SGSN_STAT_IU_PEERS_ACTIVE,
|
||||
};
|
||||
static inline void sgsn_stat_inc(unsigned int idx, int32_t value)
|
||||
{
|
||||
osmo_stat_item_inc(osmo_stat_item_group_get_item(sgsn->statg, idx), value);
|
||||
}
|
||||
|
||||
static inline void sgsn_stat_dec(unsigned int idx, int32_t value)
|
||||
{
|
||||
osmo_stat_item_dec(osmo_stat_item_group_get_item(sgsn->statg, idx), value);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ctrl interface related work (sgsn_ctrl.c)
|
||||
*/
|
||||
int sgsn_ctrl_cmds_install(void);
|
||||
|
||||
/* sgsn_vty.c */
|
||||
|
||||
@@ -166,38 +213,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_nsvc *nsvc, uint16_t ns_bvci);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
6
include/osmocom/sgsn/sgsn_rim.h
Normal file
6
include/osmocom/sgsn/sgsn_rim.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
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 msgb *msg, struct bssgp_rim_routing_info *rim_routing_address);
|
||||
@@ -17,10 +17,6 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/*! \page v42bis_page V.42bis modem data compression
|
||||
|
||||
@@ -17,10 +17,6 @@
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_V42BIS_H_)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <osmocom/vty/command.h>
|
||||
|
||||
enum bsc_vty_node {
|
||||
GBPROXY_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
SGSN_NODE,
|
||||
SGSN_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
GTPHUB_NODE,
|
||||
MME_NODE,
|
||||
};
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check whether the given FLAG works with the current language's compiler
|
||||
# or gives an error. (Warnings, however, are ignored)
|
||||
#
|
||||
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
||||
# success/failure.
|
||||
#
|
||||
# If EXTRA-FLAGS is defined, it is added to the current language's default
|
||||
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
|
||||
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
|
||||
# force the compiler to issue an error when a bad flag is given.
|
||||
#
|
||||
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
||||
#
|
||||
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
|
||||
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 4
|
||||
|
||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
||||
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
||||
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
||||
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
||||
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
|
||||
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
|
||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
||||
[AS_VAR_SET(CACHEVAR,[no])])
|
||||
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
|
||||
AS_VAR_IF(CACHEVAR,yes,
|
||||
[m4_default([$2], :)],
|
||||
[m4_default([$3], :)])
|
||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
||||
])dnl AX_CHECK_COMPILE_FLAGS
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# (C) 2013 by Katerina Barone-Adesi <kat.obsc@gmail.com>
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
@@ -16,19 +16,15 @@
|
||||
|
||||
|
||||
app_configs = {
|
||||
"gbproxy": ["doc/examples/osmo-gbproxy/osmo-gbproxy.cfg",
|
||||
"doc/examples/osmo-gbproxy/osmo-gbproxy-legacy.cfg"],
|
||||
"sgsn": ["doc/examples/osmo-sgsn/osmo-sgsn.cfg"],
|
||||
"sgsn": ["tests/osmo-sgsn.cfg"],
|
||||
"gtphub": ["doc/examples/osmo-gtphub/osmo-gtphub-1iface.cfg"]
|
||||
}
|
||||
|
||||
|
||||
apps = [(4246, "src/gprs/osmo-gbproxy", "OsmoGbProxy", "gbproxy"),
|
||||
(4245, "src/gprs/osmo-sgsn", "OsmoSGSN", "sgsn"),
|
||||
(4253, "src/gprs/osmo-gtphub", "OsmoGTPhub", "gtphub")
|
||||
apps = [(4245, "src/sgsn/osmo-sgsn", "OsmoSGSN", "sgsn"),
|
||||
(4253, "src/gtphub/osmo-gtphub", "OsmoGTPhub", "gtphub")
|
||||
]
|
||||
|
||||
vty_command = ["./src/gprs/osmo-sgsn", "-c",
|
||||
"doc/examples/osmo-sgsn/osmo-sgsn.cfg"]
|
||||
vty_command = ["./src/sgsn/osmo-sgsn", "-c", "tests/osmo-sgsn.cfg"]
|
||||
|
||||
vty_app = apps[1]
|
||||
vty_app = apps[0]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
SUBDIRS = \
|
||||
gprs \
|
||||
sgsn \
|
||||
gtphub \
|
||||
$(NULL)
|
||||
|
||||
@@ -26,98 +26,20 @@ AM_CFLAGS += \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
OSMO_LIBS = \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMOVTY_LIBS) \
|
||||
$(LIBOSMOCTRL_LIBS) \
|
||||
$(LIBOSMOGB_LIBS) \
|
||||
$(LIBGTP_LIBS) \
|
||||
$(NULL)
|
||||
noinst_LTLIBRARIES = libcommon.la
|
||||
|
||||
bin_PROGRAMS = \
|
||||
osmo-gbproxy \
|
||||
osmo-sgsn \
|
||||
osmo-gtphub \
|
||||
$(NULL)
|
||||
|
||||
osmo_gbproxy_SOURCES = \
|
||||
gb_proxy.c \
|
||||
gb_proxy_main.c \
|
||||
gb_proxy_vty.c \
|
||||
gb_proxy_ctrl.c \
|
||||
gb_proxy_patch.c \
|
||||
gb_proxy_tlli.c \
|
||||
gb_proxy_peer.c \
|
||||
gprs_gb_parse.c \
|
||||
libcommon_la_SOURCES = \
|
||||
gprs_llc_parse.c \
|
||||
crc24.c \
|
||||
gprs_utils.c \
|
||||
$(NULL)
|
||||
osmo_gbproxy_LDADD = \
|
||||
$(OSMO_LIBS) \
|
||||
-lrt \
|
||||
sgsn_ares.c \
|
||||
$(NULL)
|
||||
|
||||
osmo_sgsn_SOURCES = \
|
||||
gprs_gmm_attach.c \
|
||||
gprs_gmm.c \
|
||||
gprs_sgsn.c \
|
||||
gprs_sndcp.c \
|
||||
gprs_sndcp_comp.c \
|
||||
gprs_sndcp_dcomp.c \
|
||||
gprs_sndcp_pcomp.c \
|
||||
gprs_sndcp_vty.c \
|
||||
gprs_sndcp_xid.c \
|
||||
sgsn_main.c \
|
||||
sgsn_vty.c \
|
||||
sgsn_libgtp.c \
|
||||
gprs_llc.c \
|
||||
gprs_llc_parse.c \
|
||||
gprs_llc_vty.c \
|
||||
crc24.c \
|
||||
sgsn_ctrl.c \
|
||||
sgsn_auth.c \
|
||||
gprs_subscriber.c \
|
||||
gprs_utils.c \
|
||||
sgsn_cdr.c \
|
||||
sgsn_ares.c \
|
||||
slhc.c \
|
||||
gprs_llc_xid.c \
|
||||
v42bis.c \
|
||||
$(NULL)
|
||||
osmo_sgsn_LDADD = \
|
||||
$(OSMO_LIBS) \
|
||||
$(LIBOSMOABIS_LIBS) \
|
||||
$(LIBOSMOGSUPCLIENT_LIBS) \
|
||||
$(LIBCARES_LIBS) \
|
||||
$(LIBGTP_LIBS) \
|
||||
-lrt \
|
||||
-lm \
|
||||
$(NULL)
|
||||
if BUILD_IU
|
||||
osmo_sgsn_LDADD += \
|
||||
$(LIBOSMOSIGTRAN_LIBS) \
|
||||
$(LIBOSMORANAP_LIBS) \
|
||||
$(LIBASN1C_LIBS) \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
osmo_gtphub_SOURCES = \
|
||||
gtphub_main.c \
|
||||
gtphub.c \
|
||||
gtphub_sock.c \
|
||||
gtphub_ares.c \
|
||||
gtphub_vty.c \
|
||||
sgsn_ares.c \
|
||||
gprs_utils.c \
|
||||
$(NULL)
|
||||
osmo_gtphub_LDADD = \
|
||||
libcommon_la_LIBADD = \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMOVTY_LIBS) \
|
||||
$(LIBCARES_LIBS) \
|
||||
$(LIBGTP_LIBS) \
|
||||
$(LIBOSMOSIGTRAN_LIBS) \
|
||||
-lrt \
|
||||
$(LIBCARES_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
@@ -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];
|
||||
|
||||
1454
src/gprs/gb_proxy.c
1454
src/gprs/gb_proxy.c
File diff suppressed because it is too large
Load Diff
@@ -1,98 +0,0 @@
|
||||
/* Control Interface Implementation for the Gb-proxy */
|
||||
/*
|
||||
* (C) 2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Daniel Willmann
|
||||
*
|
||||
* 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/talloc.h>
|
||||
|
||||
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/control_cmd.h>
|
||||
#include <osmocom/sgsn/gb_proxy.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
extern vector ctrl_node_vec;
|
||||
|
||||
static int get_nsvc_state(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
struct gbproxy_config *cfg = data;
|
||||
struct gprs_ns_inst *nsi = cfg->nsi;
|
||||
struct gprs_nsvc *nsvc;
|
||||
|
||||
cmd->reply = talloc_strdup(cmd, "");
|
||||
|
||||
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
|
||||
if (nsvc == nsi->unknown_nsvc)
|
||||
continue;
|
||||
|
||||
cmd->reply = gprs_nsvc_state_append(cmd->reply, nsvc);
|
||||
}
|
||||
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE_RO(nsvc_state, "nsvc-state");
|
||||
|
||||
static int get_gbproxy_state(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
struct gbproxy_config *cfg = data;
|
||||
struct gbproxy_peer *peer;
|
||||
|
||||
cmd->reply = talloc_strdup(cmd, "");
|
||||
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
struct gprs_ra_id raid;
|
||||
gsm48_parse_ra(&raid, peer->ra);
|
||||
|
||||
cmd->reply = talloc_asprintf_append(cmd->reply, "%u,%u,%u,%u,%u,%u,%s\n",
|
||||
peer->nsei, peer->bvci,
|
||||
raid.mcc, raid.mnc,
|
||||
raid.lac, raid.rac,
|
||||
peer->blocked ? "BLOCKED" : "UNBLOCKED");
|
||||
}
|
||||
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE_RO(gbproxy_state, "gbproxy-state");
|
||||
|
||||
static int get_num_peers(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
struct gbproxy_config *cfg = data;
|
||||
|
||||
cmd->reply = talloc_strdup(cmd, "");
|
||||
cmd->reply = talloc_asprintf_append(cmd->reply, "%u", llist_count(&cfg->bts_peers));
|
||||
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
CTRL_CMD_DEFINE_RO(num_peers, "number-of-peers");
|
||||
|
||||
int gb_ctrl_cmds_install(void)
|
||||
{
|
||||
int rc = 0;
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_nsvc_state);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_gbproxy_state);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_num_peers);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1,393 +0,0 @@
|
||||
/* NS-over-IP proxy */
|
||||
|
||||
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 by On-Waves
|
||||
* 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 <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
|
||||
#include <osmocom/sgsn/signal.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/vty.h>
|
||||
#include <osmocom/sgsn/gb_proxy.h>
|
||||
|
||||
#include <osmocom/ctrl/control_vty.h>
|
||||
#include <osmocom/ctrl/control_if.h>
|
||||
#include <osmocom/ctrl/ports.h>
|
||||
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/vty/stats.h>
|
||||
#include <osmocom/vty/ports.h>
|
||||
#include <osmocom/vty/misc.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <getopt.h>
|
||||
|
||||
void *tall_sgsn_ctx;
|
||||
|
||||
const char *openbsc_copyright =
|
||||
"Copyright (C) 2010 Harald Welte and On-Waves\r\n"
|
||||
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
|
||||
"This is free software: you are free to change and redistribute it.\r\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.\r\n";
|
||||
|
||||
#define CONFIG_FILE_DEFAULT "osmo-gbproxy.cfg"
|
||||
#define CONFIG_FILE_LEGACY "osmo_gbproxy.cfg"
|
||||
|
||||
static char *config_file = NULL;
|
||||
struct gbproxy_config *gbcfg;
|
||||
static int daemonize = 0;
|
||||
|
||||
/* Pointer to the SGSN peer */
|
||||
extern struct gbprox_peer *gbprox_peer_sgsn;
|
||||
|
||||
/* call-back function for the NS protocol */
|
||||
static int proxy_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
|
||||
struct msgb *msg, uint16_t bvci)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (event) {
|
||||
case GPRS_NS_EVT_UNIT_DATA:
|
||||
rc = gbprox_rcvmsg(gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
|
||||
break;
|
||||
default:
|
||||
LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event);
|
||||
if (msg)
|
||||
msgb_free(msg);
|
||||
rc = -EIO;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void signal_handler(int signal)
|
||||
{
|
||||
fprintf(stdout, "signal %u received\n", signal);
|
||||
|
||||
switch (signal) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
|
||||
sleep(1);
|
||||
exit(0);
|
||||
break;
|
||||
case SIGABRT:
|
||||
/* in case of abort, we want to obtain a talloc report
|
||||
* and then return to the caller, who will abort the process */
|
||||
case SIGUSR1:
|
||||
talloc_report(tall_vty_ctx, stderr);
|
||||
talloc_report_full(tall_sgsn_ctx, stderr);
|
||||
break;
|
||||
case SIGUSR2:
|
||||
talloc_report_full(tall_vty_ctx, stderr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_usage()
|
||||
{
|
||||
printf("Usage: bsc_hack\n");
|
||||
}
|
||||
|
||||
static void print_help()
|
||||
{
|
||||
printf(" Some useful help...\n");
|
||||
printf(" -h --help this text\n");
|
||||
printf(" -d option --debug=DNS:DGPRS,0:0 enable debugging\n");
|
||||
printf(" -D --daemonize Fork the process into a background daemon\n");
|
||||
printf(" -c --config-file filename The config file to use [%s]\n", CONFIG_FILE_DEFAULT);
|
||||
printf(" -s --disable-color\n");
|
||||
printf(" -T --timestamp Prefix every log line with a timestamp\n");
|
||||
printf(" -V --version. Print the version of OpenBSC.\n");
|
||||
printf(" -e --log-level number. Set a global loglevel.\n");
|
||||
}
|
||||
|
||||
static void handle_options(int argc, char **argv)
|
||||
{
|
||||
while (1) {
|
||||
int option_index = 0, c;
|
||||
static struct option long_options[] = {
|
||||
{ "help", 0, 0, 'h' },
|
||||
{ "debug", 1, 0, 'd' },
|
||||
{ "daemonize", 0, 0, 'D' },
|
||||
{ "config-file", 1, 0, 'c' },
|
||||
{ "disable-color", 0, 0, 's' },
|
||||
{ "timestamp", 0, 0, 'T' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
{ "log-level", 1, 0, 'e' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "hd:Dc:sTVe:",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_usage();
|
||||
print_help();
|
||||
exit(0);
|
||||
case 's':
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
break;
|
||||
case 'd':
|
||||
log_parse_category_mask(osmo_stderr_target, optarg);
|
||||
break;
|
||||
case 'D':
|
||||
daemonize = 1;
|
||||
break;
|
||||
case 'c':
|
||||
config_file = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
log_set_print_timestamp(osmo_stderr_target, 1);
|
||||
break;
|
||||
case 'e':
|
||||
log_set_log_level(osmo_stderr_target, atoi(optarg));
|
||||
break;
|
||||
case 'V':
|
||||
print_version(1);
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int gbproxy_vty_is_config_node(struct vty *vty, int node)
|
||||
{
|
||||
switch (node) {
|
||||
/* add items that are not config */
|
||||
case CONFIG_NODE:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int gbproxy_vty_go_parent(struct vty *vty)
|
||||
{
|
||||
switch (vty->node) {
|
||||
case GBPROXY_NODE:
|
||||
default:
|
||||
if (gbproxy_vty_is_config_node(vty, vty->node))
|
||||
vty->node = CONFIG_NODE;
|
||||
else
|
||||
vty->node = ENABLE_NODE;
|
||||
|
||||
vty->index = NULL;
|
||||
}
|
||||
|
||||
return vty->node;
|
||||
}
|
||||
|
||||
static struct vty_app_info vty_info = {
|
||||
.name = "OsmoGbProxy",
|
||||
.version = PACKAGE_VERSION,
|
||||
.go_parent_cb = gbproxy_vty_go_parent,
|
||||
.is_config_node = gbproxy_vty_is_config_node,
|
||||
};
|
||||
|
||||
/* default categories */
|
||||
static struct log_info_cat gprs_categories[] = {
|
||||
[DGPRS] = {
|
||||
.name = "DGPRS",
|
||||
.description = "GPRS Packet Service",
|
||||
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||
},
|
||||
[DNS] = {
|
||||
.name = "DNS",
|
||||
.description = "GPRS Network Service (NS)",
|
||||
.enabled = 1, .loglevel = LOGL_INFO,
|
||||
},
|
||||
[DBSSGP] = {
|
||||
.name = "DBSSGP",
|
||||
.description = "GPRS BSS Gateway Protocol (BSSGP)",
|
||||
.enabled = 1, .loglevel = LOGL_DEBUG,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct log_info gprs_log_info = {
|
||||
.filter_fn = gprs_log_filter_fn,
|
||||
.cat = gprs_categories,
|
||||
.num_cat = ARRAY_SIZE(gprs_categories),
|
||||
};
|
||||
|
||||
static bool file_exists(const char *path)
|
||||
{
|
||||
struct stat sb;
|
||||
return stat(path, &sb) ? false : true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc;
|
||||
struct ctrl_handle *ctrl;
|
||||
|
||||
tall_sgsn_ctx = talloc_named_const(NULL, 0, "nsip_proxy");
|
||||
msgb_talloc_ctx_init(tall_sgsn_ctx, 0);
|
||||
vty_info.tall_ctx = tall_sgsn_ctx;
|
||||
|
||||
signal(SIGINT, &signal_handler);
|
||||
signal(SIGTERM, &signal_handler);
|
||||
signal(SIGABRT, &signal_handler);
|
||||
signal(SIGUSR1, &signal_handler);
|
||||
signal(SIGUSR2, &signal_handler);
|
||||
osmo_init_ignore_signals();
|
||||
|
||||
osmo_init_logging2(tall_sgsn_ctx, &gprs_log_info);
|
||||
|
||||
vty_info.copyright = openbsc_copyright;
|
||||
vty_init(&vty_info);
|
||||
logging_vty_add_cmds(NULL);
|
||||
osmo_talloc_vty_add_cmds();
|
||||
osmo_stats_vty_add_cmds(&gprs_log_info);
|
||||
gbproxy_vty_init();
|
||||
|
||||
handle_options(argc, argv);
|
||||
|
||||
/* Backwards compatibility: for years, the default config file name was
|
||||
* osmo_gbproxy.cfg. All other Osmocom programs use osmo-*.cfg with a
|
||||
* dash. To be able to use the new config file name without breaking
|
||||
* previous setups that might rely on the legacy default config file
|
||||
* name, we need to look for the old config file if no -c option was
|
||||
* passed AND no file exists with the new default file name. */
|
||||
if (!config_file) {
|
||||
/* No -c option was passed */
|
||||
if (file_exists(CONFIG_FILE_LEGACY)
|
||||
&& !file_exists(CONFIG_FILE_DEFAULT))
|
||||
config_file = CONFIG_FILE_LEGACY;
|
||||
else
|
||||
config_file = CONFIG_FILE_DEFAULT;
|
||||
}
|
||||
|
||||
rate_ctr_init(tall_sgsn_ctx);
|
||||
osmo_stats_init(tall_sgsn_ctx);
|
||||
|
||||
bssgp_nsi = gprs_ns_instantiate(&proxy_ns_cb, tall_sgsn_ctx);
|
||||
if (!bssgp_nsi) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gbcfg = talloc_zero(tall_sgsn_ctx, struct gbproxy_config);
|
||||
if (!gbcfg) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Unable to allocate config\n");
|
||||
exit(1);
|
||||
}
|
||||
gbproxy_init_config(gbcfg);
|
||||
gbcfg->nsi = bssgp_nsi;
|
||||
gprs_ns_vty_init(bssgp_nsi);
|
||||
gprs_ns_set_log_ss(DNS);
|
||||
bssgp_set_log_ss(DBSSGP);
|
||||
osmo_signal_register_handler(SS_L_NS, &gbprox_signal, gbcfg);
|
||||
|
||||
rc = gbproxy_parse_config(config_file, gbcfg);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot parse config file '%s'\n", config_file);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* 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_GBPROXY);
|
||||
if (rc < 0)
|
||||
exit(1);
|
||||
|
||||
/* Start control interface after getting config for
|
||||
* ctrl_vty_get_bind_addr() */
|
||||
ctrl = ctrl_interface_setup_dynip(gbcfg, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_GBPROXY, NULL);
|
||||
if (!ctrl) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Failed to create CTRL interface.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (gb_ctrl_cmds_install() != 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Failed to install CTRL commands.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!gprs_nsvc_by_nsei(gbcfg->nsi, gbcfg->nsip_sgsn_nsei)) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "You cannot proxy to NSEI %u "
|
||||
"without creating that NSEI before\n",
|
||||
gbcfg->nsip_sgsn_nsei);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
rc = gprs_ns_nsip_listen(bssgp_nsi);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
rc = gprs_ns_frgre_listen(bssgp_nsi);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen GRE "
|
||||
"socket. Do you have CAP_NET_RAW?\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (daemonize) {
|
||||
rc = osmo_daemonize();
|
||||
if (rc < 0) {
|
||||
perror("Error during daemonize");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset all the persistent NS-VCs that we've read from the config */
|
||||
gbprox_reset_persistent_nsvcs(bssgp_nsi);
|
||||
|
||||
while (1) {
|
||||
rc = osmo_select_main(0);
|
||||
if (rc < 0)
|
||||
exit(3);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -1,465 +0,0 @@
|
||||
/* Gb-proxy message patching */
|
||||
|
||||
/* (C) 2014 by On-Waves
|
||||
* 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/sgsn/gb_proxy.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
#include <osmocom/sgsn/gprs_gb_parse.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
#include <osmocom/gprs/protocol/gsm_08_18.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
/* patch RA identifier in place */
|
||||
static void gbproxy_patch_raid(struct gsm48_ra_id *raid_enc, struct gbproxy_peer *peer,
|
||||
int to_bss, const char *log_text)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
struct osmo_plmn_id old_plmn;
|
||||
struct gprs_ra_id raid;
|
||||
enum gbproxy_peer_ctr counter =
|
||||
to_bss ?
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_SGSN :
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_BSS;
|
||||
|
||||
if (!state->local_plmn.mcc || !state->local_plmn.mnc)
|
||||
return;
|
||||
|
||||
gsm48_parse_ra(&raid, (uint8_t *)raid_enc);
|
||||
|
||||
old_plmn = (struct osmo_plmn_id){
|
||||
.mcc = raid.mcc,
|
||||
.mnc = raid.mnc,
|
||||
.mnc_3_digits = raid.mnc_3_digits,
|
||||
};
|
||||
|
||||
if (!to_bss) {
|
||||
/* BSS -> SGSN */
|
||||
if (state->local_plmn.mcc)
|
||||
raid.mcc = peer->cfg->core_plmn.mcc;
|
||||
|
||||
if (state->local_plmn.mnc) {
|
||||
raid.mnc = peer->cfg->core_plmn.mnc;
|
||||
raid.mnc_3_digits = peer->cfg->core_plmn.mnc_3_digits;
|
||||
}
|
||||
} else {
|
||||
/* SGSN -> BSS */
|
||||
if (state->local_plmn.mcc)
|
||||
raid.mcc = state->local_plmn.mcc;
|
||||
|
||||
if (state->local_plmn.mnc) {
|
||||
raid.mnc = state->local_plmn.mnc;
|
||||
raid.mnc_3_digits = state->local_plmn.mnc_3_digits;
|
||||
}
|
||||
}
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %s to %s: "
|
||||
"%s-%d-%d -> %s\n",
|
||||
log_text,
|
||||
to_bss ? "BSS" : "SGSN",
|
||||
osmo_plmn_name(&old_plmn), raid.lac, raid.rac,
|
||||
osmo_rai_name(&raid));
|
||||
|
||||
gsm48_encode_ra(raid_enc, &raid);
|
||||
rate_ctr_inc(&peer->ctrg->ctr[counter]);
|
||||
}
|
||||
|
||||
static void gbproxy_patch_apn_ie(struct msgb *msg,
|
||||
uint8_t *apn_ie, size_t apn_ie_len,
|
||||
struct gbproxy_peer *peer,
|
||||
size_t *new_apn_ie_len, const char *log_text)
|
||||
{
|
||||
struct apn_ie_hdr {
|
||||
uint8_t iei;
|
||||
uint8_t apn_len;
|
||||
uint8_t apn[0];
|
||||
} *hdr = (void *)apn_ie;
|
||||
|
||||
size_t apn_len = hdr->apn_len;
|
||||
uint8_t *apn = hdr->apn;
|
||||
|
||||
OSMO_ASSERT(apn_ie_len == apn_len + sizeof(struct apn_ie_hdr));
|
||||
OSMO_ASSERT(apn_ie_len > 2 && apn_ie_len <= 102);
|
||||
|
||||
if (peer->cfg->core_apn_size == 0) {
|
||||
char str1[110];
|
||||
/* Remove the IE */
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %s to SGSN: Removing APN '%s'\n",
|
||||
log_text,
|
||||
osmo_apn_to_str(str1, apn, apn_len));
|
||||
|
||||
*new_apn_ie_len = 0;
|
||||
msgb_resize_area(msg, apn_ie, apn_ie_len, 0);
|
||||
} else {
|
||||
/* Resize the IE */
|
||||
char str1[110];
|
||||
char str2[110];
|
||||
|
||||
OSMO_ASSERT(peer->cfg->core_apn_size <= 100);
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %s to SGSN: "
|
||||
"Replacing APN '%s' -> '%s'\n",
|
||||
log_text,
|
||||
osmo_apn_to_str(str1, apn, apn_len),
|
||||
osmo_apn_to_str(str2, peer->cfg->core_apn,
|
||||
peer->cfg->core_apn_size));
|
||||
|
||||
*new_apn_ie_len = peer->cfg->core_apn_size + 2;
|
||||
msgb_resize_area(msg, apn, apn_len, peer->cfg->core_apn_size);
|
||||
memcpy(apn, peer->cfg->core_apn, peer->cfg->core_apn_size);
|
||||
hdr->apn_len = peer->cfg->core_apn_size;
|
||||
}
|
||||
|
||||
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_APN_PATCHED]);
|
||||
}
|
||||
|
||||
static int gbproxy_patch_tlli(uint8_t *tlli_enc,
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t new_tlli,
|
||||
int to_bss, const char *log_text)
|
||||
{
|
||||
uint32_t tlli_be;
|
||||
uint32_t tlli;
|
||||
enum gbproxy_peer_ctr counter =
|
||||
to_bss ?
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_SGSN :
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_BSS;
|
||||
|
||||
memcpy(&tlli_be, tlli_enc, sizeof(tlli_be));
|
||||
tlli = ntohl(tlli_be);
|
||||
|
||||
if (tlli == new_tlli)
|
||||
return 0;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %ss: "
|
||||
"Replacing %08x -> %08x\n",
|
||||
log_text, tlli, new_tlli);
|
||||
|
||||
tlli_be = htonl(new_tlli);
|
||||
memcpy(tlli_enc, &tlli_be, sizeof(tlli_be));
|
||||
|
||||
rate_ctr_inc(&peer->ctrg->ctr[counter]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gbproxy_patch_ptmsi(uint8_t *ptmsi_enc,
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t new_ptmsi,
|
||||
int to_bss, const char *log_text)
|
||||
{
|
||||
uint32_t ptmsi_be;
|
||||
uint32_t ptmsi;
|
||||
enum gbproxy_peer_ctr counter =
|
||||
to_bss ?
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN :
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_BSS;
|
||||
memcpy(&ptmsi_be, ptmsi_enc, sizeof(ptmsi_be));
|
||||
ptmsi = ntohl(ptmsi_be);
|
||||
|
||||
if (ptmsi == new_ptmsi)
|
||||
return 0;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %ss: "
|
||||
"Replacing %08x -> %08x\n",
|
||||
log_text, ptmsi, new_ptmsi);
|
||||
|
||||
ptmsi_be = htonl(new_ptmsi);
|
||||
memcpy(ptmsi_enc, &ptmsi_be, sizeof(ptmsi_be));
|
||||
|
||||
rate_ctr_inc(&peer->ctrg->ctr[counter]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gbproxy_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info, int *len_change,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
|
||||
int have_patched = 0;
|
||||
int fcs;
|
||||
struct gbproxy_config *cfg = peer->cfg;
|
||||
|
||||
if (parse_ctx->ptmsi_enc && link_info &&
|
||||
!parse_ctx->old_raid_is_foreign && peer->cfg->patch_ptmsi) {
|
||||
uint32_t ptmsi;
|
||||
if (parse_ctx->to_bss)
|
||||
ptmsi = link_info->tlli.ptmsi;
|
||||
else
|
||||
ptmsi = link_info->sgsn_tlli.ptmsi;
|
||||
|
||||
if (ptmsi != GSM_RESERVED_TMSI) {
|
||||
if (gbproxy_patch_ptmsi(parse_ctx->ptmsi_enc, peer,
|
||||
ptmsi, parse_ctx->to_bss, "P-TMSI"))
|
||||
have_patched = 1;
|
||||
} else {
|
||||
/* TODO: invalidate old RAI if present (see below) */
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_ctx->new_ptmsi_enc && link_info && cfg->patch_ptmsi) {
|
||||
uint32_t ptmsi;
|
||||
if (parse_ctx->to_bss)
|
||||
ptmsi = link_info->tlli.ptmsi;
|
||||
else
|
||||
ptmsi = link_info->sgsn_tlli.ptmsi;
|
||||
|
||||
OSMO_ASSERT(ptmsi);
|
||||
if (gbproxy_patch_ptmsi(parse_ctx->new_ptmsi_enc, peer,
|
||||
ptmsi, parse_ctx->to_bss, "new P-TMSI"))
|
||||
have_patched = 1;
|
||||
}
|
||||
|
||||
if (parse_ctx->raid_enc) {
|
||||
gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->raid_enc, peer, parse_ctx->to_bss,
|
||||
parse_ctx->llc_msg_name);
|
||||
have_patched = 1;
|
||||
}
|
||||
|
||||
if (parse_ctx->old_raid_enc && !parse_ctx->old_raid_is_foreign) {
|
||||
/* TODO: Patch to invalid if P-TMSI unknown. */
|
||||
gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->old_raid_enc, peer, parse_ctx->to_bss,
|
||||
parse_ctx->llc_msg_name);
|
||||
have_patched = 1;
|
||||
}
|
||||
|
||||
if (parse_ctx->apn_ie &&
|
||||
cfg->core_apn &&
|
||||
!parse_ctx->to_bss &&
|
||||
gbproxy_imsi_matches(cfg, GBPROX_MATCH_PATCHING, link_info) &&
|
||||
cfg->core_apn) {
|
||||
size_t new_len;
|
||||
gbproxy_patch_apn_ie(msg,
|
||||
parse_ctx->apn_ie, parse_ctx->apn_ie_len,
|
||||
peer, &new_len, parse_ctx->llc_msg_name);
|
||||
*len_change += (int)new_len - (int)parse_ctx->apn_ie_len;
|
||||
|
||||
have_patched = 1;
|
||||
}
|
||||
|
||||
if (have_patched) {
|
||||
llc_len += *len_change;
|
||||
ghp->crc_length += *len_change;
|
||||
|
||||
/* Fix FCS */
|
||||
fcs = gprs_llc_fcs(llc, ghp->crc_length);
|
||||
LOGP(DLLC, LOGL_DEBUG, "Updated LLC message, CRC: %06x -> %06x\n",
|
||||
ghp->fcs, fcs);
|
||||
|
||||
llc[llc_len - 3] = fcs & 0xff;
|
||||
llc[llc_len - 2] = (fcs >> 8) & 0xff;
|
||||
llc[llc_len - 1] = (fcs >> 16) & 0xff;
|
||||
}
|
||||
|
||||
return have_patched;
|
||||
}
|
||||
|
||||
/* patch BSSGP message to use core_plmn.mcc/mnc on the SGSN side */
|
||||
void gbproxy_patch_bssgp(struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
|
||||
struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info, int *len_change,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
const char *err_info = NULL;
|
||||
int err_ctr = -1;
|
||||
|
||||
if (parse_ctx->bssgp_raid_enc)
|
||||
gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->bssgp_raid_enc, peer,
|
||||
parse_ctx->to_bss, "BSSGP");
|
||||
|
||||
if (parse_ctx->need_decryption &&
|
||||
(peer->cfg->patch_ptmsi || peer->cfg->core_apn)) {
|
||||
/* Patching LLC messages has been requested
|
||||
* explicitly, but the message (including the
|
||||
* type) is encrypted, so we possibly fail to
|
||||
* patch the LLC part of the message. */
|
||||
err_ctr = GBPROX_PEER_CTR_PATCH_CRYPT_ERR;
|
||||
err_info = "GMM message is encrypted";
|
||||
goto patch_error;
|
||||
}
|
||||
|
||||
if (!link_info && parse_ctx->tlli_enc && parse_ctx->to_bss) {
|
||||
/* Happens with unknown (not cached) TLLI coming from
|
||||
* the SGSN */
|
||||
/* TODO: What shall be done with the message in this case? */
|
||||
err_ctr = GBPROX_PEER_CTR_TLLI_UNKNOWN;
|
||||
err_info = "TLLI sent by the SGSN is unknown";
|
||||
goto patch_error;
|
||||
}
|
||||
|
||||
if (!link_info)
|
||||
return;
|
||||
|
||||
if (parse_ctx->tlli_enc && peer->cfg->patch_ptmsi) {
|
||||
uint32_t tlli = gbproxy_map_tlli(parse_ctx->tlli,
|
||||
link_info, parse_ctx->to_bss);
|
||||
|
||||
if (tlli) {
|
||||
gbproxy_patch_tlli(parse_ctx->tlli_enc, peer, tlli,
|
||||
parse_ctx->to_bss, "TLLI");
|
||||
parse_ctx->tlli = tlli;
|
||||
} else {
|
||||
/* Internal error */
|
||||
err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
|
||||
err_info = "Replacement TLLI is 0";
|
||||
goto patch_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_ctx->bssgp_ptmsi_enc && peer->cfg->patch_ptmsi) {
|
||||
uint32_t ptmsi;
|
||||
if (parse_ctx->to_bss)
|
||||
ptmsi = link_info->tlli.ptmsi;
|
||||
else
|
||||
ptmsi = link_info->sgsn_tlli.ptmsi;
|
||||
|
||||
if (ptmsi != GSM_RESERVED_TMSI)
|
||||
gbproxy_patch_ptmsi(
|
||||
parse_ctx->bssgp_ptmsi_enc, peer,
|
||||
ptmsi, parse_ctx->to_bss, "BSSGP P-TMSI");
|
||||
}
|
||||
|
||||
if (parse_ctx->llc) {
|
||||
uint8_t *llc = parse_ctx->llc;
|
||||
size_t llc_len = parse_ctx->llc_len;
|
||||
int llc_len_change = 0;
|
||||
|
||||
gbproxy_patch_llc(msg, llc, llc_len, peer, link_info,
|
||||
&llc_len_change, parse_ctx);
|
||||
/* Note that the APN might have been resized here, but no
|
||||
* pointer int the parse_ctx will refer to an adress after the
|
||||
* APN. So it's possible to patch first and do the TLLI
|
||||
* handling afterwards. */
|
||||
|
||||
if (llc_len_change) {
|
||||
llc_len += llc_len_change;
|
||||
|
||||
/* Fix LLC IE len */
|
||||
/* TODO: This is a kludge, but the a pointer to the
|
||||
* start of the IE is not available here */
|
||||
if (llc[-2] == BSSGP_IE_LLC_PDU && llc[-1] & 0x80) {
|
||||
/* most probably a one byte length */
|
||||
if (llc_len > 127) {
|
||||
err_info = "Cannot increase size";
|
||||
err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
|
||||
goto patch_error;
|
||||
}
|
||||
llc[-1] = llc_len | 0x80;
|
||||
} else {
|
||||
llc[-2] = (llc_len >> 8) & 0x7f;
|
||||
llc[-1] = llc_len & 0xff;
|
||||
}
|
||||
*len_change += llc_len_change;
|
||||
}
|
||||
/* Note that the tp struct might contain invalid pointers here
|
||||
* if the LLC field has changed its size */
|
||||
parse_ctx->llc_len = llc_len;
|
||||
}
|
||||
return;
|
||||
|
||||
patch_error:
|
||||
OSMO_ASSERT(err_ctr >= 0);
|
||||
rate_ctr_inc(&peer->ctrg->ctr[err_ctr]);
|
||||
LOGP(DGPRS, LOGL_ERROR,
|
||||
"NSEI=%u(%s) failed to patch BSSGP message as requested: %s.\n",
|
||||
msgb_nsei(msg), parse_ctx->to_bss ? "SGSN" : "BSS",
|
||||
err_info);
|
||||
}
|
||||
|
||||
void gbproxy_clear_patch_filter(struct gbproxy_match *match)
|
||||
{
|
||||
if (match->enable) {
|
||||
regfree(&match->re_comp);
|
||||
match->enable = 0;
|
||||
}
|
||||
talloc_free(match->re_str);
|
||||
match->re_str = NULL;
|
||||
}
|
||||
|
||||
int gbproxy_set_patch_filter(struct gbproxy_match *match, const char *filter,
|
||||
const char **err_msg)
|
||||
{
|
||||
static char err_buf[300];
|
||||
int rc;
|
||||
|
||||
gbproxy_clear_patch_filter(match);
|
||||
|
||||
if (!filter)
|
||||
return 0;
|
||||
|
||||
rc = regcomp(&match->re_comp, filter,
|
||||
REG_EXTENDED | REG_NOSUB | REG_ICASE);
|
||||
|
||||
if (rc == 0) {
|
||||
match->enable = 1;
|
||||
match->re_str = talloc_strdup(tall_sgsn_ctx, filter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (err_msg) {
|
||||
regerror(rc, &match->re_comp,
|
||||
err_buf, sizeof(err_buf));
|
||||
*err_msg = err_buf;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gbproxy_check_imsi(struct gbproxy_match *match,
|
||||
const uint8_t *imsi, size_t imsi_len)
|
||||
{
|
||||
char mi_buf[200];
|
||||
int rc;
|
||||
|
||||
if (!match->enable)
|
||||
return 1;
|
||||
|
||||
rc = gprs_is_mi_imsi(imsi, imsi_len);
|
||||
if (rc > 0)
|
||||
rc = gsm48_mi_to_string(mi_buf, sizeof(mi_buf), imsi, imsi_len);
|
||||
if (rc <= 0) {
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Invalid IMSI %s\n",
|
||||
osmo_hexdump(imsi, imsi_len));
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG, "Checking IMSI '%s' (%d)\n", mi_buf, rc);
|
||||
|
||||
rc = regexec(&match->re_comp, mi_buf, 0, NULL, 0);
|
||||
if (rc == REG_NOMATCH) {
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"IMSI '%s' doesn't match pattern '%s'\n",
|
||||
mi_buf, match->re_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
/* Gb proxy peer handling */
|
||||
|
||||
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010-2013 by On-Waves
|
||||
* (C) 2013 by Holger Hans Peter Freyther
|
||||
* 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/sgsn/gb_proxy.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
#include <osmocom/gprs/protocol/gsm_08_18.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
static const struct rate_ctr_desc peer_ctr_description[] = {
|
||||
{ "blocked", "BVC Block " },
|
||||
{ "unblocked", "BVC Unblock " },
|
||||
{ "dropped", "BVC blocked, dropped packet " },
|
||||
{ "inv-nsei", "NSEI mismatch " },
|
||||
{ "tx-err", "NS Transmission error " },
|
||||
{ "raid-mod:bss", "RAID patched (BSS )" },
|
||||
{ "raid-mod:sgsn", "RAID patched (SGSN)" },
|
||||
{ "apn-mod:sgsn", "APN patched " },
|
||||
{ "tlli-mod:bss", "TLLI patched (BSS )" },
|
||||
{ "tlli-mod:sgsn", "TLLI patched (SGSN)" },
|
||||
{ "ptmsi-mod:bss", "P-TMSI patched (BSS )" },
|
||||
{ "ptmsi-mod:sgsn","P-TMSI patched (SGSN)" },
|
||||
{ "mod-crypt-err", "Patch error: encrypted " },
|
||||
{ "mod-err", "Patch error: other " },
|
||||
{ "attach-reqs", "Attach Request count " },
|
||||
{ "attach-rejs", "Attach Reject count " },
|
||||
{ "attach-acks", "Attach Accept count " },
|
||||
{ "attach-cpls", "Attach Completed count " },
|
||||
{ "ra-upd-reqs", "RoutingArea Update Request count" },
|
||||
{ "ra-upd-rejs", "RoutingArea Update Reject count " },
|
||||
{ "ra-upd-acks", "RoutingArea Update Accept count " },
|
||||
{ "ra-upd-cpls", "RoutingArea Update Compltd count" },
|
||||
{ "gmm-status", "GMM Status count (BSS)" },
|
||||
{ "gmm-status", "GMM Status count (SGSN)" },
|
||||
{ "detach-reqs", "Detach Request count " },
|
||||
{ "detach-acks", "Detach Accept count " },
|
||||
{ "pdp-act-reqs", "PDP Activation Request count " },
|
||||
{ "pdp-act-rejs", "PDP Activation Reject count " },
|
||||
{ "pdp-act-acks", "PDP Activation Accept count " },
|
||||
{ "pdp-deact-reqs","PDP Deactivation Request count " },
|
||||
{ "pdp-deact-acks","PDP Deactivation Accept count " },
|
||||
{ "tlli-unknown", "TLLI from SGSN unknown " },
|
||||
{ "tlli-cache", "TLLI cache size " },
|
||||
};
|
||||
|
||||
osmo_static_assert(ARRAY_SIZE(peer_ctr_description) == GBPROX_PEER_CTR_LAST, everything_described);
|
||||
|
||||
static const struct rate_ctr_group_desc peer_ctrg_desc = {
|
||||
.group_name_prefix = "gbproxy:peer",
|
||||
.group_description = "GBProxy Peer Statistics",
|
||||
.num_ctr = ARRAY_SIZE(peer_ctr_description),
|
||||
.ctr_desc = peer_ctr_description,
|
||||
.class_id = OSMO_STATS_CLASS_PEER,
|
||||
};
|
||||
|
||||
|
||||
/* Find the gbprox_peer by its BVCI */
|
||||
struct gbproxy_peer *gbproxy_peer_by_bvci(struct gbproxy_config *cfg, uint16_t bvci)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (peer->bvci == bvci)
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find the gbprox_peer by its NSEI */
|
||||
struct gbproxy_peer *gbproxy_peer_by_nsei(struct gbproxy_config *cfg,
|
||||
uint16_t nsei)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (peer->nsei == nsei)
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up a peer by its Routeing Area Identification (RAI) */
|
||||
struct gbproxy_peer *gbproxy_peer_by_rai(struct gbproxy_config *cfg,
|
||||
const uint8_t *ra)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (!memcmp(peer->ra, ra, 6))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up a peer by its Location Area Identification (LAI) */
|
||||
struct gbproxy_peer *gbproxy_peer_by_lai(struct gbproxy_config *cfg,
|
||||
const uint8_t *la)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (!memcmp(peer->ra, la, 5))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up a peer by its Location Area Code (LAC) */
|
||||
struct gbproxy_peer *gbproxy_peer_by_lac(struct gbproxy_config *cfg,
|
||||
const uint8_t *la)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (!memcmp(peer->ra + 3, la + 3, 2))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(struct gbproxy_config *cfg,
|
||||
struct tlv_parsed *tp)
|
||||
{
|
||||
if (TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {
|
||||
uint16_t bvci;
|
||||
|
||||
bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI));
|
||||
if (bvci >= 2)
|
||||
return gbproxy_peer_by_bvci(cfg, bvci);
|
||||
}
|
||||
|
||||
if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
|
||||
uint8_t *rai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
|
||||
/* Only compare LAC part, since MCC/MNC are possibly patched.
|
||||
* Since the LAC of different BSS must be different when
|
||||
* MCC/MNC are patched, collisions shouldn't happen. */
|
||||
return gbproxy_peer_by_lac(cfg, rai);
|
||||
}
|
||||
|
||||
if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) {
|
||||
uint8_t *lai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA);
|
||||
return gbproxy_peer_by_lac(cfg, lai);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void clean_stale_timer_cb(void *data)
|
||||
{
|
||||
time_t now;
|
||||
struct timespec ts = {0,};
|
||||
struct gbproxy_peer *peer = (struct gbproxy_peer *) data;
|
||||
|
||||
osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ts.tv_sec;
|
||||
gbproxy_remove_stale_link_infos(peer, now);
|
||||
if (peer->cfg->clean_stale_timer_freq != 0)
|
||||
osmo_timer_schedule(&peer->clean_stale_timer,
|
||||
peer->cfg->clean_stale_timer_freq, 0);
|
||||
}
|
||||
|
||||
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
|
||||
peer = talloc_zero(tall_sgsn_ctx, struct gbproxy_peer);
|
||||
if (!peer)
|
||||
return NULL;
|
||||
|
||||
peer->bvci = bvci;
|
||||
peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci);
|
||||
if (!peer->ctrg) {
|
||||
talloc_free(peer);
|
||||
return NULL;
|
||||
}
|
||||
peer->cfg = cfg;
|
||||
|
||||
llist_add(&peer->list, &cfg->bts_peers);
|
||||
|
||||
INIT_LLIST_HEAD(&peer->patch_state.logical_links);
|
||||
|
||||
osmo_timer_setup(&peer->clean_stale_timer, clean_stale_timer_cb, peer);
|
||||
if (peer->cfg->clean_stale_timer_freq != 0)
|
||||
osmo_timer_schedule(&peer->clean_stale_timer,
|
||||
peer->cfg->clean_stale_timer_freq, 0);
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
void gbproxy_peer_free(struct gbproxy_peer *peer)
|
||||
{
|
||||
llist_del(&peer->list);
|
||||
osmo_timer_del(&peer->clean_stale_timer);
|
||||
gbproxy_delete_link_infos(peer);
|
||||
|
||||
rate_ctr_group_free(peer->ctrg);
|
||||
peer->ctrg = NULL;
|
||||
|
||||
talloc_free(peer);
|
||||
}
|
||||
|
||||
int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci)
|
||||
{
|
||||
int counter = 0;
|
||||
struct gbproxy_peer *peer, *tmp;
|
||||
|
||||
llist_for_each_entry_safe(peer, tmp, &cfg->bts_peers, list) {
|
||||
if (peer->nsei != nsei)
|
||||
continue;
|
||||
if (bvci && peer->bvci != bvci)
|
||||
continue;
|
||||
|
||||
gbproxy_peer_free(peer);
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
@@ -1,723 +0,0 @@
|
||||
/* Gb-proxy TLLI state handling */
|
||||
|
||||
/* (C) 2014 by On-Waves
|
||||
* 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/gsm/gsm48.h>
|
||||
|
||||
#include <osmocom/sgsn/gb_proxy.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
#include <osmocom/sgsn/gprs_gb_parse.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_tlli(struct gbproxy_peer *peer,
|
||||
uint32_t tlli)
|
||||
{
|
||||
struct gbproxy_link_info *link_info;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
if (!tlli)
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(link_info, &state->logical_links, list)
|
||||
if (link_info->tlli.current == tlli ||
|
||||
link_info->tlli.assigned == tlli)
|
||||
return link_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_ptmsi(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t ptmsi)
|
||||
{
|
||||
struct gbproxy_link_info *link_info;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
if (ptmsi == GSM_RESERVED_TMSI)
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(link_info, &state->logical_links, list)
|
||||
if (link_info->tlli.ptmsi == ptmsi)
|
||||
return link_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_any_sgsn_tlli(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t tlli)
|
||||
{
|
||||
struct gbproxy_link_info *link_info;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
if (!tlli)
|
||||
return NULL;
|
||||
|
||||
/* Don't care about the NSEI */
|
||||
llist_for_each_entry(link_info, &state->logical_links, list)
|
||||
if (link_info->sgsn_tlli.current == tlli ||
|
||||
link_info->sgsn_tlli.assigned == tlli)
|
||||
return link_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_sgsn_tlli(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t tlli, uint32_t sgsn_nsei)
|
||||
{
|
||||
struct gbproxy_link_info *link_info;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
if (!tlli)
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(link_info, &state->logical_links, list)
|
||||
if ((link_info->sgsn_tlli.current == tlli ||
|
||||
link_info->sgsn_tlli.assigned == tlli) &&
|
||||
link_info->sgsn_nsei == sgsn_nsei)
|
||||
return link_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_imsi(
|
||||
struct gbproxy_peer *peer,
|
||||
const uint8_t *imsi,
|
||||
size_t imsi_len)
|
||||
{
|
||||
struct gbproxy_link_info *link_info;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
if (!gprs_is_mi_imsi(imsi, imsi_len))
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(link_info, &state->logical_links, list) {
|
||||
if (link_info->imsi_len != imsi_len)
|
||||
continue;
|
||||
if (memcmp(link_info->imsi, imsi, imsi_len) != 0)
|
||||
continue;
|
||||
|
||||
return link_info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void gbproxy_link_info_discard_messages(struct gbproxy_link_info *link_info)
|
||||
{
|
||||
struct msgb *msg, *nxt;
|
||||
|
||||
llist_for_each_entry_safe(msg, nxt, &link_info->stored_msgs, list) {
|
||||
llist_del(&msg->list);
|
||||
msgb_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void gbproxy_delete_link_info(struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
gbproxy_link_info_discard_messages(link_info);
|
||||
|
||||
llist_del(&link_info->list);
|
||||
talloc_free(link_info);
|
||||
state->logical_link_count -= 1;
|
||||
|
||||
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
|
||||
state->logical_link_count;
|
||||
}
|
||||
|
||||
void gbproxy_delete_link_infos(struct gbproxy_peer *peer)
|
||||
{
|
||||
struct gbproxy_link_info *link_info, *nxt;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list)
|
||||
gbproxy_delete_link_info(peer, link_info);
|
||||
|
||||
OSMO_ASSERT(state->logical_link_count == 0);
|
||||
OSMO_ASSERT(llist_empty(&state->logical_links));
|
||||
}
|
||||
|
||||
void gbproxy_attach_link_info(struct gbproxy_peer *peer, time_t now,
|
||||
struct gbproxy_link_info *link_info)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
link_info->timestamp = now;
|
||||
llist_add(&link_info->list, &state->logical_links);
|
||||
state->logical_link_count += 1;
|
||||
|
||||
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
|
||||
state->logical_link_count;
|
||||
}
|
||||
|
||||
int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
int exceeded_max_len = 0;
|
||||
int deleted_count = 0;
|
||||
int check_for_age;
|
||||
|
||||
if (peer->cfg->tlli_max_len > 0)
|
||||
exceeded_max_len =
|
||||
state->logical_link_count - peer->cfg->tlli_max_len;
|
||||
|
||||
check_for_age = peer->cfg->tlli_max_age > 0;
|
||||
|
||||
for (; exceeded_max_len > 0; exceeded_max_len--) {
|
||||
struct gbproxy_link_info *link_info;
|
||||
OSMO_ASSERT(!llist_empty(&state->logical_links));
|
||||
link_info = llist_entry(state->logical_links.prev,
|
||||
struct gbproxy_link_info,
|
||||
list);
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list "
|
||||
"(stale, length %d, max_len exceeded)\n",
|
||||
link_info->tlli.current, state->logical_link_count);
|
||||
|
||||
gbproxy_delete_link_info(peer, link_info);
|
||||
deleted_count += 1;
|
||||
}
|
||||
|
||||
while (check_for_age && !llist_empty(&state->logical_links)) {
|
||||
time_t age;
|
||||
struct gbproxy_link_info *link_info;
|
||||
link_info = llist_entry(state->logical_links.prev,
|
||||
struct gbproxy_link_info,
|
||||
list);
|
||||
age = now - link_info->timestamp;
|
||||
/* age < 0 only happens after system time jumps, discard entry */
|
||||
if (age <= peer->cfg->tlli_max_age && age >= 0) {
|
||||
check_for_age = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list "
|
||||
"(stale, age %d, max_age exceeded)\n",
|
||||
link_info->tlli.current, (int)age);
|
||||
|
||||
gbproxy_delete_link_info(peer, link_info);
|
||||
deleted_count += 1;
|
||||
}
|
||||
|
||||
return deleted_count;
|
||||
}
|
||||
|
||||
struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_peer *peer)
|
||||
{
|
||||
struct gbproxy_link_info *link_info;
|
||||
|
||||
link_info = talloc_zero(peer, struct gbproxy_link_info);
|
||||
link_info->tlli.ptmsi = GSM_RESERVED_TMSI;
|
||||
link_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
|
||||
|
||||
link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
|
||||
|
||||
INIT_LLIST_HEAD(&link_info->stored_msgs);
|
||||
|
||||
return link_info;
|
||||
}
|
||||
|
||||
void gbproxy_detach_link_info(
|
||||
struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
llist_del(&link_info->list);
|
||||
OSMO_ASSERT(state->logical_link_count > 0);
|
||||
state->logical_link_count -= 1;
|
||||
|
||||
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
|
||||
state->logical_link_count;
|
||||
}
|
||||
|
||||
void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
|
||||
const uint8_t *imsi, size_t imsi_len)
|
||||
{
|
||||
if (!gprs_is_mi_imsi(imsi, imsi_len))
|
||||
return;
|
||||
|
||||
link_info->imsi_len = imsi_len;
|
||||
link_info->imsi =
|
||||
talloc_realloc_size(link_info, link_info->imsi, imsi_len);
|
||||
OSMO_ASSERT(link_info->imsi != NULL);
|
||||
memcpy(link_info->imsi, imsi, imsi_len);
|
||||
}
|
||||
|
||||
void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
|
||||
struct gbproxy_peer *peer, uint32_t new_tlli)
|
||||
{
|
||||
if (new_tlli == tlli_state->current)
|
||||
return;
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"The TLLI has been reassigned from %08x to %08x\n",
|
||||
tlli_state->current, new_tlli);
|
||||
|
||||
/* Remember assigned TLLI */
|
||||
tlli_state->assigned = new_tlli;
|
||||
tlli_state->bss_validated = 0;
|
||||
tlli_state->net_validated = 0;
|
||||
}
|
||||
|
||||
uint32_t gbproxy_map_tlli(uint32_t other_tlli,
|
||||
struct gbproxy_link_info *link_info, int to_bss)
|
||||
{
|
||||
uint32_t tlli = 0;
|
||||
struct gbproxy_tlli_state *src, *dst;
|
||||
if (to_bss) {
|
||||
src = &link_info->sgsn_tlli;
|
||||
dst = &link_info->tlli;
|
||||
} else {
|
||||
src = &link_info->tlli;
|
||||
dst = &link_info->sgsn_tlli;
|
||||
}
|
||||
if (src->current == other_tlli)
|
||||
tlli = dst->current;
|
||||
else if (src->assigned == other_tlli)
|
||||
tlli = dst->assigned;
|
||||
|
||||
return tlli;
|
||||
}
|
||||
|
||||
static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
|
||||
uint32_t tlli, int to_bss)
|
||||
{
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
|
||||
__func__, tlli_state->current, tlli_state->assigned,
|
||||
tlli_state->net_validated, tlli_state->bss_validated, tlli);
|
||||
|
||||
if (!tlli_state->assigned || tlli_state->assigned != tlli)
|
||||
return;
|
||||
|
||||
/* TODO: Is this ok? Check spec */
|
||||
if (gprs_tlli_type(tlli) != TLLI_LOCAL)
|
||||
return;
|
||||
|
||||
/* See GSM 04.08, 4.7.1.5 */
|
||||
if (to_bss)
|
||||
tlli_state->net_validated = 1;
|
||||
else
|
||||
tlli_state->bss_validated = 1;
|
||||
|
||||
if (!tlli_state->bss_validated || !tlli_state->net_validated)
|
||||
return;
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"The TLLI %08x has been validated (was %08x)\n",
|
||||
tlli_state->assigned, tlli_state->current);
|
||||
|
||||
tlli_state->current = tlli;
|
||||
tlli_state->assigned = 0;
|
||||
}
|
||||
|
||||
static void gbproxy_touch_link_info(struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info,
|
||||
time_t now)
|
||||
{
|
||||
gbproxy_detach_link_info(peer, link_info);
|
||||
gbproxy_attach_link_info(peer, now, link_info);
|
||||
}
|
||||
|
||||
static int gbproxy_unregister_link_info(struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info)
|
||||
{
|
||||
if (!link_info)
|
||||
return 1;
|
||||
|
||||
if (link_info->tlli.ptmsi == GSM_RESERVED_TMSI && !link_info->imsi_len) {
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n",
|
||||
link_info->tlli.current);
|
||||
gbproxy_delete_link_info(peer, link_info);
|
||||
return 1;
|
||||
}
|
||||
|
||||
link_info->tlli.current = 0;
|
||||
link_info->tlli.assigned = 0;
|
||||
link_info->sgsn_tlli.current = 0;
|
||||
link_info->sgsn_tlli.assigned = 0;
|
||||
|
||||
link_info->is_deregistered = 1;
|
||||
|
||||
gbproxy_reset_link(link_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gbproxy_imsi_matches(struct gbproxy_config *cfg,
|
||||
enum gbproxy_match_id match_id,
|
||||
struct gbproxy_link_info *link_info)
|
||||
{
|
||||
struct gbproxy_match *match;
|
||||
OSMO_ASSERT(match_id >= 0 && match_id < ARRAY_SIZE(cfg->matches));
|
||||
|
||||
match = &cfg->matches[match_id];
|
||||
if (!match->enable)
|
||||
return 1;
|
||||
|
||||
return link_info != NULL && link_info->is_matching[match_id];
|
||||
}
|
||||
|
||||
static void gbproxy_assign_imsi(struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
int imsi_matches;
|
||||
struct gbproxy_link_info *other_link_info;
|
||||
enum gbproxy_match_id match_id;
|
||||
|
||||
/* Make sure that there is a second entry with the same IMSI */
|
||||
other_link_info = gbproxy_link_info_by_imsi(
|
||||
peer, parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
|
||||
if (other_link_info && other_link_info != link_info) {
|
||||
char mi_buf[200];
|
||||
mi_buf[0] = '\0';
|
||||
gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
|
||||
parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list (IMSI %s re-used)\n",
|
||||
other_link_info->tlli.current, mi_buf);
|
||||
gbproxy_delete_link_info(peer, other_link_info);
|
||||
}
|
||||
|
||||
/* Update the IMSI field */
|
||||
gbproxy_update_link_info(link_info,
|
||||
parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
|
||||
/* Check, whether the IMSI matches */
|
||||
OSMO_ASSERT(ARRAY_SIZE(link_info->is_matching) ==
|
||||
ARRAY_SIZE(peer->cfg->matches));
|
||||
for (match_id = 0; match_id < ARRAY_SIZE(link_info->is_matching);
|
||||
++match_id) {
|
||||
imsi_matches = gbproxy_check_imsi(
|
||||
&peer->cfg->matches[match_id],
|
||||
parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
if (imsi_matches >= 0)
|
||||
link_info->is_matching[match_id] = imsi_matches;
|
||||
}
|
||||
}
|
||||
|
||||
static int gbproxy_tlli_match(const struct gbproxy_tlli_state *a,
|
||||
const struct gbproxy_tlli_state *b)
|
||||
{
|
||||
if (a->current && a->current == b->current)
|
||||
return 1;
|
||||
|
||||
if (a->assigned && a->assigned == b->assigned)
|
||||
return 1;
|
||||
|
||||
if (a->ptmsi != GSM_RESERVED_TMSI && a->ptmsi == b->ptmsi)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gbproxy_remove_matching_link_infos(
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info)
|
||||
{
|
||||
struct gbproxy_link_info *info, *nxt;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
/* Make sure that there is no second entry with the same P-TMSI or TLLI */
|
||||
llist_for_each_entry_safe(info, nxt, &state->logical_links, list) {
|
||||
if (info == link_info)
|
||||
continue;
|
||||
|
||||
if (!gbproxy_tlli_match(&link_info->tlli, &info->tlli) &&
|
||||
(link_info->sgsn_nsei != info->sgsn_nsei ||
|
||||
!gbproxy_tlli_match(&link_info->sgsn_tlli, &info->sgsn_tlli)))
|
||||
continue;
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list (P-TMSI/TLLI re-used)\n",
|
||||
info->tlli.current);
|
||||
gbproxy_delete_link_info(peer, info);
|
||||
}
|
||||
}
|
||||
|
||||
static struct gbproxy_link_info *gbproxy_get_link_info_ul(
|
||||
struct gbproxy_peer *peer,
|
||||
int *tlli_is_valid,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
struct gbproxy_link_info *link_info = NULL;
|
||||
|
||||
if (parse_ctx->tlli_enc) {
|
||||
link_info = gbproxy_link_info_by_tlli(peer, parse_ctx->tlli);
|
||||
|
||||
if (link_info) {
|
||||
*tlli_is_valid = 1;
|
||||
return link_info;
|
||||
}
|
||||
}
|
||||
|
||||
*tlli_is_valid = 0;
|
||||
|
||||
if (!link_info && parse_ctx->imsi) {
|
||||
link_info = gbproxy_link_info_by_imsi(
|
||||
peer, parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
}
|
||||
|
||||
if (!link_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
|
||||
uint32_t bss_ptmsi;
|
||||
gprs_parse_tmsi(parse_ctx->ptmsi_enc, &bss_ptmsi);
|
||||
link_info = gbproxy_link_info_by_ptmsi(peer, bss_ptmsi);
|
||||
}
|
||||
|
||||
if (!link_info)
|
||||
return NULL;
|
||||
|
||||
link_info->is_deregistered = 0;
|
||||
|
||||
return link_info;
|
||||
}
|
||||
|
||||
struct gbproxy_link_info *gbproxy_update_link_state_ul(
|
||||
struct gbproxy_peer *peer,
|
||||
time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
struct gbproxy_link_info *link_info;
|
||||
int tlli_is_valid;
|
||||
|
||||
link_info = gbproxy_get_link_info_ul(peer, &tlli_is_valid, parse_ctx);
|
||||
|
||||
if (parse_ctx->tlli_enc && parse_ctx->llc) {
|
||||
uint32_t sgsn_tlli;
|
||||
|
||||
if (!link_info) {
|
||||
LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n",
|
||||
parse_ctx->tlli);
|
||||
link_info = gbproxy_link_info_alloc(peer);
|
||||
gbproxy_attach_link_info(peer, now, link_info);
|
||||
|
||||
/* Setup TLLIs */
|
||||
sgsn_tlli = gbproxy_make_sgsn_tlli(peer, link_info,
|
||||
parse_ctx->tlli);
|
||||
link_info->sgsn_tlli.current = sgsn_tlli;
|
||||
link_info->tlli.current = parse_ctx->tlli;
|
||||
} else if (!tlli_is_valid) {
|
||||
/* New TLLI (info found by IMSI or P-TMSI) */
|
||||
link_info->tlli.current = parse_ctx->tlli;
|
||||
link_info->tlli.assigned = 0;
|
||||
link_info->sgsn_tlli.current =
|
||||
gbproxy_make_sgsn_tlli(peer, link_info,
|
||||
parse_ctx->tlli);
|
||||
link_info->sgsn_tlli.assigned = 0;
|
||||
gbproxy_touch_link_info(peer, link_info, now);
|
||||
} else {
|
||||
sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, link_info, 0);
|
||||
if (!sgsn_tlli)
|
||||
sgsn_tlli = gbproxy_make_sgsn_tlli(peer, link_info,
|
||||
parse_ctx->tlli);
|
||||
|
||||
gbproxy_validate_tlli(&link_info->tlli,
|
||||
parse_ctx->tlli, 0);
|
||||
gbproxy_validate_tlli(&link_info->sgsn_tlli,
|
||||
sgsn_tlli, 0);
|
||||
gbproxy_touch_link_info(peer, link_info, now);
|
||||
}
|
||||
} else if (link_info) {
|
||||
gbproxy_touch_link_info(peer, link_info, now);
|
||||
}
|
||||
|
||||
if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
|
||||
gbproxy_assign_imsi(peer, link_info, parse_ctx);
|
||||
|
||||
return link_info;
|
||||
}
|
||||
|
||||
static struct gbproxy_link_info *gbproxy_get_link_info_dl(
|
||||
struct gbproxy_peer *peer,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
struct gbproxy_link_info *link_info = NULL;
|
||||
|
||||
/* Which key to use depends on its availability only, if that fails, do
|
||||
* not retry it with another key (e.g. IMSI). */
|
||||
if (parse_ctx->tlli_enc)
|
||||
link_info = gbproxy_link_info_by_sgsn_tlli(peer, parse_ctx->tlli,
|
||||
parse_ctx->peer_nsei);
|
||||
|
||||
/* TODO: Get link_info by (SGSN) P-TMSI if that is available (see
|
||||
* GSM 08.18, 7.2) instead of using the IMSI as key. */
|
||||
else if (parse_ctx->imsi)
|
||||
link_info = gbproxy_link_info_by_imsi(
|
||||
peer, parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
|
||||
if (link_info)
|
||||
link_info->is_deregistered = 0;
|
||||
|
||||
return link_info;
|
||||
}
|
||||
|
||||
struct gbproxy_link_info *gbproxy_update_link_state_dl(
|
||||
struct gbproxy_peer *peer,
|
||||
time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
struct gbproxy_link_info *link_info = NULL;
|
||||
|
||||
link_info = gbproxy_get_link_info_dl(peer, parse_ctx);
|
||||
|
||||
if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && link_info) {
|
||||
/* A new P-TMSI has been signalled in the message,
|
||||
* register new TLLI */
|
||||
uint32_t new_sgsn_ptmsi;
|
||||
uint32_t new_bss_ptmsi = GSM_RESERVED_TMSI;
|
||||
gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_sgsn_ptmsi);
|
||||
|
||||
if (link_info->sgsn_tlli.ptmsi == new_sgsn_ptmsi)
|
||||
new_bss_ptmsi = link_info->tlli.ptmsi;
|
||||
|
||||
if (new_bss_ptmsi == GSM_RESERVED_TMSI)
|
||||
new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Got new PTMSI %08x from SGSN, using %08x for BSS\n",
|
||||
new_sgsn_ptmsi, new_bss_ptmsi);
|
||||
/* Setup PTMSIs */
|
||||
link_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
|
||||
link_info->tlli.ptmsi = new_bss_ptmsi;
|
||||
} else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !link_info &&
|
||||
!peer->cfg->patch_ptmsi) {
|
||||
/* A new P-TMSI has been signalled in the message with an unknown
|
||||
* TLLI, create a new link_info */
|
||||
/* TODO: Add a test case for this branch */
|
||||
uint32_t new_ptmsi;
|
||||
gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
|
||||
parse_ctx->tlli, new_ptmsi);
|
||||
|
||||
link_info = gbproxy_link_info_alloc(peer);
|
||||
link_info->sgsn_tlli.current = parse_ctx->tlli;
|
||||
link_info->tlli.current = parse_ctx->tlli;
|
||||
link_info->sgsn_tlli.ptmsi = new_ptmsi;
|
||||
link_info->tlli.ptmsi = new_ptmsi;
|
||||
gbproxy_attach_link_info(peer, now, link_info);
|
||||
} else if (parse_ctx->tlli_enc && parse_ctx->llc && !link_info &&
|
||||
!peer->cfg->patch_ptmsi) {
|
||||
/* Unknown SGSN TLLI, create a new link_info */
|
||||
uint32_t new_ptmsi;
|
||||
link_info = gbproxy_link_info_alloc(peer);
|
||||
LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
|
||||
parse_ctx->tlli);
|
||||
|
||||
gbproxy_attach_link_info(peer, now, link_info);
|
||||
|
||||
/* Setup TLLIs */
|
||||
link_info->sgsn_tlli.current = parse_ctx->tlli;
|
||||
link_info->tlli.current = parse_ctx->tlli;
|
||||
|
||||
if (!parse_ctx->new_ptmsi_enc)
|
||||
return link_info;
|
||||
/* A new P-TMSI has been signalled in the message */
|
||||
|
||||
gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Assigning new P-TMSI %08x\n", new_ptmsi);
|
||||
/* Setup P-TMSIs */
|
||||
link_info->sgsn_tlli.ptmsi = new_ptmsi;
|
||||
link_info->tlli.ptmsi = new_ptmsi;
|
||||
} else if (parse_ctx->tlli_enc && parse_ctx->llc && link_info) {
|
||||
uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
|
||||
link_info, 1);
|
||||
gbproxy_validate_tlli(&link_info->sgsn_tlli, parse_ctx->tlli, 1);
|
||||
gbproxy_validate_tlli(&link_info->tlli, bss_tlli, 1);
|
||||
gbproxy_touch_link_info(peer, link_info, now);
|
||||
} else if (link_info) {
|
||||
gbproxy_touch_link_info(peer, link_info, now);
|
||||
}
|
||||
|
||||
if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
|
||||
gbproxy_assign_imsi(peer, link_info, parse_ctx);
|
||||
|
||||
return link_info;
|
||||
}
|
||||
|
||||
int gbproxy_update_link_state_after(
|
||||
struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info,
|
||||
time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
int rc = 0;
|
||||
if (parse_ctx->invalidate_tlli && link_info) {
|
||||
int keep_info =
|
||||
peer->cfg->keep_link_infos == GBPROX_KEEP_ALWAYS ||
|
||||
(peer->cfg->keep_link_infos == GBPROX_KEEP_REATTACH &&
|
||||
parse_ctx->await_reattach) ||
|
||||
(peer->cfg->keep_link_infos == GBPROX_KEEP_IDENTIFIED &&
|
||||
link_info->imsi_len > 0);
|
||||
if (keep_info) {
|
||||
LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
|
||||
link_info->tlli.current);
|
||||
rc = gbproxy_unregister_link_info(peer, link_info);
|
||||
} else {
|
||||
LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
|
||||
link_info->tlli.current);
|
||||
gbproxy_delete_link_info(peer, link_info);
|
||||
rc = 1;
|
||||
}
|
||||
} else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
|
||||
parse_ctx->new_ptmsi_enc && link_info) {
|
||||
/* A new PTMSI has been signaled in the message,
|
||||
* register new TLLI */
|
||||
uint32_t new_sgsn_ptmsi = link_info->sgsn_tlli.ptmsi;
|
||||
uint32_t new_bss_ptmsi = link_info->tlli.ptmsi;
|
||||
uint32_t new_sgsn_tlli;
|
||||
uint32_t new_bss_tlli = 0;
|
||||
|
||||
new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
|
||||
if (new_bss_ptmsi != GSM_RESERVED_TMSI)
|
||||
new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Assigning new TLLI %08x to SGSN, %08x to BSS\n",
|
||||
new_sgsn_tlli, new_bss_tlli);
|
||||
|
||||
gbproxy_reassign_tlli(&link_info->sgsn_tlli,
|
||||
peer, new_sgsn_tlli);
|
||||
gbproxy_reassign_tlli(&link_info->tlli,
|
||||
peer, new_bss_tlli);
|
||||
gbproxy_remove_matching_link_infos(peer, link_info);
|
||||
}
|
||||
|
||||
gbproxy_remove_stale_link_infos(peer, now);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,926 +0,0 @@
|
||||
/*
|
||||
* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010 by On-Waves
|
||||
* 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 <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gb_proxy.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
#include <osmocom/sgsn/vty.h>
|
||||
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/misc.h>
|
||||
|
||||
static struct gbproxy_config *g_cfg = NULL;
|
||||
|
||||
/*
|
||||
* vty code for gbproxy below
|
||||
*/
|
||||
static struct cmd_node gbproxy_node = {
|
||||
GBPROXY_NODE,
|
||||
"%s(config-gbproxy)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
static const struct value_string keep_modes[] = {
|
||||
{GBPROX_KEEP_NEVER, "never"},
|
||||
{GBPROX_KEEP_REATTACH, "re-attach"},
|
||||
{GBPROX_KEEP_IDENTIFIED, "identified"},
|
||||
{GBPROX_KEEP_ALWAYS, "always"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static const struct value_string match_ids[] = {
|
||||
{GBPROX_MATCH_PATCHING, "patching"},
|
||||
{GBPROX_MATCH_ROUTING, "routing"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer)
|
||||
{
|
||||
struct gprs_ra_id raid;
|
||||
gsm48_parse_ra(&raid, peer->ra);
|
||||
|
||||
vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "
|
||||
"RAI %s", peer->nsei, peer->bvci, osmo_rai_name(&raid));
|
||||
if (peer->blocked)
|
||||
vty_out(vty, " [BVC-BLOCKED]");
|
||||
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
static int config_write_gbproxy(struct vty *vty)
|
||||
{
|
||||
enum gbproxy_match_id match_id;
|
||||
|
||||
vty_out(vty, "gbproxy%s", VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
|
||||
VTY_NEWLINE);
|
||||
|
||||
if (g_cfg->core_plmn.mcc > 0)
|
||||
vty_out(vty, " core-mobile-country-code %s%s",
|
||||
osmo_mcc_name(g_cfg->core_plmn.mcc), VTY_NEWLINE);
|
||||
if (g_cfg->core_plmn.mnc > 0)
|
||||
vty_out(vty, " core-mobile-network-code %s%s",
|
||||
osmo_mnc_name(g_cfg->core_plmn.mnc, g_cfg->core_plmn.mnc_3_digits), VTY_NEWLINE);
|
||||
|
||||
for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id) {
|
||||
struct gbproxy_match *match = &g_cfg->matches[match_id];
|
||||
if (match->re_str)
|
||||
vty_out(vty, " match-imsi %s %s%s",
|
||||
get_value_string(match_ids, match_id),
|
||||
match->re_str, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
if (g_cfg->core_apn != NULL) {
|
||||
if (g_cfg->core_apn_size > 0) {
|
||||
char str[500] = {0};
|
||||
vty_out(vty, " core-access-point-name %s%s",
|
||||
osmo_apn_to_str(str, g_cfg->core_apn,
|
||||
g_cfg->core_apn_size),
|
||||
VTY_NEWLINE);
|
||||
} else {
|
||||
vty_out(vty, " core-access-point-name none%s",
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_cfg->route_to_sgsn2)
|
||||
vty_out(vty, " secondary-sgsn nsei %u%s", g_cfg->nsip_sgsn2_nsei,
|
||||
VTY_NEWLINE);
|
||||
|
||||
if (g_cfg->clean_stale_timer_freq > 0)
|
||||
vty_out(vty, " link-list clean-stale-timer %u%s",
|
||||
g_cfg->clean_stale_timer_freq, VTY_NEWLINE);
|
||||
if (g_cfg->tlli_max_age > 0)
|
||||
vty_out(vty, " link-list max-age %d%s",
|
||||
g_cfg->tlli_max_age, VTY_NEWLINE);
|
||||
if (g_cfg->tlli_max_len > 0)
|
||||
vty_out(vty, " link-list max-length %d%s",
|
||||
g_cfg->tlli_max_len, VTY_NEWLINE);
|
||||
vty_out(vty, " link-list keep-mode %s%s",
|
||||
get_value_string(keep_modes, g_cfg->keep_link_infos),
|
||||
VTY_NEWLINE);
|
||||
if (g_cfg->stored_msgs_max_len > 0)
|
||||
vty_out(vty, " link stored-msgs-max-length %"PRIu32"%s",
|
||||
g_cfg->stored_msgs_max_len, VTY_NEWLINE);
|
||||
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy,
|
||||
cfg_gbproxy_cmd,
|
||||
"gbproxy",
|
||||
"Configure the Gb proxy")
|
||||
{
|
||||
vty->node = GBPROXY_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_nsip_sgsn_nsei,
|
||||
cfg_nsip_sgsn_nsei_cmd,
|
||||
"sgsn nsei <0-65534>",
|
||||
"SGSN information\n"
|
||||
"NSEI to be used in the connection with the SGSN\n"
|
||||
"The NSEI\n")
|
||||
{
|
||||
unsigned int nsei = atoi(argv[0]);
|
||||
|
||||
if (g_cfg->route_to_sgsn2 && g_cfg->nsip_sgsn2_nsei == nsei) {
|
||||
vty_out(vty, "SGSN NSEI %d conflicts with secondary SGSN NSEI%s",
|
||||
nsei, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
g_cfg->nsip_sgsn_nsei = nsei;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_core_mnc,
|
||||
cfg_gbproxy_core_mnc_cmd,
|
||||
"core-mobile-network-code <1-999>",
|
||||
GBPROXY_CORE_MNC_STR "NCC value\n")
|
||||
{
|
||||
uint16_t mnc;
|
||||
bool mnc_3_digits;
|
||||
if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
|
||||
vty_out(vty, "%% Invalid MNC: %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
g_cfg->core_plmn.mnc = mnc;
|
||||
g_cfg->core_plmn.mnc_3_digits = mnc_3_digits;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_no_core_mnc,
|
||||
cfg_gbproxy_no_core_mnc_cmd,
|
||||
"no core-mobile-network-code",
|
||||
NO_STR GBPROXY_CORE_MNC_STR)
|
||||
{
|
||||
g_cfg->core_plmn.mnc = 0;
|
||||
g_cfg->core_plmn.mnc_3_digits = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_core_mcc,
|
||||
cfg_gbproxy_core_mcc_cmd,
|
||||
"core-mobile-country-code <1-999>",
|
||||
GBPROXY_CORE_MCC_STR "MCC value\n")
|
||||
{
|
||||
g_cfg->core_plmn.mcc = atoi(argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_no_core_mcc,
|
||||
cfg_gbproxy_no_core_mcc_cmd,
|
||||
"no core-mobile-country-code",
|
||||
NO_STR GBPROXY_CORE_MCC_STR)
|
||||
{
|
||||
g_cfg->core_plmn.mcc = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_MATCH_IMSI_STR "Restrict actions to certain IMSIs\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_match_imsi,
|
||||
cfg_gbproxy_match_imsi_cmd,
|
||||
"match-imsi (patching|routing) .REGEXP",
|
||||
GBPROXY_MATCH_IMSI_STR
|
||||
"Patch MS related information elements on match only\n"
|
||||
"Route to the secondary SGSN on match only\n"
|
||||
"Regular expression for the IMSI match\n")
|
||||
{
|
||||
const char *filter = argv[1];
|
||||
const char *err_msg = NULL;
|
||||
struct gbproxy_match *match;
|
||||
enum gbproxy_match_id match_id = get_string_value(match_ids, argv[0]);
|
||||
|
||||
OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
|
||||
match_id < GBPROX_MATCH_LAST);
|
||||
match = &g_cfg->matches[match_id];
|
||||
|
||||
if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
|
||||
vty_out(vty, "Match expression invalid: %s%s",
|
||||
err_msg, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
g_cfg->acquire_imsi = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_no_match_imsi,
|
||||
cfg_gbproxy_no_match_imsi_cmd,
|
||||
"no match-imsi",
|
||||
NO_STR GBPROXY_MATCH_IMSI_STR)
|
||||
{
|
||||
enum gbproxy_match_id match_id;
|
||||
|
||||
for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id)
|
||||
gbproxy_clear_patch_filter(&g_cfg->matches[match_id]);
|
||||
|
||||
g_cfg->acquire_imsi = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n"
|
||||
#define GBPROXY_CORE_APN_ARG_STR "Replace APN by this string\n" "Remove APN\n"
|
||||
|
||||
static int set_core_apn(struct vty *vty, const char *apn)
|
||||
{
|
||||
int apn_len;
|
||||
|
||||
if (!apn) {
|
||||
talloc_free(g_cfg->core_apn);
|
||||
g_cfg->core_apn = NULL;
|
||||
g_cfg->core_apn_size = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
apn_len = strlen(apn);
|
||||
|
||||
if (apn_len >= 100) {
|
||||
vty_out(vty, "APN string too long (max 99 chars)%s",
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (apn_len == 0) {
|
||||
talloc_free(g_cfg->core_apn);
|
||||
/* TODO: replace NULL */
|
||||
g_cfg->core_apn = talloc_zero_size(NULL, 2);
|
||||
g_cfg->core_apn_size = 0;
|
||||
} else {
|
||||
/* TODO: replace NULL */
|
||||
g_cfg->core_apn =
|
||||
talloc_realloc_size(NULL, g_cfg->core_apn, apn_len + 1);
|
||||
g_cfg->core_apn_size =
|
||||
gprs_str_to_apn(g_cfg->core_apn, apn_len + 1, apn);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_core_apn,
|
||||
cfg_gbproxy_core_apn_cmd,
|
||||
"core-access-point-name (APN|none)",
|
||||
GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR)
|
||||
{
|
||||
if (strcmp(argv[0], "none") == 0)
|
||||
return set_core_apn(vty, "");
|
||||
else
|
||||
return set_core_apn(vty, argv[0]);
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_no_core_apn,
|
||||
cfg_gbproxy_no_core_apn_cmd,
|
||||
"no core-access-point-name",
|
||||
NO_STR GBPROXY_CORE_APN_STR)
|
||||
{
|
||||
return set_core_apn(vty, NULL);
|
||||
}
|
||||
|
||||
/* TODO: Remove the patch-ptmsi command, since P-TMSI patching is enabled
|
||||
* automatically when needed. This command is only left for manual testing
|
||||
* (e.g. doing P-TMSI patching without using a secondary SGSN)
|
||||
*/
|
||||
#define GBPROXY_PATCH_PTMSI_STR "Patch P-TMSI/TLLI\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_patch_ptmsi,
|
||||
cfg_gbproxy_patch_ptmsi_cmd,
|
||||
"patch-ptmsi",
|
||||
GBPROXY_PATCH_PTMSI_STR)
|
||||
{
|
||||
g_cfg->patch_ptmsi = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_no_patch_ptmsi,
|
||||
cfg_gbproxy_no_patch_ptmsi_cmd,
|
||||
"no patch-ptmsi",
|
||||
NO_STR GBPROXY_PATCH_PTMSI_STR)
|
||||
{
|
||||
g_cfg->patch_ptmsi = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* TODO: Remove the acquire-imsi command, since that feature is enabled
|
||||
* automatically when IMSI matching is enabled. This command is only left for
|
||||
* manual testing (e.g. doing IMSI acquisition without IMSI based patching)
|
||||
*/
|
||||
#define GBPROXY_ACQUIRE_IMSI_STR "Acquire the IMSI before establishing a LLC connection (Experimental)\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_acquire_imsi,
|
||||
cfg_gbproxy_acquire_imsi_cmd,
|
||||
"acquire-imsi",
|
||||
GBPROXY_ACQUIRE_IMSI_STR)
|
||||
{
|
||||
g_cfg->acquire_imsi = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_no_acquire_imsi,
|
||||
cfg_gbproxy_no_acquire_imsi_cmd,
|
||||
"no acquire-imsi",
|
||||
NO_STR GBPROXY_ACQUIRE_IMSI_STR)
|
||||
{
|
||||
g_cfg->acquire_imsi = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_SECOND_SGSN_STR "Route matching LLC connections to a second SGSN (Experimental)\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_secondary_sgsn,
|
||||
cfg_gbproxy_secondary_sgsn_cmd,
|
||||
"secondary-sgsn nsei <0-65534>",
|
||||
GBPROXY_SECOND_SGSN_STR
|
||||
"NSEI to be used in the connection with the SGSN\n"
|
||||
"The NSEI\n")
|
||||
{
|
||||
unsigned int nsei = atoi(argv[0]);
|
||||
|
||||
if (g_cfg->nsip_sgsn_nsei == nsei) {
|
||||
vty_out(vty, "Secondary SGSN NSEI %d conflicts with primary SGSN NSEI%s",
|
||||
nsei, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
g_cfg->route_to_sgsn2 = 1;
|
||||
g_cfg->nsip_sgsn2_nsei = nsei;
|
||||
|
||||
g_cfg->patch_ptmsi = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_no_secondary_sgsn,
|
||||
cfg_gbproxy_no_secondary_sgsn_cmd,
|
||||
"no secondary-sgsn",
|
||||
NO_STR GBPROXY_SECOND_SGSN_STR)
|
||||
{
|
||||
g_cfg->route_to_sgsn2 = 0;
|
||||
g_cfg->nsip_sgsn2_nsei = 0xFFFF;
|
||||
|
||||
g_cfg->patch_ptmsi = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_LINK_LIST_STR "Set TLLI list parameters\n"
|
||||
#define GBPROXY_LINK_STR "Set TLLI parameters\n"
|
||||
|
||||
#define GBPROXY_CLEAN_STALE_TIMER_STR "Periodic timer to clean stale links\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_link_list_clean_stale_timer,
|
||||
cfg_gbproxy_link_list_clean_stale_timer_cmd,
|
||||
"link-list clean-stale-timer <1-999999>",
|
||||
GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR
|
||||
"Frequency at which the periodic timer is fired (in seconds)\n")
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);
|
||||
|
||||
/* Re-schedule running timers soon in case prev frequency was really big
|
||||
and new frequency is desired to be lower. After initial run, periodic
|
||||
time is used. Use random() to avoid firing timers for all peers at
|
||||
the same time */
|
||||
llist_for_each_entry(peer, &g_cfg->bts_peers, list)
|
||||
osmo_timer_schedule(&peer->clean_stale_timer,
|
||||
random() % 5, random() % 1000000);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_link_list_no_clean_stale_timer,
|
||||
cfg_gbproxy_link_list_no_clean_stale_timer_cmd,
|
||||
"no link-list clean-stale-timer",
|
||||
NO_STR GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR)
|
||||
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
g_cfg->clean_stale_timer_freq = 0;
|
||||
|
||||
llist_for_each_entry(peer, &g_cfg->bts_peers, list)
|
||||
osmo_timer_del(&peer->clean_stale_timer);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_link_list_max_age,
|
||||
cfg_gbproxy_link_list_max_age_cmd,
|
||||
"link-list max-age <1-999999>",
|
||||
GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR
|
||||
"Maximum age in seconds\n")
|
||||
{
|
||||
g_cfg->tlli_max_age = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_link_list_no_max_age,
|
||||
cfg_gbproxy_link_list_no_max_age_cmd,
|
||||
"no link-list max-age",
|
||||
NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR)
|
||||
{
|
||||
g_cfg->tlli_max_age = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_MAX_LEN_STR "Limit list length\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_link_list_max_len,
|
||||
cfg_gbproxy_link_list_max_len_cmd,
|
||||
"link-list max-length <1-99999>",
|
||||
GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR
|
||||
"Maximum number of logical links in the list\n")
|
||||
{
|
||||
g_cfg->tlli_max_len = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_link_list_no_max_len,
|
||||
cfg_gbproxy_link_list_no_max_len_cmd,
|
||||
"no link-list max-length",
|
||||
NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR)
|
||||
{
|
||||
g_cfg->tlli_max_len = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_link_list_keep_mode,
|
||||
cfg_gbproxy_link_list_keep_mode_cmd,
|
||||
"link-list keep-mode (never|re-attach|identified|always)",
|
||||
GBPROXY_LINK_LIST_STR "How to keep entries for detached logical links\n"
|
||||
"Discard entry immediately after detachment\n"
|
||||
"Keep entry if a re-attachment has be requested\n"
|
||||
"Keep entry if it associated with an IMSI\n"
|
||||
"Don't discard entries after detachment\n")
|
||||
{
|
||||
int val = get_string_value(keep_modes, argv[0]);
|
||||
OSMO_ASSERT(val >= GBPROX_KEEP_NEVER && val <= GBPROX_KEEP_ALWAYS);
|
||||
g_cfg->keep_link_infos = val;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_link_stored_msgs_max_len,
|
||||
cfg_gbproxy_link_stored_msgs_max_len_cmd,
|
||||
"link stored-msgs-max-length <1-99999>",
|
||||
GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR
|
||||
"Maximum number of msgb stored in the logical link waiting to acquire its IMSI\n")
|
||||
{
|
||||
g_cfg->stored_msgs_max_len = (uint32_t) atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_link_no_stored_msgs_max_len,
|
||||
cfg_gbproxy_link_no_stored_msgs_max_len_cmd,
|
||||
"no link stored-msgs-max-length",
|
||||
NO_STR GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR)
|
||||
{
|
||||
g_cfg->stored_msgs_max_len = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
|
||||
SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
int show_stats = argc >= 1;
|
||||
|
||||
if (show_stats)
|
||||
vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
|
||||
|
||||
llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
|
||||
gbprox_vty_print_peer(vty, peer);
|
||||
|
||||
if (show_stats)
|
||||
vty_out_rate_ctr_group(vty, " ", peer->ctrg);
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
|
||||
SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
char mi_buf[200];
|
||||
time_t now;
|
||||
struct timespec ts = {0,};
|
||||
|
||||
osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ts.tv_sec;
|
||||
|
||||
llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
|
||||
struct gbproxy_link_info *link_info;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
gbprox_vty_print_peer(vty, peer);
|
||||
|
||||
llist_for_each_entry(link_info, &state->logical_links, list) {
|
||||
time_t age = now - link_info->timestamp;
|
||||
|
||||
if (link_info->imsi > 0) {
|
||||
snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
|
||||
gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
|
||||
link_info->imsi,
|
||||
link_info->imsi_len);
|
||||
} else {
|
||||
snprintf(mi_buf, sizeof(mi_buf), "(none)");
|
||||
}
|
||||
vty_out(vty, " TLLI %08x, IMSI %s, AGE %d",
|
||||
link_info->tlli.current, mi_buf, (int)age);
|
||||
|
||||
if (link_info->stored_msgs_len)
|
||||
vty_out(vty, ", STORED %"PRIu32"/%"PRIu32,
|
||||
link_info->stored_msgs_len,
|
||||
g_cfg->stored_msgs_max_len);
|
||||
|
||||
if (g_cfg->route_to_sgsn2)
|
||||
vty_out(vty, ", SGSN NSEI %d",
|
||||
link_info->sgsn_nsei);
|
||||
|
||||
if (link_info->is_deregistered)
|
||||
vty_out(vty, ", DE-REGISTERED");
|
||||
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
|
||||
"delete-gbproxy-peer <0-65534> bvci <2-65534>",
|
||||
"Delete a GBProxy peer by NSEI and optionally BVCI\n"
|
||||
"NSEI number\n"
|
||||
"Only delete peer with a matching BVCI\n"
|
||||
"BVCI number\n")
|
||||
{
|
||||
const uint16_t nsei = atoi(argv[0]);
|
||||
const uint16_t bvci = atoi(argv[1]);
|
||||
int counter;
|
||||
|
||||
counter = gbproxy_cleanup_peers(g_cfg, nsei, bvci);
|
||||
|
||||
if (counter == 0) {
|
||||
vty_out(vty, "BVC not found%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
|
||||
"delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
|
||||
"Delete a GBProxy peer by NSEI and optionally BVCI\n"
|
||||
"NSEI number\n"
|
||||
"Only delete BSSGP connections (BVC)\n"
|
||||
"Only delete dynamic NS connections (NS-VC)\n"
|
||||
"Delete BVC and dynamic NS connections\n"
|
||||
"Show what would be deleted instead of actually deleting\n"
|
||||
)
|
||||
{
|
||||
const uint16_t nsei = atoi(argv[0]);
|
||||
const char *mode = argv[1];
|
||||
int dry_run = argc > 2;
|
||||
int delete_bvc = 0;
|
||||
int delete_nsvc = 0;
|
||||
int counter;
|
||||
|
||||
if (strcmp(mode, "only-bvc") == 0)
|
||||
delete_bvc = 1;
|
||||
else if (strcmp(mode, "only-nsvc") == 0)
|
||||
delete_nsvc = 1;
|
||||
else
|
||||
delete_bvc = delete_nsvc = 1;
|
||||
|
||||
if (delete_bvc) {
|
||||
if (!dry_run)
|
||||
counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);
|
||||
else {
|
||||
struct gbproxy_peer *peer;
|
||||
counter = 0;
|
||||
llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
|
||||
if (peer->nsei != nsei)
|
||||
continue;
|
||||
|
||||
vty_out(vty, "BVC: ");
|
||||
gbprox_vty_print_peer(vty, peer);
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
vty_out(vty, "%sDeleted %d BVC%s",
|
||||
dry_run ? "Not " : "", counter, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
if (delete_nsvc) {
|
||||
struct gprs_ns_inst *nsi = g_cfg->nsi;
|
||||
struct gprs_nsvc *nsvc, *nsvc2;
|
||||
|
||||
counter = 0;
|
||||
llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) {
|
||||
if (nsvc->nsei != nsei)
|
||||
continue;
|
||||
if (nsvc->persistent)
|
||||
continue;
|
||||
|
||||
if (!dry_run)
|
||||
gprs_nsvc_delete(nsvc);
|
||||
else
|
||||
vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, "
|
||||
"remote %s%s",
|
||||
nsvc->nsei, nsvc->nsvci,
|
||||
gprs_ns_ll_str(nsvc), VTY_NEWLINE);
|
||||
counter += 1;
|
||||
}
|
||||
vty_out(vty, "%sDeleted %d NS-VC%s",
|
||||
dry_run ? "Not " : "", counter, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_DELETE_LINK_STR \
|
||||
"Delete a GBProxy logical link entry by NSEI and identification\nNSEI number\n"
|
||||
|
||||
DEFUN(delete_gb_link_by_id, delete_gb_link_by_id_cmd,
|
||||
"delete-gbproxy-link <0-65534> (tlli|imsi|sgsn-nsei) IDENT",
|
||||
GBPROXY_DELETE_LINK_STR
|
||||
"Delete entries with a matching TLLI (hex)\n"
|
||||
"Delete entries with a matching IMSI\n"
|
||||
"Delete entries with a matching SGSN NSEI\n"
|
||||
"Identification to match\n")
|
||||
{
|
||||
const uint16_t nsei = atoi(argv[0]);
|
||||
enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_SGSN = 's'} match;
|
||||
uint32_t ident = 0;
|
||||
const char *imsi = NULL;
|
||||
struct gbproxy_peer *peer = 0;
|
||||
struct gbproxy_link_info *link_info, *nxt;
|
||||
struct gbproxy_patch_state *state;
|
||||
char mi_buf[200];
|
||||
int found = 0;
|
||||
|
||||
match = argv[1][0];
|
||||
|
||||
switch (match) {
|
||||
case MATCH_TLLI: ident = strtoll(argv[2], NULL, 16); break;
|
||||
case MATCH_IMSI: imsi = argv[2]; break;
|
||||
case MATCH_SGSN: ident = strtoll(argv[2], NULL, 0); break;
|
||||
};
|
||||
|
||||
peer = gbproxy_peer_by_nsei(g_cfg, nsei);
|
||||
if (!peer) {
|
||||
vty_out(vty, "Didn't find peer with NSEI %d%s",
|
||||
nsei, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
state = &peer->patch_state;
|
||||
|
||||
llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list) {
|
||||
switch (match) {
|
||||
case MATCH_TLLI:
|
||||
if (link_info->tlli.current != ident)
|
||||
continue;
|
||||
break;
|
||||
case MATCH_SGSN:
|
||||
if (link_info->sgsn_nsei != ident)
|
||||
continue;
|
||||
break;
|
||||
case MATCH_IMSI:
|
||||
if (!link_info->imsi)
|
||||
continue;
|
||||
mi_buf[0] = '\0';
|
||||
gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
|
||||
link_info->imsi,
|
||||
link_info->imsi_len);
|
||||
|
||||
if (strcmp(mi_buf, imsi) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
vty_out(vty, "Deleting link with TLLI %08x%s", link_info->tlli.current,
|
||||
VTY_NEWLINE);
|
||||
gbproxy_delete_link_info(peer, link_info);
|
||||
found += 1;
|
||||
}
|
||||
|
||||
if (!found && argc >= 2) {
|
||||
vty_out(vty, "Didn't find link entry with %s %s%s",
|
||||
argv[1], argv[2], VTY_NEWLINE);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(delete_gb_link, delete_gb_link_cmd,
|
||||
"delete-gbproxy-link <0-65534> (stale|de-registered)",
|
||||
GBPROXY_DELETE_LINK_STR
|
||||
"Delete stale entries\n"
|
||||
"Delete de-registered entries\n")
|
||||
{
|
||||
const uint16_t nsei = atoi(argv[0]);
|
||||
enum {MATCH_STALE = 's', MATCH_DEREGISTERED = 'd'} match;
|
||||
struct gbproxy_peer *peer = 0;
|
||||
struct gbproxy_link_info *link_info, *nxt;
|
||||
struct gbproxy_patch_state *state;
|
||||
time_t now;
|
||||
struct timespec ts = {0,};
|
||||
|
||||
int found = 0;
|
||||
|
||||
match = argv[1][0];
|
||||
|
||||
peer = gbproxy_peer_by_nsei(g_cfg, nsei);
|
||||
if (!peer) {
|
||||
vty_out(vty, "Didn't find peer with NSEI %d%s",
|
||||
nsei, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
state = &peer->patch_state;
|
||||
|
||||
osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ts.tv_sec;
|
||||
|
||||
if (match == MATCH_STALE) {
|
||||
found = gbproxy_remove_stale_link_infos(peer, now);
|
||||
if (found)
|
||||
vty_out(vty, "Deleted %d stale logical link%s%s",
|
||||
found, found == 1 ? "" : "s", VTY_NEWLINE);
|
||||
} else {
|
||||
llist_for_each_entry_safe(link_info, nxt,
|
||||
&state->logical_links, list) {
|
||||
if (!link_info->is_deregistered)
|
||||
continue;
|
||||
|
||||
gbproxy_delete_link_info(peer, link_info);
|
||||
found += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
vty_out(vty, "Deleted %d %s logical link%s%s",
|
||||
found, argv[1], found == 1 ? "" : "s", VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* legacy commands to provide an upgrade path from "broken" releases
|
||||
* or pre-releases
|
||||
*/
|
||||
DEFUN_DEPRECATED(cfg_gbproxy_broken_apn_match,
|
||||
cfg_gbproxy_broken_apn_match_cmd,
|
||||
"core-access-point-name none match-imsi .REGEXP",
|
||||
GBPROXY_CORE_APN_STR GBPROXY_MATCH_IMSI_STR "Remove APN\n"
|
||||
"Patch MS related information elements on match only\n"
|
||||
"Route to the secondary SGSN on match only\n"
|
||||
"Regular expression for the IMSI match\n")
|
||||
{
|
||||
const char *filter = argv[0];
|
||||
const char *err_msg = NULL;
|
||||
struct gbproxy_match *match;
|
||||
enum gbproxy_match_id match_id = get_string_value(match_ids, "patching");
|
||||
|
||||
/* apply APN none */
|
||||
set_core_apn(vty, "");
|
||||
|
||||
/* do the matching... with copy and paste */
|
||||
OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
|
||||
match_id < GBPROX_MATCH_LAST);
|
||||
match = &g_cfg->matches[match_id];
|
||||
|
||||
if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
|
||||
vty_out(vty, "Match expression invalid: %s%s",
|
||||
err_msg, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
g_cfg->acquire_imsi = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
|
||||
#define GBPROXY_MAX_LEN_STR "Limit list length\n"
|
||||
DEFUN_DEPRECATED(cfg_gbproxy_depr_tlli_list_max_len,
|
||||
cfg_gbproxy_depr_tlli_list_max_len_cmd,
|
||||
"tlli-list max-length <1-99999>",
|
||||
GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR
|
||||
"Maximum number of TLLIs in the list\n")
|
||||
{
|
||||
g_cfg->tlli_max_len = atoi(argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int gbproxy_vty_init(void)
|
||||
{
|
||||
install_element_ve(&show_gbproxy_cmd);
|
||||
install_element_ve(&show_gbproxy_links_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
|
||||
install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
|
||||
install_element(ENABLE_NODE, &delete_gb_link_by_id_cmd);
|
||||
install_element(ENABLE_NODE, &delete_gb_link_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
|
||||
install_node(&gbproxy_node, config_write_gbproxy);
|
||||
install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_match_imsi_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_secondary_sgsn_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_clean_stale_timer_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_age_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_len_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_keep_mode_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_stored_msgs_max_len_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_secondary_sgsn_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_clean_stale_timer_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_age_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_len_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_link_no_stored_msgs_max_len_cmd);
|
||||
|
||||
/* broken or deprecated to allow an upgrade path */
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_broken_apn_match_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_depr_tlli_list_max_len_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
g_cfg = cfg;
|
||||
rc = vty_read_config_file(config_file, NULL);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,996 +0,0 @@
|
||||
/* GPRS SGSN 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/core/backtrace.h>
|
||||
#include <osmocom/gprs/gprs_ns.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/sgsn/gprs_subscriber.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_sgsn.h>
|
||||
#include <osmocom/sgsn/sgsn.h>
|
||||
#include <osmocom/sgsn/gprs_gmm.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
#include <osmocom/sgsn/signal.h>
|
||||
#include <osmocom/sgsn/gprs_gmm_attach.h>
|
||||
#include <osmocom/sgsn/gprs_llc.h>
|
||||
|
||||
#include <pdp.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "../../bscconfig.h"
|
||||
|
||||
#if BUILD_IU
|
||||
#include <osmocom/ranap/iu_client.h>
|
||||
#endif
|
||||
|
||||
#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);
|
||||
|
||||
static const struct rate_ctr_desc mmctx_ctr_description[] = {
|
||||
{ "sign:packets:in", "Signalling Messages ( In)" },
|
||||
{ "sign:packets:out", "Signalling Messages (Out)" },
|
||||
{ "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)" },
|
||||
{ "pdp_ctx_act", "PDP Context Activations " },
|
||||
{ "suspend", "SUSPEND Count " },
|
||||
{ "paging:ps", "Paging Packet Switched " },
|
||||
{ "paging:cs", "Paging Circuit Switched " },
|
||||
{ "ra_update", "Routing Area Update " },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc mmctx_ctrg_desc = {
|
||||
.group_name_prefix = "sgsn:mmctx",
|
||||
.group_description = "SGSN MM Context Statistics",
|
||||
.num_ctr = ARRAY_SIZE(mmctx_ctr_description),
|
||||
.ctr_desc = mmctx_ctr_description,
|
||||
.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 sucessful received LLC bytes (encrypt & fcs correct)" },
|
||||
{ "llc:dl_packets", "Count sucessful sent LLC packets before giving it to the bssgp layer" },
|
||||
{ "llc:ul_packets", "Count sucessful 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) {
|
||||
if (ctx->ran_type == MM_CTX_T_UTRAN_Iu
|
||||
&& uectx == ctx->iu.ue_ctx)
|
||||
return ctx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up a SGSN MM context based on TLLI + RAI */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid)
|
||||
{
|
||||
struct sgsn_mm_ctx *ctx;
|
||||
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
|
||||
if ((tlli == ctx->gb.tlli || tlli == ctx->gb.tlli_new) &&
|
||||
gprs_ra_id_equals(raid, &ctx->ra))
|
||||
return ctx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid)
|
||||
{
|
||||
struct sgsn_mm_ctx *ctx;
|
||||
int tlli_type;
|
||||
|
||||
/* TODO: Also check the P_TMSI signature to be safe. That signature
|
||||
* should be different (at least with a sufficiently high probability)
|
||||
* after SGSN restarts and for multiple SGSN instances.
|
||||
*/
|
||||
|
||||
tlli_type = gprs_tlli_type(tlli);
|
||||
if (tlli_type != TLLI_FOREIGN && tlli_type != TLLI_LOCAL)
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(ctx, &sgsn_mm_ctxts, 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))
|
||||
return ctx;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (p_tmsi == ctx->p_tmsi ||
|
||||
(ctx->p_tmsi_old && ctx->p_tmsi_old == p_tmsi))
|
||||
return ctx;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!strcmp(imsi, ctx->imsi))
|
||||
return ctx;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/* Allocate a new SGSN MM context for GERAN_Gb */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid)
|
||||
{
|
||||
struct sgsn_mm_ctx *ctx;
|
||||
|
||||
ctx = talloc_zero(tall_sgsn_ctx, struct sgsn_mm_ctx);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
memcpy(&ctx->ra, raid, sizeof(ctx->ra));
|
||||
ctx->ran_type = MM_CTX_T_GERAN_Gb;
|
||||
ctx->gb.tlli = tlli;
|
||||
ctx->gmm_state = GMM_DEREGISTERED;
|
||||
ctx->pmm_state = MM_IDLE;
|
||||
ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
|
||||
ctx->ciph_algo = sgsn->cfg.cipher;
|
||||
LOGMMCTXP(LOGL_DEBUG, ctx, "Allocated with %s cipher.\n",
|
||||
get_value_string(gprs_cipher_names, ctx->ciph_algo));
|
||||
ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, tlli);
|
||||
if (!ctx->ctrg) {
|
||||
LOGMMCTXP(LOGL_ERROR, ctx, "Cannot allocate counter group\n");
|
||||
talloc_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
ctx->gmm_att_req.fsm = osmo_fsm_inst_alloc(&gmm_attach_req_fsm, ctx, ctx, LOGL_DEBUG, "gb_gmm_req");
|
||||
INIT_LLIST_HEAD(&ctx->pdp_list);
|
||||
|
||||
llist_add(&ctx->list, &sgsn_mm_ctxts);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/* Allocate a new SGSN MM context */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx)
|
||||
{
|
||||
#if BUILD_IU
|
||||
struct sgsn_mm_ctx *ctx;
|
||||
struct ranap_ue_conn_ctx *ue_ctx = uectx;
|
||||
|
||||
ctx = talloc_zero(tall_sgsn_ctx, struct sgsn_mm_ctx);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->ran_type = MM_CTX_T_UTRAN_Iu;
|
||||
ctx->iu.ue_ctx = ue_ctx;
|
||||
ctx->iu.ue_ctx->rab_assign_addr_enc = sgsn->cfg.iu.rab_assign_addr_enc;
|
||||
ctx->iu.new_key = 1;
|
||||
ctx->gmm_state = GMM_DEREGISTERED;
|
||||
ctx->pmm_state = PMM_DETACHED;
|
||||
ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
|
||||
ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, ue_ctx->conn_id);
|
||||
if (!ctx->ctrg) {
|
||||
LOGMMCTXP(LOGL_ERROR, ctx, "Cannot allocate counter group for %s.%u\n",
|
||||
mmctx_ctrg_desc.group_name_prefix, ue_ctx->conn_id);
|
||||
talloc_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
ctx->gmm_att_req.fsm = osmo_fsm_inst_alloc(&gmm_attach_req_fsm, ctx, ctx, LOGL_DEBUG, "gb_gmm_req");
|
||||
|
||||
/* Need to get RAID from IU conn */
|
||||
ctx->ra = ctx->iu.ue_ctx->ra_id;
|
||||
|
||||
INIT_LLIST_HEAD(&ctx->pdp_list);
|
||||
|
||||
llist_add(&ctx->list, &sgsn_mm_ctxts);
|
||||
|
||||
return ctx;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* this is a hard _free_ function, it doesn't clean up the PDP contexts
|
||||
* in libgtp! */
|
||||
static void sgsn_mm_ctx_free(struct sgsn_mm_ctx *mm)
|
||||
{
|
||||
struct sgsn_pdp_ctx *pdp, *pdp2;
|
||||
|
||||
/* Unlink from global list of MM contexts */
|
||||
llist_del(&mm->list);
|
||||
|
||||
/* Free all PDP contexts */
|
||||
llist_for_each_entry_safe(pdp, pdp2, &mm->pdp_list, list)
|
||||
sgsn_pdp_ctx_free(pdp);
|
||||
|
||||
rate_ctr_group_free(mm->ctrg);
|
||||
|
||||
talloc_free(mm);
|
||||
}
|
||||
|
||||
void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *mm)
|
||||
{
|
||||
struct gprs_llc_llme *llme = NULL;
|
||||
uint32_t tlli = mm->gb.tlli;
|
||||
struct sgsn_pdp_ctx *pdp, *pdp2;
|
||||
struct sgsn_signal_data sig_data;
|
||||
|
||||
if (mm->ran_type == MM_CTX_T_GERAN_Gb)
|
||||
llme = mm->gb.llme;
|
||||
else
|
||||
OSMO_ASSERT(mm->gb.llme == NULL);
|
||||
|
||||
/* Forget about ongoing look-ups */
|
||||
if (mm->ggsn_lookup) {
|
||||
LOGMMCTXP(LOGL_NOTICE, mm,
|
||||
"Cleaning mmctx with on-going query.\n");
|
||||
mm->ggsn_lookup->mmctx = NULL;
|
||||
mm->ggsn_lookup = NULL;
|
||||
}
|
||||
|
||||
/* delete all existing PDP contexts for this MS */
|
||||
llist_for_each_entry_safe(pdp, pdp2, &mm->pdp_list, list) {
|
||||
LOGMMCTXP(LOGL_NOTICE, mm,
|
||||
"Dropping PDP context for NSAPI=%u\n", pdp->nsapi);
|
||||
sgsn_pdp_ctx_terminate(pdp);
|
||||
}
|
||||
|
||||
if (osmo_timer_pending(&mm->timer)) {
|
||||
LOGMMCTXP(LOGL_INFO, mm, "Cancelling MM timer %u\n", mm->T);
|
||||
osmo_timer_del(&mm->timer);
|
||||
}
|
||||
|
||||
memset(&sig_data, 0, sizeof(sig_data));
|
||||
sig_data.mm = mm;
|
||||
osmo_signal_dispatch(SS_SGSN, S_SGSN_MM_FREE, &sig_data);
|
||||
|
||||
|
||||
/* Detach from subscriber which is possibly freed then */
|
||||
if (mm->subscr) {
|
||||
struct gprs_subscr *subscr = gprs_subscr_get(mm->subscr);
|
||||
gprs_subscr_cleanup(subscr);
|
||||
gprs_subscr_put(subscr);
|
||||
}
|
||||
|
||||
if (mm->gmm_att_req.fsm)
|
||||
gmm_att_req_free(mm);
|
||||
|
||||
sgsn_mm_ctx_free(mm);
|
||||
mm = NULL;
|
||||
|
||||
if (llme) {
|
||||
/* TLLI unassignment, must be called after sgsn_mm_ctx_free */
|
||||
gprs_llgmm_assign(llme, tlli, 0xffffffff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
struct sgsn_pdp_ctx *pdp;
|
||||
|
||||
llist_for_each_entry(pdp, &mm->pdp_list, list) {
|
||||
if (pdp->nsapi == nsapi)
|
||||
return pdp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look up PDP context by MM context and transaction ID */
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
|
||||
uint8_t tid)
|
||||
{
|
||||
struct sgsn_pdp_ctx *pdp;
|
||||
|
||||
llist_for_each_entry(pdp, &mm->pdp_list, list) {
|
||||
if (pdp->ti == tid)
|
||||
return pdp;
|
||||
}
|
||||
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 */
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
if (llist_empty(&ggc->pdp_list) || ggc->echo_interval <= 0) {
|
||||
if (osmo_timer_pending(&ggc->echo_timer))
|
||||
osmo_timer_del(&ggc->echo_timer);
|
||||
} else {
|
||||
if (!osmo_timer_pending(&ggc->echo_timer))
|
||||
osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
ggc->echo_interval = -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;
|
||||
uint32_t ptmsi = 0xdeadbeef;
|
||||
int max_retries = 100, rc = 0;
|
||||
|
||||
restart:
|
||||
rc = osmo_get_rand_id((uint8_t *) &ptmsi, sizeof(ptmsi));
|
||||
if (rc < 0)
|
||||
goto failed;
|
||||
|
||||
/* Enforce that the 2 MSB are set without loosing the distance between
|
||||
* identical values. Since rand() has no duplicate values within a
|
||||
* period (because the size of the state is the same like the size of
|
||||
* the random value), this leads to a distance of period/4 when the
|
||||
* distribution of the 2 MSB is uniform. This approach fails with a
|
||||
* probability of (3/4)^max_retries, only 1% of the approaches will
|
||||
* need more than 16 numbers (even distribution assumed).
|
||||
*
|
||||
* Alternatively, a freeze list could be used if another PRNG is used
|
||||
* or when this approach proves to be not sufficient.
|
||||
*/
|
||||
if (ptmsi >= 0xC0000000) {
|
||||
if (!max_retries--)
|
||||
goto failed;
|
||||
goto restart;
|
||||
}
|
||||
ptmsi |= 0xC0000000;
|
||||
|
||||
if (ptmsi == GSM_RESERVED_TMSI) {
|
||||
if (!max_retries--)
|
||||
goto failed;
|
||||
goto restart;
|
||||
}
|
||||
|
||||
llist_for_each_entry(mm, &sgsn_mm_ctxts, list) {
|
||||
if (mm->p_tmsi == ptmsi) {
|
||||
if (!max_retries--)
|
||||
goto failed;
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
|
||||
return ptmsi;
|
||||
|
||||
failed:
|
||||
LOGP(DGPRS, LOGL_ERROR, "Failed to allocate a P-TMSI: %d (%s)\n", rc, strerror(-rc));
|
||||
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_state == 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;
|
||||
}
|
||||
|
||||
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
|
||||
{
|
||||
sgsn_ggsn_ctx_check_echo_timer(ggc);
|
||||
|
||||
llist_add(&pdp->ggsn_list, &ggc->pdp_list);
|
||||
}
|
||||
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);
|
||||
LOGMMCTXP(LOGL_INFO, mmctx, "Subscriber data update\n");
|
||||
|
||||
sgsn_auth_update(mmctx);
|
||||
}
|
||||
|
||||
static void insert_extra(struct tlv_parsed *tp,
|
||||
struct sgsn_subscriber_data *data,
|
||||
struct sgsn_subscriber_pdp_data *pdp)
|
||||
{
|
||||
tp->lv[OSMO_IE_GSM_SUB_QOS].len = pdp->qos_subscribed_len;
|
||||
tp->lv[OSMO_IE_GSM_SUB_QOS].val = pdp->qos_subscribed;
|
||||
|
||||
/* Prefer PDP charging characteristics of per subscriber one */
|
||||
if (pdp->has_pdp_charg) {
|
||||
tp->lv[OSMO_IE_GSM_CHARG_CHAR].len = sizeof(pdp->pdp_charg);
|
||||
tp->lv[OSMO_IE_GSM_CHARG_CHAR].val = &pdp->pdp_charg[0];
|
||||
} else if (data->has_pdp_charg) {
|
||||
tp->lv[OSMO_IE_GSM_CHARG_CHAR].len = sizeof(data->pdp_charg);
|
||||
tp->lv[OSMO_IE_GSM_CHARG_CHAR].val = &data->pdp_charg[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The tlv_parsed tp parameter will be modified to insert a
|
||||
* OSMO_IE_GSM_SUB_QOS in case the data is available in the
|
||||
* PDP context handling.
|
||||
*/
|
||||
struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
|
||||
struct tlv_parsed *tp,
|
||||
enum gsm48_gsm_cause *gsm_cause,
|
||||
char *out_apn_str)
|
||||
{
|
||||
char req_apn_str[GSM_APN_LENGTH] = {0};
|
||||
const struct apn_ctx *apn_ctx = NULL;
|
||||
const char *selected_apn_str = NULL;
|
||||
struct sgsn_subscriber_pdp_data *pdp;
|
||||
struct sgsn_ggsn_ctx *ggsn = NULL;
|
||||
int allow_any_apn = 0;
|
||||
|
||||
out_apn_str[0] = '\0';
|
||||
|
||||
if (TLVP_PRESENT(tp, GSM48_IE_GSM_APN)) {
|
||||
if (TLVP_LEN(tp, GSM48_IE_GSM_APN) >= GSM_APN_LENGTH - 1) {
|
||||
LOGMMCTXP(LOGL_ERROR, mmctx, "APN IE too long\n");
|
||||
*gsm_cause = GSM_CAUSE_INV_MAND_INFO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osmo_apn_to_str(req_apn_str,
|
||||
TLVP_VAL(tp, GSM48_IE_GSM_APN),
|
||||
TLVP_LEN(tp, GSM48_IE_GSM_APN));
|
||||
|
||||
if (strcmp(req_apn_str, "*") == 0)
|
||||
req_apn_str[0] = 0;
|
||||
}
|
||||
|
||||
if (mmctx->subscr == NULL)
|
||||
allow_any_apn = 1;
|
||||
|
||||
if (strlen(req_apn_str) == 0 && !allow_any_apn) {
|
||||
/* No specific APN requested, check for an APN that is both
|
||||
* granted and configured */
|
||||
|
||||
llist_for_each_entry(pdp, &mmctx->subscr->sgsn_data->pdp_list, list) {
|
||||
if (strcmp(pdp->apn_str, "*") == 0)
|
||||
{
|
||||
allow_any_apn = 1;
|
||||
selected_apn_str = "";
|
||||
insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
|
||||
continue;
|
||||
}
|
||||
if (!llist_empty(&sgsn_apn_ctxts)) {
|
||||
apn_ctx = sgsn_apn_ctx_match(req_apn_str, mmctx->imsi);
|
||||
/* Not configured */
|
||||
if (apn_ctx == NULL)
|
||||
continue;
|
||||
}
|
||||
insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
|
||||
selected_apn_str = pdp->apn_str;
|
||||
break;
|
||||
}
|
||||
} else if (!allow_any_apn) {
|
||||
/* Check whether the given APN is granted */
|
||||
llist_for_each_entry(pdp, &mmctx->subscr->sgsn_data->pdp_list, list) {
|
||||
if (strcmp(pdp->apn_str, "*") == 0) {
|
||||
insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
|
||||
selected_apn_str = req_apn_str;
|
||||
allow_any_apn = 1;
|
||||
continue;
|
||||
}
|
||||
if (strcasecmp(pdp->apn_str, req_apn_str) == 0) {
|
||||
insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
|
||||
selected_apn_str = req_apn_str;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (strlen(req_apn_str) != 0) {
|
||||
/* Any APN is allowed */
|
||||
selected_apn_str = req_apn_str;
|
||||
} else {
|
||||
/* Prefer the GGSN associated with the wildcard APN */
|
||||
selected_apn_str = "";
|
||||
}
|
||||
|
||||
if (!allow_any_apn && selected_apn_str == NULL) {
|
||||
/* Access not granted */
|
||||
LOGMMCTXP(LOGL_NOTICE, mmctx,
|
||||
"The requested APN '%s' is not allowed\n",
|
||||
req_apn_str);
|
||||
*gsm_cause = GSM_CAUSE_REQ_SERV_OPT_NOTSUB;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy the selected apn_str */
|
||||
if (selected_apn_str)
|
||||
strcpy(out_apn_str, selected_apn_str);
|
||||
else
|
||||
out_apn_str[0] = '\0';
|
||||
|
||||
if (apn_ctx == NULL && selected_apn_str)
|
||||
apn_ctx = sgsn_apn_ctx_match(selected_apn_str, mmctx->imsi);
|
||||
|
||||
if (apn_ctx != NULL) {
|
||||
ggsn = apn_ctx->ggsn;
|
||||
} else if (llist_empty(&sgsn_apn_ctxts)) {
|
||||
/* No configuration -> use GGSN 0 */
|
||||
ggsn = sgsn_ggsn_ctx_by_id(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);
|
||||
} else {
|
||||
/* No matching configuration found */
|
||||
LOGMMCTXP(LOGL_NOTICE, mmctx,
|
||||
"The selected APN '%s' has not been configured\n",
|
||||
selected_apn_str);
|
||||
*gsm_cause = GSM_CAUSE_MISSING_APN;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ggsn) {
|
||||
LOGMMCTXP(LOGL_NOTICE, mmctx,
|
||||
"No static GGSN configured. Selected APN '%s'\n",
|
||||
selected_apn_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOGMMCTXP(LOGL_INFO, mmctx,
|
||||
"Found GGSN %d for APN '%s' (requested '%s')\n",
|
||||
ggsn->id, selected_apn_str ? selected_apn_str : "---",
|
||||
req_apn_str);
|
||||
|
||||
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.gsup_server_port = OSMO_GSUP_PORT;
|
||||
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);
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
@@ -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;
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
#include <netdb.h>
|
||||
|
||||
extern void *tall_sgsn_ctx;
|
||||
|
||||
struct cares_event_fd {
|
||||
struct llist_head head;
|
||||
struct osmo_fd fd;
|
||||
@@ -51,8 +49,8 @@ static int ares_osmo_fd_cb(struct osmo_fd *fd, unsigned int what)
|
||||
LOGP(DGPRS, LOGL_DEBUG, "C-ares fd(%d) ready(%d)\n", fd->fd, what);
|
||||
|
||||
ares_process_fd(sgsn->ares_channel,
|
||||
(what & BSC_FD_READ) ? fd->fd : ARES_SOCKET_BAD,
|
||||
(what & BSC_FD_WRITE) ? fd->fd : ARES_SOCKET_BAD);
|
||||
(what & OSMO_FD_READ) ? fd->fd : ARES_SOCKET_BAD,
|
||||
(what & OSMO_FD_WRITE) ? fd->fd : ARES_SOCKET_BAD);
|
||||
osmo_ares_reschedule(sgsn);
|
||||
return 0;
|
||||
}
|
||||
@@ -120,14 +118,14 @@ static void setup_ares_osmo_fd(void *data, int fd, int read, int write)
|
||||
|
||||
update_fd:
|
||||
if (read)
|
||||
ufd->fd.when |= BSC_FD_READ;
|
||||
osmo_fd_read_enable(&ufd->fd);
|
||||
else
|
||||
ufd->fd.when &= ~BSC_FD_READ;
|
||||
osmo_fd_read_disable(&ufd->fd);
|
||||
|
||||
if (write)
|
||||
ufd->fd.when |= BSC_FD_WRITE;
|
||||
osmo_fd_write_enable(&ufd->fd);
|
||||
else
|
||||
ufd->fd.when &= ~BSC_FD_WRITE;
|
||||
osmo_fd_write_disable(&ufd->fd);
|
||||
|
||||
osmo_ares_reschedule(sgsn);
|
||||
}
|
||||
|
||||
45
src/gtphub/Makefile.am
Normal file
45
src/gtphub/Makefile.am
Normal file
@@ -0,0 +1,45 @@
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_builddir) \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-fno-strict-aliasing \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(LIBOSMOVTY_CFLAGS) \
|
||||
$(LIBOSMOGSUPCLIENT_CFLAGS) \
|
||||
$(COVERAGE_CFLAGS) \
|
||||
$(LIBGTP_CFLAGS) \
|
||||
$(NULL)
|
||||
if BUILD_IU
|
||||
AM_CFLAGS += \
|
||||
$(LIBASN1C_CFLAGS) \
|
||||
$(LIBOSMOSIGTRAN_CFLAGS) \
|
||||
$(LIBOSMORANAP_CFLAGS) \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
bin_PROGRAMS = osmo-gtphub
|
||||
|
||||
osmo_gtphub_SOURCES = \
|
||||
gtphub_main.c \
|
||||
gtphub.c \
|
||||
gtphub_sock.c \
|
||||
gtphub_ares.c \
|
||||
gtphub_vty.c \
|
||||
$(NULL)
|
||||
|
||||
osmo_gtphub_LDADD = \
|
||||
$(top_builddir)/src/gprs/sgsn_ares.o \
|
||||
$(top_builddir)/src/gprs/gprs_utils.o \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(LIBOSMOVTY_LIBS) \
|
||||
$(LIBCARES_LIBS) \
|
||||
$(LIBGTP_LIBS) \
|
||||
$(LIBOSMOSIGTRAN_LIBS) \
|
||||
-lrt \
|
||||
$(NULL)
|
||||
@@ -29,10 +29,10 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <gtp.h>
|
||||
#include <gtpie.h>
|
||||
#include <osmocom/gtp/gtp.h>
|
||||
#include <osmocom/gtp/gtpie.h>
|
||||
|
||||
#include <osmocom/sgsn/gtphub.h>
|
||||
#include <osmocom/gtphub/gtphub.h>
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
|
||||
@@ -59,15 +59,6 @@ void *osmo_gtphub_ctx;
|
||||
/* TODO move this to osmocom/core/select.h ? */
|
||||
typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what);
|
||||
|
||||
/* TODO move this to osmocom/core/linuxlist.h ? */
|
||||
#define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next)
|
||||
#define llist_first(head, type, entry) \
|
||||
llist_entry(__llist_first(head), type, entry)
|
||||
|
||||
#define __llist_last(head) (((head)->next == (head)) ? NULL : (head)->prev)
|
||||
#define llist_last(head, type, entry) \
|
||||
llist_entry(__llist_last(head), type, entry)
|
||||
|
||||
/* TODO move GTP header stuff to openggsn/gtp/ ? See gtp_decaps*() */
|
||||
|
||||
enum gtp_rc {
|
||||
@@ -167,12 +158,12 @@ void gsn_addr_copy(struct gsn_addr *gsna, const struct gsn_addr *src)
|
||||
}
|
||||
|
||||
int gsn_addr_from_sockaddr(struct gsn_addr *gsna, uint16_t *port,
|
||||
const struct osmo_sockaddr *sa)
|
||||
const struct sgsn_sockaddr *sa)
|
||||
{
|
||||
char addr_str[256];
|
||||
char port_str[6];
|
||||
|
||||
if (osmo_sockaddr_to_strs(addr_str, sizeof(addr_str),
|
||||
if (sgsn_sockaddr_to_strs(addr_str, sizeof(addr_str),
|
||||
port_str, sizeof(port_str),
|
||||
sa, (NI_NUMERICHOST | NI_NUMERICSERV))
|
||||
!= 0) {
|
||||
@@ -484,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)
|
||||
@@ -613,7 +604,7 @@ void expiry_add(struct expiry *exq, struct expiring_item *item, time_t now)
|
||||
|
||||
OSMO_ASSERT(llist_empty(&exq->items)
|
||||
|| (item->expiry
|
||||
>= llist_last(&exq->items, struct expiring_item, entry)->expiry));
|
||||
>= llist_last_entry(&exq->items, struct expiring_item, entry)->expiry));
|
||||
|
||||
/* Add/move to the tail to always sort by expiry, ascending. */
|
||||
llist_del(&item->entry);
|
||||
@@ -853,10 +844,7 @@ static int gtphub_sock_init(struct osmo_fd *ofd,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ofd->when = BSC_FD_READ;
|
||||
ofd->cb = cb;
|
||||
ofd->data = data;
|
||||
ofd->priv_nr = ofd_id;
|
||||
osmo_fd_setup(ofd, -1, OSMO_FD_READ, cb, data, ofd_id);
|
||||
|
||||
int rc;
|
||||
rc = osmo_sock_init_ofd(ofd,
|
||||
@@ -925,7 +913,7 @@ static void gtphub_bind_stop(struct gtphub_bind *b) {
|
||||
/* Recv datagram from from->fd, write sender's address to *from_addr.
|
||||
* Return the number of bytes read, zero on error. */
|
||||
static int gtphub_read(const struct osmo_fd *from,
|
||||
struct osmo_sockaddr *from_addr,
|
||||
struct sgsn_sockaddr *from_addr,
|
||||
uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
OSMO_ASSERT(from_addr);
|
||||
@@ -946,7 +934,7 @@ static int gtphub_read(const struct osmo_fd *from,
|
||||
}
|
||||
|
||||
LOG(LOGL_DEBUG, "Received %d bytes from %s: %s%s\n",
|
||||
(int)received, osmo_sockaddr_to_str(from_addr),
|
||||
(int)received, sgsn_sockaddr_to_str(from_addr),
|
||||
osmo_hexdump(buf, received > 1000? 1000 : received),
|
||||
received > 1000 ? "..." : "");
|
||||
|
||||
@@ -983,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);
|
||||
@@ -1007,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];
|
||||
@@ -1116,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);
|
||||
@@ -1145,9 +1133,7 @@ static const char *gtphub_peer_strb(struct gtphub_peer *peer, char *buf,
|
||||
if (llist_empty(&peer->addresses))
|
||||
return "(addressless)";
|
||||
|
||||
struct gtphub_peer_addr *a = llist_first(&peer->addresses,
|
||||
struct gtphub_peer_addr,
|
||||
entry);
|
||||
struct gtphub_peer_addr *a = llist_first_entry_or_null(&peer->addresses, struct gtphub_peer_addr, entry);
|
||||
return gsn_addr_to_strb(&a->addr, buf, buflen);
|
||||
}
|
||||
|
||||
@@ -1948,14 +1934,14 @@ static int from_sgsns_read_cb(struct osmo_fd *from_sgsns_ofd, unsigned int what)
|
||||
LOG(LOGL_DEBUG, "=== reading from SGSN (%s)\n",
|
||||
gtphub_plane_idx_names[plane_idx]);
|
||||
|
||||
if (!(what & BSC_FD_READ))
|
||||
if (!(what & OSMO_FD_READ))
|
||||
return 0;
|
||||
|
||||
struct gtphub *hub = from_sgsns_ofd->data;
|
||||
|
||||
static uint8_t buf[4096];
|
||||
struct osmo_sockaddr from_addr;
|
||||
struct osmo_sockaddr to_addr;
|
||||
struct sgsn_sockaddr from_addr;
|
||||
struct sgsn_sockaddr to_addr;
|
||||
struct osmo_fd *to_ofd;
|
||||
int len;
|
||||
uint8_t *reply_buf;
|
||||
@@ -1979,14 +1965,14 @@ static int from_ggsns_read_cb(struct osmo_fd *from_ggsns_ofd, unsigned int what)
|
||||
OSMO_ASSERT(plane_idx < GTPH_PLANE_N);
|
||||
LOG(LOGL_DEBUG, "=== reading from GGSN (%s)\n",
|
||||
gtphub_plane_idx_names[plane_idx]);
|
||||
if (!(what & BSC_FD_READ))
|
||||
if (!(what & OSMO_FD_READ))
|
||||
return 0;
|
||||
|
||||
struct gtphub *hub = from_ggsns_ofd->data;
|
||||
|
||||
static uint8_t buf[4096];
|
||||
struct osmo_sockaddr from_addr;
|
||||
struct osmo_sockaddr to_addr;
|
||||
struct sgsn_sockaddr from_addr;
|
||||
struct sgsn_sockaddr to_addr;
|
||||
struct osmo_fd *to_ofd;
|
||||
int len;
|
||||
uint8_t *reply_buf;
|
||||
@@ -2071,9 +2057,9 @@ static int gtphub_unmap(struct gtphub *hub,
|
||||
|
||||
static int gsn_addr_to_sockaddr(struct gsn_addr *src,
|
||||
uint16_t port,
|
||||
struct osmo_sockaddr *dst)
|
||||
struct sgsn_sockaddr *dst)
|
||||
{
|
||||
return osmo_sockaddr_init_udp(dst, gsn_addr_to_str(src), port);
|
||||
return sgsn_sockaddr_init_udp(dst, gsn_addr_to_str(src), port);
|
||||
}
|
||||
|
||||
/* If p is an Echo request, replace p's data with the matching response and
|
||||
@@ -2107,7 +2093,7 @@ static int gtphub_handle_echo_req(struct gtphub *hub, struct gtp_packet_desc *p,
|
||||
}
|
||||
|
||||
struct gtphub_peer_port *gtphub_known_addr_have_port(const struct gtphub_bind *bind,
|
||||
const struct osmo_sockaddr *addr);
|
||||
const struct sgsn_sockaddr *addr);
|
||||
|
||||
/* Parse buffer as GTP packet, replace elements in-place and return the ofd and
|
||||
* address to forward to. Return a pointer to the osmo_fd, but copy the
|
||||
@@ -2117,18 +2103,18 @@ struct gtphub_peer_port *gtphub_known_addr_have_port(const struct gtphub_bind *b
|
||||
int gtphub_handle_buf(struct gtphub *hub,
|
||||
unsigned int side_idx,
|
||||
unsigned int plane_idx,
|
||||
const struct osmo_sockaddr *from_addr,
|
||||
const struct sgsn_sockaddr *from_addr,
|
||||
uint8_t *buf,
|
||||
size_t received,
|
||||
time_t now,
|
||||
uint8_t **reply_buf,
|
||||
struct osmo_fd **to_ofd,
|
||||
struct osmo_sockaddr *to_addr)
|
||||
struct sgsn_sockaddr *to_addr)
|
||||
{
|
||||
struct gtphub_bind *from_bind = &hub->to_gsns[side_idx][plane_idx];
|
||||
struct gtphub_bind *to_bind = &hub->to_gsns[other_side_idx(side_idx)][plane_idx];
|
||||
|
||||
rate_ctr_add(&from_bind->counters_io->ctr[GTPH_CTR_BYTES_IN],
|
||||
rate_ctr_add(rate_ctr_group_get_ctr(from_bind->counters_io, GTPH_CTR_BYTES_IN),
|
||||
received);
|
||||
|
||||
struct gtp_packet_desc p;
|
||||
@@ -2138,7 +2124,7 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
(side_idx == GTPH_SIDE_GGSN)? "<-" : "->",
|
||||
gtphub_plane_idx_names[plane_idx],
|
||||
gtphub_side_idx_names[side_idx],
|
||||
osmo_sockaddr_to_str(from_addr),
|
||||
sgsn_sockaddr_to_str(from_addr),
|
||||
gtp_type_str(p.type));
|
||||
|
||||
if (p.rc <= 0) {
|
||||
@@ -2146,26 +2132,26 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
gtp_type_str(p.type),
|
||||
gtphub_side_idx_names[side_idx],
|
||||
gtphub_plane_idx_names[plane_idx],
|
||||
osmo_sockaddr_to_str(from_addr));
|
||||
sgsn_sockaddr_to_str(from_addr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rate_ctr_inc(&from_bind->counters_io->ctr[GTPH_CTR_PKTS_IN]);
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(from_bind->counters_io, GTPH_CTR_PKTS_IN));
|
||||
|
||||
int reply_len;
|
||||
reply_len = gtphub_handle_echo_req(hub, &p, reply_buf);
|
||||
if (reply_len > 0) {
|
||||
/* It was an echo. Nothing left to do. */
|
||||
osmo_sockaddr_copy(to_addr, from_addr);
|
||||
sgsn_sockaddr_copy(to_addr, from_addr);
|
||||
*to_ofd = &from_bind->ofd;
|
||||
|
||||
rate_ctr_inc(&from_bind->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
|
||||
rate_ctr_add(&from_bind->counters_io->ctr[GTPH_CTR_BYTES_OUT],
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(from_bind->counters_io, GTPH_CTR_PKTS_OUT));
|
||||
rate_ctr_add(rate_ctr_group_get_ctr(from_bind->counters_io, GTPH_CTR_BYTES_OUT),
|
||||
reply_len);
|
||||
LOG(LOGL_DEBUG, "%s Echo response to %s: %d bytes to %s\n",
|
||||
(side_idx == GTPH_SIDE_GGSN)? "-->" : "<--",
|
||||
gtphub_side_idx_names[side_idx],
|
||||
(int)reply_len, osmo_sockaddr_to_str(to_addr));
|
||||
(int)reply_len, sgsn_sockaddr_to_str(to_addr));
|
||||
return reply_len;
|
||||
}
|
||||
if (reply_len < 0)
|
||||
@@ -2178,7 +2164,7 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
* so no-one else is allowed to talk to us from that side. */
|
||||
struct gtphub_peer_port *from_peer = hub->proxy[side_idx][plane_idx];
|
||||
if (from_peer) {
|
||||
if (osmo_sockaddr_cmp(&from_peer->sa, from_addr) != 0) {
|
||||
if (sgsn_sockaddr_cmp(&from_peer->sa, from_addr) != 0) {
|
||||
LOG(LOGL_ERROR,
|
||||
"Rejecting: %s proxy configured, but GTP packet"
|
||||
" received on %s bind is from another sender:"
|
||||
@@ -2186,7 +2172,7 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
gtphub_side_idx_names[side_idx],
|
||||
gtphub_side_idx_names[side_idx],
|
||||
gtphub_port_str(from_peer),
|
||||
osmo_sockaddr_to_str(from_addr));
|
||||
sgsn_sockaddr_to_str(from_addr));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -2204,7 +2190,7 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
if (side_idx == GTPH_SIDE_GGSN) {
|
||||
LOG(LOGL_ERROR, "Dropping packet%s: unknown GGSN peer: %s\n",
|
||||
gtp_type_str(p.type),
|
||||
osmo_sockaddr_to_str(from_addr));
|
||||
sgsn_sockaddr_to_str(from_addr));
|
||||
return -1;
|
||||
} else {
|
||||
/* SGSN */
|
||||
@@ -2216,7 +2202,7 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
"Dropping packet%s: User plane peer was not"
|
||||
"announced by PDP Context: %s\n",
|
||||
gtp_type_str(p.type),
|
||||
osmo_sockaddr_to_str(from_addr));
|
||||
sgsn_sockaddr_to_str(from_addr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2235,13 +2221,13 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
LOG(LOGL_ERROR, "Dropping packet%s: invalid %s peer: %s\n",
|
||||
gtp_type_str(p.type),
|
||||
gtphub_side_idx_names[side_idx],
|
||||
osmo_sockaddr_to_str(from_addr));
|
||||
sgsn_sockaddr_to_str(from_addr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rate_ctr_add(&from_peer->counters_io->ctr[GTPH_CTR_BYTES_IN],
|
||||
rate_ctr_add(rate_ctr_group_get_ctr(from_peer->counters_io, GTPH_CTR_BYTES_IN),
|
||||
received);
|
||||
rate_ctr_inc(&from_peer->counters_io->ctr[GTPH_CTR_PKTS_IN]);
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(from_peer->counters_io, GTPH_CTR_PKTS_IN));
|
||||
|
||||
LOG(LOGL_DEBUG, "from %s peer: %s\n", gtphub_side_idx_names[side_idx],
|
||||
gtphub_port_str(from_peer));
|
||||
@@ -2260,9 +2246,9 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
|
||||
if (p.tun) {
|
||||
struct gtphub_tunnel_endpoint *te = &p.tun->endpoint[p.side_idx][p.plane_idx];
|
||||
rate_ctr_add(&te->counters_io->ctr[GTPH_CTR_BYTES_IN],
|
||||
rate_ctr_add(rate_ctr_group_get_ctr(te->counters_io, GTPH_CTR_BYTES_IN),
|
||||
received);
|
||||
rate_ctr_inc(&te->counters_io->ctr[GTPH_CTR_PKTS_IN]);
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(te->counters_io, GTPH_CTR_PKTS_IN));
|
||||
}
|
||||
|
||||
if ((!to_peer) && (side_idx == GTPH_SIDE_SGSN)) {
|
||||
@@ -2297,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. */
|
||||
@@ -2309,24 +2295,24 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
if (!to_peer_from_seq)
|
||||
gtphub_map_seq(&p, from_peer, to_peer);
|
||||
|
||||
osmo_sockaddr_copy(to_addr, &to_peer->sa);
|
||||
sgsn_sockaddr_copy(to_addr, &to_peer->sa);
|
||||
|
||||
*reply_buf = (uint8_t*)p.data;
|
||||
|
||||
if (received) {
|
||||
rate_ctr_inc(&to_bind->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
|
||||
rate_ctr_add(&to_bind->counters_io->ctr[GTPH_CTR_BYTES_OUT],
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(to_bind->counters_io, GTPH_CTR_PKTS_OUT));
|
||||
rate_ctr_add(rate_ctr_group_get_ctr(to_bind->counters_io, GTPH_CTR_BYTES_OUT),
|
||||
received);
|
||||
|
||||
rate_ctr_inc(&to_peer->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
|
||||
rate_ctr_add(&to_peer->counters_io->ctr[GTPH_CTR_BYTES_OUT],
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(to_peer->counters_io, GTPH_CTR_PKTS_OUT));
|
||||
rate_ctr_add(rate_ctr_group_get_ctr(to_peer->counters_io, GTPH_CTR_BYTES_OUT),
|
||||
received);
|
||||
}
|
||||
|
||||
if (p.tun) {
|
||||
struct gtphub_tunnel_endpoint *te = &p.tun->endpoint[other_side_idx(p.side_idx)][p.plane_idx];
|
||||
rate_ctr_inc(&te->counters_io->ctr[GTPH_CTR_PKTS_OUT]);
|
||||
rate_ctr_add(&te->counters_io->ctr[GTPH_CTR_BYTES_OUT],
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(te->counters_io, GTPH_CTR_PKTS_OUT));
|
||||
rate_ctr_add(rate_ctr_group_get_ctr(te->counters_io, GTPH_CTR_BYTES_OUT),
|
||||
received);
|
||||
}
|
||||
|
||||
@@ -2335,7 +2321,7 @@ int gtphub_handle_buf(struct gtphub *hub,
|
||||
(side_idx == GTPH_SIDE_SGSN)? "-->" : "<--",
|
||||
gtphub_side_idx_names[other_side_idx(side_idx)],
|
||||
p.header_tei, p.seq,
|
||||
(int)received, osmo_sockaddr_to_str(to_addr));
|
||||
(int)received, sgsn_sockaddr_to_str(to_addr));
|
||||
return received;
|
||||
}
|
||||
|
||||
@@ -2645,7 +2631,7 @@ static struct gtphub_peer_port *gtphub_port_find(const struct gtphub_bind *bind,
|
||||
}
|
||||
|
||||
struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind,
|
||||
const struct osmo_sockaddr *addr)
|
||||
const struct sgsn_sockaddr *addr)
|
||||
{
|
||||
struct gsn_addr gsna;
|
||||
uint16_t port;
|
||||
@@ -2704,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));
|
||||
@@ -2762,7 +2748,7 @@ struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
|
||||
/* Find a GGSN peer with a matching address. If the address is known but the
|
||||
* port not, create a new port for that peer address. */
|
||||
struct gtphub_peer_port *gtphub_known_addr_have_port(const struct gtphub_bind *bind,
|
||||
const struct osmo_sockaddr *addr)
|
||||
const struct sgsn_sockaddr *addr)
|
||||
{
|
||||
struct gtphub_peer_addr *pa;
|
||||
struct gtphub_peer_port *pp;
|
||||
@@ -2817,7 +2803,7 @@ static int gtphub_resolve_ggsn(struct gtphub *hub,
|
||||
|
||||
/* TODO move to osmocom/core/socket.c ? */
|
||||
/* use this in osmo_sock_init() to remove dup. */
|
||||
/* Internal: call getaddrinfo for osmo_sockaddr_init(). The caller is required
|
||||
/* Internal: call getaddrinfo for sgsn_sockaddr_init(). The caller is required
|
||||
to call freeaddrinfo(*result), iff zero is returned. */
|
||||
static int _osmo_getaddrinfo(struct addrinfo **result,
|
||||
uint16_t family, uint16_t type, uint8_t proto,
|
||||
@@ -2844,7 +2830,7 @@ static int _osmo_getaddrinfo(struct addrinfo **result,
|
||||
}
|
||||
|
||||
/* TODO move to osmocom/core/socket.c ? */
|
||||
int osmo_sockaddr_init(struct osmo_sockaddr *addr,
|
||||
int sgsn_sockaddr_init(struct sgsn_sockaddr *addr,
|
||||
uint16_t family, uint16_t type, uint8_t proto,
|
||||
const char *host, uint16_t port)
|
||||
{
|
||||
@@ -2865,9 +2851,9 @@ int osmo_sockaddr_init(struct osmo_sockaddr *addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
|
||||
int sgsn_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
|
||||
char *port_str, size_t port_str_len,
|
||||
const struct osmo_sockaddr *addr,
|
||||
const struct sgsn_sockaddr *addr,
|
||||
int flags)
|
||||
{
|
||||
int rc;
|
||||
@@ -2896,14 +2882,14 @@ int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
|
||||
return rc;
|
||||
}
|
||||
|
||||
const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
|
||||
const char *sgsn_sockaddr_to_strb(const struct sgsn_sockaddr *addr,
|
||||
char *buf, size_t buf_len)
|
||||
{
|
||||
char portbuf[6];
|
||||
const int portbuf_len = 6;
|
||||
OSMO_ASSERT(buf_len > portbuf_len);
|
||||
char *portbuf = buf + buf_len - portbuf_len;
|
||||
buf_len -= portbuf_len;
|
||||
if (osmo_sockaddr_to_strs(buf, buf_len,
|
||||
if (sgsn_sockaddr_to_strs(buf, buf_len,
|
||||
portbuf, portbuf_len,
|
||||
addr,
|
||||
NI_NUMERICHOST | NI_NUMERICSERV))
|
||||
@@ -2918,17 +2904,17 @@ const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr)
|
||||
const char *sgsn_sockaddr_to_str(const struct sgsn_sockaddr *addr)
|
||||
{
|
||||
static char buf[256];
|
||||
const char *result = osmo_sockaddr_to_strb(addr, buf, sizeof(buf));
|
||||
const char *result = sgsn_sockaddr_to_strb(addr, buf, sizeof(buf));
|
||||
if (! result)
|
||||
return "(invalid)";
|
||||
return result;
|
||||
}
|
||||
|
||||
int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
|
||||
const struct osmo_sockaddr *b)
|
||||
int sgsn_sockaddr_cmp(const struct sgsn_sockaddr *a,
|
||||
const struct sgsn_sockaddr *b)
|
||||
{
|
||||
if (a == b)
|
||||
return 0;
|
||||
@@ -2938,7 +2924,7 @@ int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
|
||||
return 1;
|
||||
if (a->l != b->l) {
|
||||
/* Lengths are not the same, but determine the order. Will
|
||||
* anyone ever sort a list by osmo_sockaddr though...? */
|
||||
* anyone ever sort a list by sgsn_sockaddr though...? */
|
||||
int cmp = memcmp(&a->a, &b->a, (a->l < b->l)? a->l : b->l);
|
||||
if (cmp == 0) {
|
||||
if (a->l < b->l)
|
||||
@@ -2951,8 +2937,8 @@ int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
|
||||
return memcmp(&a->a, &b->a, a->l);
|
||||
}
|
||||
|
||||
void osmo_sockaddr_copy(struct osmo_sockaddr *dst,
|
||||
const struct osmo_sockaddr *src)
|
||||
void sgsn_sockaddr_copy(struct sgsn_sockaddr *dst,
|
||||
const struct sgsn_sockaddr *src)
|
||||
{
|
||||
OSMO_ASSERT(src->l <= sizeof(dst->a));
|
||||
memcpy(&dst->a, &src->a, src->l);
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
@@ -95,11 +96,11 @@ void log_cfg(struct gtphub_cfg *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
static void signal_handler(int signal)
|
||||
static void signal_handler(int signum)
|
||||
{
|
||||
fprintf(stdout, "signal %d received\n", signal);
|
||||
fprintf(stdout, "signal %d received\n", signum);
|
||||
|
||||
switch (signal) {
|
||||
switch (signum) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
|
||||
@@ -107,8 +108,16 @@ static void signal_handler(int signal)
|
||||
exit(0);
|
||||
break;
|
||||
case SIGABRT:
|
||||
/* in case of abort, we want to obtain a talloc report
|
||||
* and then return to the caller, who will abort the process */
|
||||
/* in case of abort, we want to obtain a talloc report and
|
||||
* then run default SIGABRT handler, who will generate coredump
|
||||
* and abort the process. abort() should do this for us after we
|
||||
* return, but program wouldn't exit if an external SIGABRT is
|
||||
* received.
|
||||
*/
|
||||
talloc_report_full(osmo_gtphub_ctx, stderr);
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
raise(SIGABRT);
|
||||
break;
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
talloc_report_full(osmo_gtphub_ctx, stderr);
|
||||
@@ -118,44 +127,12 @@ static void signal_handler(int signal)
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILD_IU
|
||||
int gtphub_vty_go_parent(struct vty *vty)
|
||||
{
|
||||
switch (vty->node) {
|
||||
default:
|
||||
osmo_ss7_vty_go_parent(vty);
|
||||
}
|
||||
|
||||
return vty->node;
|
||||
}
|
||||
#endif
|
||||
|
||||
int gtphub_vty_is_config_node(struct vty *vty, int node)
|
||||
{
|
||||
/* Check if libosmo-sccp declares the node in
|
||||
* question as config node */
|
||||
#if BUILD_IU
|
||||
if (osmo_ss7_is_config_node(vty, node))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
switch (node) {
|
||||
/* add items that are not config */
|
||||
case CONFIG_NODE:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static struct vty_app_info vty_info = {
|
||||
.name = "OsmoGTPhub",
|
||||
.version = PACKAGE_VERSION,
|
||||
#if BUILD_IU
|
||||
.go_parent_cb = gtphub_vty_go_parent,
|
||||
.go_parent_cb = osmo_ss7_vty_go_parent,
|
||||
#endif
|
||||
.is_config_node = gtphub_vty_is_config_node,
|
||||
};
|
||||
|
||||
struct cmdline_cfg {
|
||||
@@ -238,12 +215,12 @@ static void print_help(struct cmdline_cfg *ccfg)
|
||||
printf(" -e,--log-level <nr> Set a global log level.\n");
|
||||
printf(" -r,--restart-file <path> File for counting restarts [%s].\n",
|
||||
ccfg->restart_counter_file);
|
||||
printf(" -V,--version Print the version number.\n");
|
||||
printf(" -V,--version Print the version.\n");
|
||||
}
|
||||
|
||||
static void list_categories(void)
|
||||
{
|
||||
printf("Avaliable debug categories:\n");
|
||||
printf("Available debug categories:\n");
|
||||
int i;
|
||||
for (i = 0; i < gtphub_log_info.num_cat; ++i) {
|
||||
if (!gtphub_log_info.cat[i].name)
|
||||
@@ -322,6 +299,11 @@ static void handle_options(struct cmdline_cfg *ccfg, int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > optind) {
|
||||
fprintf(stderr, "Unsupported positional arguments on command line\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@@ -356,7 +338,7 @@ int main(int argc, char **argv)
|
||||
|
||||
vty_info.copyright = gtphub_copyright;
|
||||
vty_init(&vty_info);
|
||||
logging_vty_add_cmds(NULL);
|
||||
logging_vty_add_cmds();
|
||||
osmo_talloc_vty_add_cmds();
|
||||
gtphub_vty_init(hub, cfg);
|
||||
|
||||
@@ -372,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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user