mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-sgsn.git
				synced 2025-11-03 21:53:16 +00:00 
			
		
		
		
	Compare commits
	
		
			129 Commits
		
	
	
		
			pespin/rel
			...
			osmith/fix
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					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 | 
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -2,6 +2,7 @@ debian/*.log
 | 
			
		||||
*.o
 | 
			
		||||
*.lo
 | 
			
		||||
*.a
 | 
			
		||||
*.la
 | 
			
		||||
.deps
 | 
			
		||||
Makefile
 | 
			
		||||
Makefile.in
 | 
			
		||||
@@ -38,9 +39,9 @@ ltmain.sh
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# apps and app data
 | 
			
		||||
src/gprs/osmo-sgsn
 | 
			
		||||
src/gprs/osmo-gbproxy
 | 
			
		||||
src/gprs/osmo-gtphub
 | 
			
		||||
src/sgsn/osmo-sgsn
 | 
			
		||||
src/gbproxy/osmo-gbproxy
 | 
			
		||||
src/gtphub/osmo-gtphub
 | 
			
		||||
src/libcommon/gsup_test_client
 | 
			
		||||
 | 
			
		||||
#tests
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								TODO-RELEASE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								TODO-RELEASE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
#component	what		description / commit summary line
 | 
			
		||||
osmo-sgsn	libgtp		We dropped libgtp gtp_retranstimeout timer code which became a
 | 
			
		||||
				no-op in osmo-ggsn.git c94837c6a401bf0f80791b619a9b4cfbe9160afd,
 | 
			
		||||
				which means next osmo-sgsn release will require libgtp > 1.4.0.
 | 
			
		||||
							
								
								
									
										17
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								configure.ac
									
									
									
									
									
								
							@@ -39,12 +39,12 @@ AC_SEARCH_LIBS([dlopen], [dl dld], [LIBRARY_DL="$LIBS";LIBS=""])
 | 
			
		||||
AC_SUBST(LIBRARY_DL)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.0.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.0.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.0.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.0.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.2.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.2.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.2.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.2.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.2.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 1.0.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.4.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.0.0)
 | 
			
		||||
 | 
			
		||||
@@ -61,7 +61,7 @@ AM_CONDITIONAL(BUILD_IU, test "x$osmo_ac_iu" = "xyes")
 | 
			
		||||
AC_SUBST(osmo_ac_iu)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.3.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBGTP, libgtp >= 1.4.0)
 | 
			
		||||
PKG_CHECK_MODULES(LIBCARES, libcares)
 | 
			
		||||
 | 
			
		||||
dnl checks for header files
 | 
			
		||||
@@ -116,7 +116,7 @@ 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([-Wnull-dereference], [CFLAGS="$CFLAGS -Wnull-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"])
 | 
			
		||||
 | 
			
		||||
@@ -247,6 +247,9 @@ AC_OUTPUT(
 | 
			
		||||
    include/osmocom/sgsn/Makefile
 | 
			
		||||
    src/Makefile
 | 
			
		||||
    src/gprs/Makefile
 | 
			
		||||
    src/sgsn/Makefile
 | 
			
		||||
    src/gbproxy/Makefile
 | 
			
		||||
    src/gtphub/Makefile
 | 
			
		||||
    tests/Makefile
 | 
			
		||||
    tests/atlocal
 | 
			
		||||
    tests/gprs/Makefile
 | 
			
		||||
 
 | 
			
		||||
@@ -77,4 +77,5 @@ if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
 | 
			
		||||
	make -C "$base/doc/manuals" publish
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
$MAKE maintainer-clean
 | 
			
		||||
osmo-clean-workspace.sh
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										66
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,69 @@
 | 
			
		||||
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 ]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -10,17 +10,18 @@ Build-Depends: debhelper (>=9),
 | 
			
		||||
               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.4.0),
 | 
			
		||||
               libosmocore-dev (>= 1.2.0),
 | 
			
		||||
               libosmo-abis-dev (>= 0.6.0),
 | 
			
		||||
               libosmo-netif-dev (>= 0.4.0),
 | 
			
		||||
               libosmo-gsup-client-dev (>= 1.0.0),
 | 
			
		||||
               libasn1c-dev (>= 0.9.30),
 | 
			
		||||
               libosmo-ranap-dev (>= 0.4.0),
 | 
			
		||||
               libosmo-sigtran-dev (>= 1.0.0),
 | 
			
		||||
               libosmo-sccp-dev (>= 1.0.0),
 | 
			
		||||
               osmo-gsm-manuals-dev
 | 
			
		||||
Standards-Version: 3.9.8
 | 
			
		||||
Vcs-Git: git://git.osmocom.org/osmo-sgsn.git
 | 
			
		||||
Vcs-Browser: https://git.osmocom.org/osmo-sgsn
 | 
			
		||||
@@ -67,3 +68,12 @@ 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.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										62
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							@@ -81,38 +81,38 @@ Files:     include/osmocom/sgsn/a_reset.h
 | 
			
		||||
           include/osmocom/sgsn/gprs_utils.h
 | 
			
		||||
           include/osmocom/sgsn/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_gb_parse.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/gbproxy/gb_proxy.c
 | 
			
		||||
           src/gbproxy/gb_proxy_main.c
 | 
			
		||||
           src/gbproxy/gb_proxy_patch.c
 | 
			
		||||
           src/gbproxy/gb_proxy_peer.c
 | 
			
		||||
           src/gbproxy/gb_proxy_tlli.c
 | 
			
		||||
           src/gbproxy/gb_proxy_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/sgsn_test.c
 | 
			
		||||
           tests/slhc/slhc_test.c
 | 
			
		||||
@@ -140,8 +140,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
 | 
			
		||||
Files:     src/gtphub/gtphub_ares.c
 | 
			
		||||
           src/gtphub/gtphub_sock.c
 | 
			
		||||
           tests/gbproxy/gbproxy_test.c
 | 
			
		||||
Copyright: 2013 Jacob Erlbeck <jerlbeck@sysmocom.de>
 | 
			
		||||
           2013 sysmocom s.f.m.c. GmbH
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										6
									
								
								debian/rules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								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)
 | 
			
		||||
#
 | 
			
		||||
@@ -63,3 +63,7 @@ override_dh_strip:
 | 
			
		||||
# 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
 | 
			
		||||
 
 | 
			
		||||
@@ -22,4 +22,5 @@ ns
 | 
			
		||||
 timer tns-alive-retries 10
 | 
			
		||||
 encapsulation framerelay-gre enabled 0
 | 
			
		||||
 encapsulation framerelay-gre local-ip 0.0.0.0
 | 
			
		||||
 encapsulation udp local-ip 127.0.0.100
 | 
			
		||||
 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:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ line vty
 | 
			
		||||
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-sgsns 127.0.0.10
 | 
			
		||||
 bind-to-ggsns 127.0.0.2
 | 
			
		||||
 | 
			
		||||
 ! Local nonstandard ports or separate IPs:
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ sgsn
 | 
			
		||||
 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
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ sgsn
 | 
			
		||||
 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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								doc/examples/osmo-sgsn/osmo-sgsn_custom-sccp.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								doc/examples/osmo-sgsn/osmo-sgsn_custom-sccp.cfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
!
 | 
			
		||||
! Osmocom SGSN configuration
 | 
			
		||||
!
 | 
			
		||||
!
 | 
			
		||||
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
 | 
			
		||||
 as as-clnt-OsmoSGSN-A m3ua
 | 
			
		||||
  asp asp-clnt-OsmoSGSN-A
 | 
			
		||||
  routing-key 3 0.23.4
 | 
			
		||||
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
 | 
			
		||||
 encapsulation udp local-ip 127.0.0.1
 | 
			
		||||
 encapsulation udp local-port 23000
 | 
			
		||||
 encapsulation framerelay-gre enabled 0
 | 
			
		||||
!
 | 
			
		||||
bssgp
 | 
			
		||||
!
 | 
			
		||||
@@ -1,16 +1,23 @@
 | 
			
		||||
EXTRA_DIST = osmosgsn-usermanual.adoc \
 | 
			
		||||
    osmosgsn-usermanual-docinfo.xml \
 | 
			
		||||
    osmosgsn-vty-reference.xml \
 | 
			
		||||
    osmogbproxy-usermanual.adoc \
 | 
			
		||||
    osmogbproxy-usermanual-docinfo.xml \
 | 
			
		||||
    regen_doc.sh \
 | 
			
		||||
    chapters \
 | 
			
		||||
    vty
 | 
			
		||||
    vty \
 | 
			
		||||
    osmogbproxy-vty-reference.xml \
 | 
			
		||||
    vty-osmogbproxy \
 | 
			
		||||
    $(NULL)
 | 
			
		||||
 | 
			
		||||
if BUILD_MANUALS
 | 
			
		||||
  ASCIIDOC = osmosgsn-usermanual.adoc
 | 
			
		||||
  ASCIIDOC = osmosgsn-usermanual.adoc osmogbproxy-usermanual.adoc
 | 
			
		||||
  ASCIIDOC_DEPS = $(srcdir)/chapters/*.adoc
 | 
			
		||||
  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
 | 
			
		||||
 | 
			
		||||
  VTY_REFERENCE = osmosgsn-vty-reference.xml
 | 
			
		||||
  VTY_REFERENCE = osmosgsn-vty-reference.xml osmogbproxy-vty-reference.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,7 +7,7 @@ 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.
 | 
			
		||||
 | 
			
		||||
@@ -17,7 +17,7 @@ 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.
 | 
			
		||||
@@ -100,7 +100,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 +116,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 +153,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 +251,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 +277,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 +304,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 +321,38 @@ 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)
 | 
			
		||||
----
 | 
			
		||||
sgsn
 | 
			
		||||
 encryption GEA3
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
.Example: Turn off encryption (GEA0)
 | 
			
		||||
----
 | 
			
		||||
sgsn
 | 
			
		||||
 encryption GEA0
 | 
			
		||||
----
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
[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
 | 
			
		||||
@@ -93,6 +65,8 @@ These counters and their description based on OsmoSGSN UNKNOWN (OsmoSGSN).
 | 
			
		||||
| 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
 | 
			
		||||
@@ -102,20 +76,7 @@ NSVC Peer Statistics
 | 
			
		||||
| 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 
 | 
			
		||||
[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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								doc/manuals/chapters/gbproxy-configuration.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								doc/manuals/chapters/gbproxy-configuration.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
== Configuring OsmoGbPROXY
 | 
			
		||||
 | 
			
		||||
TBD.  Unfortunately this chapter of the manual still needs to be written.
 | 
			
		||||
Osmocom has very limited funding and support resources; Feel free to help
 | 
			
		||||
us completing this documentation by contributing with code, documentation
 | 
			
		||||
or by supporting the developers financially.
 | 
			
		||||
							
								
								
									
										29
									
								
								doc/manuals/chapters/gbproxy-control.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								doc/manuals/chapters/gbproxy-control.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
[[control]]
 | 
			
		||||
== Control interface
 | 
			
		||||
 | 
			
		||||
The actual protocol is described in <<common-control-if>>, the variables
 | 
			
		||||
common to all programs using it are described in <<ctrl_common_vars>>. Here we
 | 
			
		||||
describe variables specific to OsmoGbPROXY.
 | 
			
		||||
 | 
			
		||||
.Variables available over control interface
 | 
			
		||||
[options="header",width="100%",cols="20%,5%,5%,50%,20%"]
 | 
			
		||||
|===
 | 
			
		||||
|Name|Access|Trap|Value|Comment
 | 
			
		||||
|nsvc-state|RO|No|"<nsei>,<nsvci>,<local-alive>,<local-blocked>,<remote-role>,<remote-alive>,<remote-blocked>"|See <<nsvc_state>> for details.
 | 
			
		||||
|gbproxy-state|RO|No|"<nsei>,<bvci>,<mcc>,<mnc>,<lac>,<rac>,<blocked>"|See <<gbproxy_state>> for details.
 | 
			
		||||
|number-of-peers|RO|No|"<num-of-bss>"|Count of concurrent BSS(BTS) peers.
 | 
			
		||||
|===
 | 
			
		||||
 | 
			
		||||
[[nsvc_state]]
 | 
			
		||||
=== nsvc-state
 | 
			
		||||
 | 
			
		||||
Return the list of active NS-VCs (NS Virtual Circuits), including information
 | 
			
		||||
on the key parameters, such as NSEI, NSVCI and the local + remote ALIVE
 | 
			
		||||
and BLOCKED state.
 | 
			
		||||
 | 
			
		||||
[[gbproxy_state]]
 | 
			
		||||
=== gbproxy-state
 | 
			
		||||
 | 
			
		||||
Return the list of active Peers, including information on the key
 | 
			
		||||
parameters, such as NSEI, BVCI, and the MCC-MNC-LAC-RAC of the attached
 | 
			
		||||
BSS, as well as the overall state (BLOCKED or UNBLOCKED).
 | 
			
		||||
							
								
								
									
										127
									
								
								doc/manuals/chapters/gbproxy-overview.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								doc/manuals/chapters/gbproxy-overview.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
			
		||||
[[chapter_overview]]
 | 
			
		||||
== Overview
 | 
			
		||||
 | 
			
		||||
=== About OsmoGbPROXY
 | 
			
		||||
 | 
			
		||||
OsmoGbPROXY is the Osmocom proxy for the 3GPP Gb interface.  The Gb
 | 
			
		||||
interface is defined by 3GPP as the protocol between the BSS and the
 | 
			
		||||
SGSN inside the 2G/2.5G/2.75G packet switched network domain.
 | 
			
		||||
 | 
			
		||||
As Osmocom implements a BTS-colocated PCU, there are potentially many
 | 
			
		||||
Gb interface connections between all those many PCUs in the network
 | 
			
		||||
and the SGSN.  This can be cumbersome to configure/maintain at the
 | 
			
		||||
SGSN sine.
 | 
			
		||||
 | 
			
		||||
OsmoGbPROXY aggregates many PCU-facing Gb connections into one Gb
 | 
			
		||||
connection to the SGSN.  This is achieved by
 | 
			
		||||
 | 
			
		||||
* maintaining sepaate NS-VCs on the PCU side and on the SGSN side
 | 
			
		||||
* more or less transparently routing BSSGP peer-to-peer Virtual Circuits
 | 
			
		||||
  (BVCs) through the proxy
 | 
			
		||||
* having some special handling for the signaling BVC (BVCI=0) which is
 | 
			
		||||
  shared among all the PCUs connected to the proxy
 | 
			
		||||
 | 
			
		||||
=== Data Model
 | 
			
		||||
 | 
			
		||||
==== gbproxy_config
 | 
			
		||||
 | 
			
		||||
This contains the parsed configuration of the OsmoGbPROXY.
 | 
			
		||||
 | 
			
		||||
==== gproxy_peer
 | 
			
		||||
 | 
			
		||||
A "peer" is any remote NS-entity that the proxy interacts with.  A peer
 | 
			
		||||
includes information about:
 | 
			
		||||
 | 
			
		||||
* the [unique] NSEI of the peer
 | 
			
		||||
* the [unique] BVCI of the peer
 | 
			
		||||
* the Routeing Area (RA) of the peer
 | 
			
		||||
 | 
			
		||||
==== gbproxy_tlli_state
 | 
			
		||||
 | 
			
		||||
One of the (unique) TLLI of any of the subscribers/UEs attached to any of
 | 
			
		||||
the BTSs/PCUs served by the proxy.
 | 
			
		||||
 | 
			
		||||
==== gbproxy_link_info
 | 
			
		||||
 | 
			
		||||
One of the [unique] subscribers/connections that are served through this
 | 
			
		||||
proxy.  The information includes
 | 
			
		||||
 | 
			
		||||
* the TLLI on BSS side
 | 
			
		||||
* the TLLI on SGSN side (may be different due to P-TMSI rewriting)
 | 
			
		||||
* the NSEI of the SGSN for this link
 | 
			
		||||
* a timestamp when we last conversed with this subscriber
 | 
			
		||||
* state related to IMSI acquisition
 | 
			
		||||
** a temporary queue of stored messages (until IMSI acquisition succeeds)
 | 
			
		||||
** N(U) rewriting state (inserting IDENTTIY REQ changes LLC sequence numbers)
 | 
			
		||||
 | 
			
		||||
==== gbproxy_match
 | 
			
		||||
 | 
			
		||||
A single matching rule against which IMSIs are matched.  The matching rule
 | 
			
		||||
is expressed as regular expression.  There can be one such matching rule for
 | 
			
		||||
each
 | 
			
		||||
 | 
			
		||||
* routing between two different SGSNs, see below
 | 
			
		||||
* patching of messages (e.g. APN, PLMN)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== Advanced Features
 | 
			
		||||
 | 
			
		||||
==== PLMN patching
 | 
			
		||||
 | 
			
		||||
This feature permits to modify the PLMN inside any BSSGP messages
 | 
			
		||||
containing the Routing Area ID (RAID).
 | 
			
		||||
 | 
			
		||||
The configured core-mcc and core-mnc will be used towards the SGSN,
 | 
			
		||||
irrespective of which MCC/MNC the PCU is using/reporting on Gb.
 | 
			
		||||
 | 
			
		||||
==== APN patching
 | 
			
		||||
 | 
			
		||||
This will transparently re-write the APN name inside SM ACTIVATE PDP
 | 
			
		||||
REQUEST messages on the way from the MS to the SGSN.  The patching is
 | 
			
		||||
performed based on matching on the IMSI of the subscriber.
 | 
			
		||||
 | 
			
		||||
The configured core-apn will be used towards the SGSN, irrespective
 | 
			
		||||
of which APN the MS is requesting in its Layer3 signaling.
 | 
			
		||||
 | 
			
		||||
APN patching can only be performed if no GPRS encryption is enabled in
 | 
			
		||||
the network!
 | 
			
		||||
 | 
			
		||||
APN patching is useful in case a valid APN cannot reliably be
 | 
			
		||||
provisioned via other means, such as via the SIM Card, OTA-DM or via
 | 
			
		||||
CAMEL rewriting in the SGSN.
 | 
			
		||||
 | 
			
		||||
==== P-TMSI patching
 | 
			
		||||
 | 
			
		||||
This feature transparently rewrite the P-TMSI between MS and SGSN.  This
 | 
			
		||||
is required when using the Secondary SGSN support, as both SGSNs could
 | 
			
		||||
allocate overlapping TMSIs and we must make sure they're unique across
 | 
			
		||||
both SGSNs.
 | 
			
		||||
 | 
			
		||||
P-TMSI patching is required by (and hence automatically enablede if
 | 
			
		||||
secondary SGSN support is enabled.
 | 
			
		||||
 | 
			
		||||
P-TMSI patching can only be performed if no GPRS encryption is enabled in
 | 
			
		||||
the network!
 | 
			
		||||
 | 
			
		||||
==== IMSI Acquisition
 | 
			
		||||
 | 
			
		||||
This is a special feature where the proxy will by itself inject GMM IDENTITY
 | 
			
		||||
REQUEST messages for the IMSI into the downlink BSSGP traffic in order
 | 
			
		||||
to establish the IMSI of subscribers for which it is not otherwise known
 | 
			
		||||
 | 
			
		||||
IMSI acquisition is automatically enabled if secondary SGSN support is
 | 
			
		||||
enabled.
 | 
			
		||||
 | 
			
		||||
==== Secondary SGSN Support
 | 
			
		||||
 | 
			
		||||
This allows the proxy to connect not only to one SGSN, but to two
 | 
			
		||||
different SGSNs.  IMSI matching rules are applied to determine which of
 | 
			
		||||
the SGSNs is to be used for traffic of this subscriber.
 | 
			
		||||
 | 
			
		||||
One possible use case of this feature is to have a "local break-out" for
 | 
			
		||||
subscribers who are native to this network (and hence save
 | 
			
		||||
latencies/overhead of back-hauling all related traffic via the
 | 
			
		||||
SGSN+GGSN) while at the same time maintaining the classic behavior for
 | 
			
		||||
inbound roaming subscribers, where the roaming agreements mandate that
 | 
			
		||||
data traffic is brought back to the GGSN in the HPLMN via the SGSN of
 | 
			
		||||
the VPLMN.
 | 
			
		||||
							
								
								
									
										39
									
								
								doc/manuals/chapters/gbproxy-running.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								doc/manuals/chapters/gbproxy-running.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
== Running OsmoGbPROXY
 | 
			
		||||
 | 
			
		||||
The OsmoGbPROXY executable (`osmo-gbproxy`) offers the following command-line
 | 
			
		||||
options:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== SYNOPSIS
 | 
			
		||||
 | 
			
		||||
*osmo-gbproxy* [-h|-V] [-d 'DBGMASK'] [-D] [-c 'CONFIGFILE'] [-s] [-e 'LOGLEVEL'] [-T]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
=== OPTIONS
 | 
			
		||||
 | 
			
		||||
*-h, --help*::
 | 
			
		||||
	Print a short help message about the supported options
 | 
			
		||||
*-V, --version*::
 | 
			
		||||
	Print the compile-time version number of the 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,
 | 
			
		||||
	see <<logging>> for further information.
 | 
			
		||||
*-D, --daemonize*::
 | 
			
		||||
	Fork the process as a daemon into background.
 | 
			
		||||
*-c, --config-file 'CONFIGFILE'*::
 | 
			
		||||
	Specify the file and path name of the configuration file to be
 | 
			
		||||
	used. If none is specified, use `osmo_sgsn.cfg` in the current
 | 
			
		||||
	working directory.
 | 
			
		||||
*-s, --disable-color*::
 | 
			
		||||
	Disable colors for logging to stderr. This has mostly been
 | 
			
		||||
	deprecated by VTY based logging configuration, see <<logging>>
 | 
			
		||||
	for more information.
 | 
			
		||||
*-e, --log-level 'LOGLEVEL'*::
 | 
			
		||||
	Set the global log level for logging to stderr. This has mostly
 | 
			
		||||
	been deprecated by VTY based logging configuration, see
 | 
			
		||||
	<<logging>> for more information.
 | 
			
		||||
*-T, --timestamp*::
 | 
			
		||||
        Enable prefixing each log line on stderr with a timestamp.  This
 | 
			
		||||
        has mostly been deprecated by VTY based logging configuration, see
 | 
			
		||||
        <<logging>> for more information.
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								doc/manuals/osmogbproxy-usermanual-docinfo.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								doc/manuals/osmogbproxy-usermanual-docinfo.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
<revhistory>
 | 
			
		||||
  <revision>
 | 
			
		||||
    <revnumber>1</revnumber>
 | 
			
		||||
    <date>March 21, 2019</date>
 | 
			
		||||
    <authorinitials>HW</authorinitials>
 | 
			
		||||
    <revremark>
 | 
			
		||||
      Initial version.
 | 
			
		||||
    </revremark>
 | 
			
		||||
  </revision>
 | 
			
		||||
</revhistory>
 | 
			
		||||
 | 
			
		||||
<authorgroup>
 | 
			
		||||
  <author>
 | 
			
		||||
    <firstname>Harald</firstname>
 | 
			
		||||
    <surname>Welte</surname>
 | 
			
		||||
    <email>hwelte@sysmocom.de</email>
 | 
			
		||||
    <authorinitials>HW</authorinitials>
 | 
			
		||||
    <affiliation>
 | 
			
		||||
      <shortaffil>sysmocom</shortaffil>
 | 
			
		||||
      <orgname>sysmocom - s.f.m.c. GmbH</orgname>
 | 
			
		||||
      <jobtitle>Managing Director</jobtitle>
 | 
			
		||||
    </affiliation>
 | 
			
		||||
  </author>
 | 
			
		||||
</authorgroup>
 | 
			
		||||
 | 
			
		||||
<copyright>
 | 
			
		||||
  <year>2013-2019</year>
 | 
			
		||||
  <holder>sysmocom - s.f.m.c. GmbH</holder>
 | 
			
		||||
</copyright>
 | 
			
		||||
 | 
			
		||||
<legalnotice>
 | 
			
		||||
  <para>
 | 
			
		||||
	Permission is granted to copy, distribute and/or modify this
 | 
			
		||||
	document under the terms of the GNU Free Documentation License,
 | 
			
		||||
	Version 1.3 or any later version published by the Free Software
 | 
			
		||||
	Foundation; with no Invariant Sections, no Front-Cover Texts,
 | 
			
		||||
	and no Back-Cover Texts.  A copy of the license is included in
 | 
			
		||||
	the section entitled "GNU Free Documentation License".
 | 
			
		||||
  </para>
 | 
			
		||||
  <para>
 | 
			
		||||
	The Asciidoc source code of this manual can be found at
 | 
			
		||||
	<ulink url="https://git.osmocom.org/osmo-sgsn/doc/">
 | 
			
		||||
		https://git.osmocom.org/osmo-sgsn/doc/
 | 
			
		||||
	</ulink>
 | 
			
		||||
  </para>
 | 
			
		||||
</legalnotice>
 | 
			
		||||
							
								
								
									
										34
									
								
								doc/manuals/osmogbproxy-usermanual.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								doc/manuals/osmogbproxy-usermanual.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
:gfdl-enabled:
 | 
			
		||||
 | 
			
		||||
OsmoGbPROXY User Manual
 | 
			
		||||
=======================
 | 
			
		||||
Harald Welte <hwelte@sysmocom.de>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/preface.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/gbproxy-overview.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/gbproxy-running.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/gbproxy-control.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/vty.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/logging.adoc[]
 | 
			
		||||
 | 
			
		||||
include::{srcdir}/chapters/gbproxy-configuration.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/gb.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/control_if.adoc[]
 | 
			
		||||
 | 
			
		||||
//include::{srcdir}/chapters/counters.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/port_numbers.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/bibliography.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/glossary.adoc[]
 | 
			
		||||
 | 
			
		||||
include::./common/chapters/gfdl.adoc[]
 | 
			
		||||
							
								
								
									
										38
									
								
								doc/manuals/osmogbproxy-vty-reference.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								doc/manuals/osmogbproxy-vty-reference.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
  ex:ts=2:sw=42sts=2:et
 | 
			
		||||
  -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
-->
 | 
			
		||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML 5.0//EN"
 | 
			
		||||
"http://docbook.org/xml/5.0/dtd/docbook.dtd" [
 | 
			
		||||
<!ENTITY chapter-vty      SYSTEM      "./common/chapters/vty.xml" >
 | 
			
		||||
<!ENTITY sections-vty     SYSTEM      "generated/docbook_osmogbproxy-vty-reference.xml"  >
 | 
			
		||||
]>
 | 
			
		||||
 | 
			
		||||
<book>
 | 
			
		||||
  <info>
 | 
			
		||||
    <revhistory>
 | 
			
		||||
        <revision>
 | 
			
		||||
            <revnumber>v1</revnumber>
 | 
			
		||||
            <date>2nd December 2019</date>
 | 
			
		||||
            <authorinitials>hw</authorinitials>
 | 
			
		||||
            <revremark>Initial</revremark>
 | 
			
		||||
        </revision>
 | 
			
		||||
    </revhistory>
 | 
			
		||||
 | 
			
		||||
    <title>OsmoGbProxy VTY Reference</title>
 | 
			
		||||
 | 
			
		||||
    <copyright>
 | 
			
		||||
      <year>2019</year>
 | 
			
		||||
    </copyright>
 | 
			
		||||
 | 
			
		||||
    <legalnotice>
 | 
			
		||||
      <para>This work is copyright by <orgname>sysmocom - s.f.m.c. GmbH</orgname>. All rights reserved.
 | 
			
		||||
      </para>
 | 
			
		||||
    </legalnotice>
 | 
			
		||||
  </info>
 | 
			
		||||
 | 
			
		||||
  <!-- Main chapters-->
 | 
			
		||||
  &chapter-vty;
 | 
			
		||||
</book>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										77
									
								
								doc/manuals/regen_doc.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										77
									
								
								doc/manuals/regen_doc.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
#!/bin/sh -e
 | 
			
		||||
 | 
			
		||||
require_osmo_interact_vty() {
 | 
			
		||||
	if command -v osmo_interact_vty.py >/dev/null 2>&1; then
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	echo "ERROR: osmo_interact_vty.py not found. Are osmo-python-tests in PATH?"
 | 
			
		||||
	exit 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# $1: "update_vty_reference" or "update_counters"
 | 
			
		||||
# $2: output file
 | 
			
		||||
# $3: port
 | 
			
		||||
# $4-$n: command
 | 
			
		||||
interact_vty() {
 | 
			
		||||
	action="$1"
 | 
			
		||||
	output="$2"
 | 
			
		||||
	port="$3"
 | 
			
		||||
	log="/tmp/$4.log"
 | 
			
		||||
	shift 3
 | 
			
		||||
 | 
			
		||||
	echo "Starting in background: $@"
 | 
			
		||||
	"$@" > "$log" 2>&1 &
 | 
			
		||||
	pid="$!"
 | 
			
		||||
 | 
			
		||||
	sleep 0.5
 | 
			
		||||
	if ! kill -0 "$pid" 2>/dev/null; then
 | 
			
		||||
		echo "ERROR: start failed!"
 | 
			
		||||
		cat "$log"
 | 
			
		||||
		exit 1
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	case "$action" in
 | 
			
		||||
		"update_vty_reference")
 | 
			
		||||
			echo "Updating VTY reference: $output"
 | 
			
		||||
			osmo_interact_vty.py -X -p "$port" -H 127.0.0.1 -O "$output"
 | 
			
		||||
			;;
 | 
			
		||||
		"update_counters")
 | 
			
		||||
			echo "Updating asciidoc counters: $output"
 | 
			
		||||
			osmo_interact_vty.py -c "enable;show asciidoc counters" -p "$port" -H 127.0.0.1 -O "$output"
 | 
			
		||||
			;;
 | 
			
		||||
		*)
 | 
			
		||||
			echo "ERROR: invalid argument: $action"
 | 
			
		||||
			exit 1
 | 
			
		||||
			;;
 | 
			
		||||
	esac
 | 
			
		||||
 | 
			
		||||
	kill "$pid"
 | 
			
		||||
	echo "Done (killed $1)"
 | 
			
		||||
	echo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DIR="$(cd "$(dirname "$0")"; pwd)"
 | 
			
		||||
cd "$DIR"
 | 
			
		||||
 | 
			
		||||
require_osmo_interact_vty
 | 
			
		||||
 | 
			
		||||
interact_vty \
 | 
			
		||||
	"update_vty_reference" \
 | 
			
		||||
	"vty/sgsn_vty_reference.xml" \
 | 
			
		||||
	4245 \
 | 
			
		||||
	osmo-sgsn -c "../examples/osmo-sgsn/osmo-sgsn.cfg"
 | 
			
		||||
 | 
			
		||||
interact_vty \
 | 
			
		||||
	"update_vty_reference" \
 | 
			
		||||
	"vty-osmogbproxy/gbproxy_vty_reference.xml" \
 | 
			
		||||
	4246 \
 | 
			
		||||
	osmo-gbproxy -c "../examples/osmo-gbproxy/osmo-gbproxy.cfg"
 | 
			
		||||
 | 
			
		||||
interact_vty \
 | 
			
		||||
	"update_counters" \
 | 
			
		||||
	"chapters/counters_generated.adoc" \
 | 
			
		||||
	4245 \
 | 
			
		||||
	osmo-sgsn -c "../examples/osmo-sgsn/osmo-sgsn.cfg"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
echo "Done with all"
 | 
			
		||||
							
								
								
									
										5
									
								
								doc/manuals/vty-osmogbproxy/gbproxy_vty_additions.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								doc/manuals/vty-osmogbproxy/gbproxy_vty_additions.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'>
 | 
			
		||||
    <node id='config-gbproxy'>
 | 
			
		||||
	    <description>Configure the Gb proxy</description>
 | 
			
		||||
    </node>
 | 
			
		||||
</vtydoc>
 | 
			
		||||
							
								
								
									
										1627
									
								
								doc/manuals/vty-osmogbproxy/gbproxy_vty_reference.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1627
									
								
								doc/manuals/vty-osmogbproxy/gbproxy_vty_reference.xml
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -187,7 +187,7 @@
 | 
			
		||||
        <param name='MASK' doc='List of logging categories to log, e.g. 'abc:mno:xyz'. Available log categories depend on the specific application, refer to the 'logging level' command. Optionally add individual log levels like 'abc,1:mno,3:xyz,5', where the level numbers are LOGL_DEBUG=1 LOGL_INFO=3 LOGL_NOTICE=5 LOGL_ERROR=7 LOGL_FATAL=8' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='logging level (|mm|pag|meas|ref|gprs|ns|bssgp|llc|sndcp|slhc|ranap|sua|v42bis|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (debug|info|notice|error|fatal)'>
 | 
			
		||||
    <command id='logging level (|mm|pag|meas|ref|gprs|ns|bssgp|llc|sndcp|slhc|ranap|sua|v42bis|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='logging' doc='Configure logging' />
 | 
			
		||||
        <param name='level' doc='Set the log level for a specified category' />
 | 
			
		||||
@@ -222,6 +222,7 @@
 | 
			
		||||
        <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' />
 | 
			
		||||
        <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' />
 | 
			
		||||
        <param name='ljibuf' doc='libosmo-netif Jitter Buffer' />
 | 
			
		||||
        <param name='lrspro' doc='Remote SIM protocol' />
 | 
			
		||||
        <param name='debug' doc='Log debug messages and higher levels' />
 | 
			
		||||
        <param name='info' doc='Log informational messages and higher levels' />
 | 
			
		||||
        <param name='notice' doc='Log noticeable messages and higher levels' />
 | 
			
		||||
@@ -733,7 +734,7 @@
 | 
			
		||||
        <param name='MASK' doc='List of logging categories to log, e.g. 'abc:mno:xyz'. Available log categories depend on the specific application, refer to the 'logging level' command. Optionally add individual log levels like 'abc,1:mno,3:xyz,5', where the level numbers are LOGL_DEBUG=1 LOGL_INFO=3 LOGL_NOTICE=5 LOGL_ERROR=7 LOGL_FATAL=8' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='logging level (|mm|pag|meas|ref|gprs|ns|bssgp|llc|sndcp|slhc|ranap|sua|v42bis|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (debug|info|notice|error|fatal)'>
 | 
			
		||||
    <command id='logging level (|mm|pag|meas|ref|gprs|ns|bssgp|llc|sndcp|slhc|ranap|sua|v42bis|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='logging' doc='Configure logging' />
 | 
			
		||||
        <param name='level' doc='Set the log level for a specified category' />
 | 
			
		||||
@@ -768,6 +769,7 @@
 | 
			
		||||
        <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' />
 | 
			
		||||
        <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' />
 | 
			
		||||
        <param name='ljibuf' doc='libosmo-netif Jitter Buffer' />
 | 
			
		||||
        <param name='lrspro' doc='Remote SIM protocol' />
 | 
			
		||||
        <param name='debug' doc='Log debug messages and higher levels' />
 | 
			
		||||
        <param name='info' doc='Log informational messages and higher levels' />
 | 
			
		||||
        <param name='notice' doc='Log noticeable messages and higher levels' />
 | 
			
		||||
@@ -1488,7 +1490,8 @@
 | 
			
		||||
        <param name='category' doc='Configure log message' />
 | 
			
		||||
        <param name='0' doc='Don't prefix each log message' />
 | 
			
		||||
        <param name='1' doc='Prefix each log message with category/subsystem name' />
 | 
			
		||||
      </params>    </command>
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='logging print category-hex (0|1)'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='logging' doc='Configure logging' />
 | 
			
		||||
@@ -1518,7 +1521,7 @@
 | 
			
		||||
        <param name='[last]' doc='Log source file info at the end of a log line. If omitted, log source file info just before the log text.' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='logging level (|mm|pag|meas|ref|gprs|ns|bssgp|llc|sndcp|slhc|ranap|sua|v42bis|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (debug|info|notice|error|fatal)'>
 | 
			
		||||
    <command id='logging level (|mm|pag|meas|ref|gprs|ns|bssgp|llc|sndcp|slhc|ranap|sua|v42bis|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='logging' doc='Configure logging' />
 | 
			
		||||
        <param name='level' doc='Set the log level for a specified category' />
 | 
			
		||||
@@ -1553,6 +1556,7 @@
 | 
			
		||||
        <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' />
 | 
			
		||||
        <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' />
 | 
			
		||||
        <param name='ljibuf' doc='libosmo-netif Jitter Buffer' />
 | 
			
		||||
        <param name='lrspro' doc='Remote SIM protocol' />
 | 
			
		||||
        <param name='debug' doc='Log debug messages and higher levels' />
 | 
			
		||||
        <param name='info' doc='Log informational messages and higher levels' />
 | 
			
		||||
        <param name='notice' doc='Log noticeable messages and higher levels' />
 | 
			
		||||
@@ -1696,10 +1700,11 @@
 | 
			
		||||
        <param name='login' doc='Enable password checking' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='bind A.B.C.D'>
 | 
			
		||||
    <command id='bind A.B.C.D [<0-65535>]'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='bind' doc='Accept VTY telnet connections on local interface' />
 | 
			
		||||
        <param name='A.B.C.D' doc='Local interface IP address (default: 127.0.0.1)' />
 | 
			
		||||
        <param name='[<0-65535>]' doc='Local TCP port number' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
  </node>
 | 
			
		||||
@@ -1762,7 +1767,7 @@
 | 
			
		||||
        <param name='<0-65535>' doc='NS Entity ID (NSEI)' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='timer (tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries) <0-65535>'>
 | 
			
		||||
    <command id='timer (tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries|tsns-prov) <0-65535>'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='timer' doc='Network Service Timer' />
 | 
			
		||||
        <param name='tns-block' doc='(un)blocking Timer (Tns-block) timeout' />
 | 
			
		||||
@@ -1772,6 +1777,7 @@
 | 
			
		||||
        <param name='tns-test' doc='Test Timer (Tns-test) timeout' />
 | 
			
		||||
        <param name='tns-alive' doc='Alive Timer (Tns-alive) timeout' />
 | 
			
		||||
        <param name='tns-alive-retries' doc='Alive Timer (Tns-alive) number of retries' />
 | 
			
		||||
        <param name='tsns-prov' doc='SNS Provision Timer (Tsns-prov) timeout' />
 | 
			
		||||
        <param name='<0-65535>' doc='Timer Value' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
@@ -2224,6 +2230,13 @@
 | 
			
		||||
        <param name='remote' doc='Use remote subscription data only (HLR)' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='authentication (optional|required)'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='authentication' doc='Whether to enforce MS authentication in GERAN (only with auth-policy remote)' />
 | 
			
		||||
        <param name='optional' doc='Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)' />
 | 
			
		||||
        <param name='required' doc='Always require authentication (only available for auth-policy remote, default with that auth-policy)' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='encryption (GEA0|GEA1|GEA2|GEA3|GEA4)'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='encryption' doc='Set encryption algorithm for SGSN' />
 | 
			
		||||
@@ -2234,6 +2247,13 @@
 | 
			
		||||
        <param name='GEA4' doc='Use GEA4' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='gsup ipa-name NAME'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='gsup' doc='GSUP Parameters' />
 | 
			
		||||
        <param name='ipa-name' doc='Set the IPA name of this SGSN' />
 | 
			
		||||
        <param name='NAME' doc='A unique name for this SGSN. For example: PLMN + redundancy server number: SGSN-901-70-0. This name is used for GSUP routing and must be set if more than one SGSN is connected to the network. The default is 'SGSN-00-00-00-00-00-00'.' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='gsup remote-ip A.B.C.D'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='gsup' doc='GSUP Parameters' />
 | 
			
		||||
@@ -2325,7 +2345,8 @@
 | 
			
		||||
        <param name='no' doc='Negate a command or set its defaults' />
 | 
			
		||||
        <param name='cdr' doc='CDR' />
 | 
			
		||||
        <param name='trap' doc='Disable sending CDR via TRAP CTRL messages' />
 | 
			
		||||
      </params>    </command>
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='cdr interval <1-2147483647>'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='cdr' doc='CDR' />
 | 
			
		||||
@@ -2439,7 +2460,7 @@
 | 
			
		||||
    <command id='compression rfc1144 active slots <1-256>'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='compression' doc='Configure compression' />
 | 
			
		||||
        <param name='rfc1144' doc='RFC1144 Header compresion scheme' />
 | 
			
		||||
        <param name='rfc1144' doc='RFC1144 Header compression scheme' />
 | 
			
		||||
        <param name='active' doc='Compression is actively proposed' />
 | 
			
		||||
        <param name='slots' doc='Number of compression state slots' />
 | 
			
		||||
        <param name='<1-256>' doc='Number of compression state slots' />
 | 
			
		||||
@@ -2448,7 +2469,7 @@
 | 
			
		||||
    <command id='compression rfc1144 passive'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='compression' doc='Configure compression' />
 | 
			
		||||
        <param name='rfc1144' doc='RFC1144 Header compresion scheme' />
 | 
			
		||||
        <param name='rfc1144' doc='RFC1144 Header compression scheme' />
 | 
			
		||||
        <param name='passive' doc='Compression is available on request' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
@@ -2462,7 +2483,7 @@
 | 
			
		||||
    <command id='compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='compression' doc='Configure compression' />
 | 
			
		||||
        <param name='v42bis' doc='V.42bis data compresion scheme' />
 | 
			
		||||
        <param name='v42bis' doc='V.42bis data compression scheme' />
 | 
			
		||||
        <param name='active' doc='Compression is actively proposed' />
 | 
			
		||||
        <param name='direction' doc='Direction in which the compression shall be active (p0)' />
 | 
			
		||||
        <param name='ms' doc='Compress ms->sgsn direction only' />
 | 
			
		||||
@@ -2477,10 +2498,16 @@
 | 
			
		||||
    <command id='compression v42bis passive'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='compression' doc='Configure compression' />
 | 
			
		||||
        <param name='v42bis' doc='V.42bis data compresion scheme' />
 | 
			
		||||
        <param name='v42bis' doc='V.42bis data compression scheme' />
 | 
			
		||||
        <param name='passive' doc='Compression is available on request' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='cs7-instance-iu <0-15>'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='cs7-instance-iu' doc='Set SS7 to be used by the Iu-Interface.' />
 | 
			
		||||
        <param name='<0-15>' doc='SS7 instance reference number (default: 0)' />
 | 
			
		||||
      </params>
 | 
			
		||||
    </command>
 | 
			
		||||
    <command id='iu rab-assign-addr-enc (x213|v4raw)'>
 | 
			
		||||
      <params>
 | 
			
		||||
        <param name='iu' doc='Iu interface protocol options' />
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,18 @@ noinst_HEADERS = \
 | 
			
		||||
	crc24.h \
 | 
			
		||||
	debug.h \
 | 
			
		||||
	gb_proxy.h \
 | 
			
		||||
	gprs_gb.h \
 | 
			
		||||
	gprs_gb_parse.h \
 | 
			
		||||
	gprs_gmm.h \
 | 
			
		||||
	gprs_gmm_fsm.h \
 | 
			
		||||
	gprs_gmm_attach.h \
 | 
			
		||||
	gprs_mm_state_gb_fsm.h \
 | 
			
		||||
	gprs_mm_state_iu_fsm.h \
 | 
			
		||||
	gprs_llc.h \
 | 
			
		||||
	gprs_llc_xid.h \
 | 
			
		||||
	gprs_ranap.h \
 | 
			
		||||
	gprs_sgsn.h \
 | 
			
		||||
	gprs_sm.h \
 | 
			
		||||
	gprs_sndcp_comp.h \
 | 
			
		||||
	gprs_sndcp_dcomp.h \
 | 
			
		||||
	gprs_sndcp.h \
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@ enum {
 | 
			
		||||
	DVLR,
 | 
			
		||||
	DIUCS,
 | 
			
		||||
	DSIGTRAN,
 | 
			
		||||
	DGTP,
 | 
			
		||||
	Debug_LastEntry,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <regex.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#define GBPROXY_INIT_VU_GEN_TX 256
 | 
			
		||||
 | 
			
		||||
@@ -70,29 +71,30 @@ enum gbproxy_peer_ctr {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum gbproxy_keep_mode {
 | 
			
		||||
	GBPROX_KEEP_NEVER,
 | 
			
		||||
	GBPROX_KEEP_REATTACH,
 | 
			
		||||
	GBPROX_KEEP_IDENTIFIED,
 | 
			
		||||
	GBPROX_KEEP_ALWAYS,
 | 
			
		||||
	GBPROX_KEEP_NEVER,	/* don't ever keep TLLI/IMSI state of de-registered subscribers */
 | 
			
		||||
	GBPROX_KEEP_REATTACH,	/* keep if re-attach has been requested by SGSN */
 | 
			
		||||
	GBPROX_KEEP_IDENTIFIED,	/* keep if we had resolved an IMSI */
 | 
			
		||||
	GBPROX_KEEP_ALWAYS,	/* always keep */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum gbproxy_match_id {
 | 
			
		||||
	GBPROX_MATCH_PATCHING,
 | 
			
		||||
	GBPROX_MATCH_ROUTING,
 | 
			
		||||
	GBPROX_MATCH_PATCHING,	/* match rule on whether or not we should patch */
 | 
			
		||||
	GBPROX_MATCH_ROUTING,	/* match rule on whether or not we should route (2-SGSN) */
 | 
			
		||||
	GBPROX_MATCH_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct gbproxy_match {
 | 
			
		||||
	int   enable;
 | 
			
		||||
	char *re_str;
 | 
			
		||||
	regex_t re_comp;
 | 
			
		||||
	bool  enable;		/* is this match enabled? */
 | 
			
		||||
	char *re_str;		/* regular expression (for IMSI) in string format */
 | 
			
		||||
	regex_t re_comp;	/* compiled regular expression (for IMSI) */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* global gb-proxy configuration */
 | 
			
		||||
struct gbproxy_config {
 | 
			
		||||
	/* parsed from config file */
 | 
			
		||||
	uint16_t nsip_sgsn_nsei;
 | 
			
		||||
 | 
			
		||||
	/* misc */
 | 
			
		||||
	/* NS instance of libosmogb */
 | 
			
		||||
	struct gprs_ns_inst *nsi;
 | 
			
		||||
 | 
			
		||||
	/* Linked list of all Gb peers (except SGSN) */
 | 
			
		||||
@@ -101,10 +103,13 @@ struct gbproxy_config {
 | 
			
		||||
	/* Counter */
 | 
			
		||||
	struct rate_ctr_group *ctrg;
 | 
			
		||||
 | 
			
		||||
	/* force mcc/mnc */
 | 
			
		||||
	/* MCC/MNC to be patched into RA-ID on the way from BSS to SGSN? */
 | 
			
		||||
	struct osmo_plmn_id core_plmn;
 | 
			
		||||
 | 
			
		||||
	/* APN to be patched into PDP CTX ACT REQ on the way from BSS to SGSN */
 | 
			
		||||
	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 */
 | 
			
		||||
@@ -114,14 +119,18 @@ struct gbproxy_config {
 | 
			
		||||
	/* 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;
 | 
			
		||||
	/* Should the P-TMSI be patched on the fly (required for 2-SGSN config) */
 | 
			
		||||
	bool patch_ptmsi;
 | 
			
		||||
	/* Should the IMSI be acquired by the proxy (required for 2-SGSN config) */
 | 
			
		||||
	bool acquire_imsi;
 | 
			
		||||
	/* Should we route subscribers to two different SGSNs? */
 | 
			
		||||
	bool route_to_sgsn2;
 | 
			
		||||
	/* NSEI of the second SGSN */
 | 
			
		||||
	uint16_t nsip_sgsn2_nsei;
 | 
			
		||||
	/* should we keep a cache of per-subscriber state even after de-registration? */
 | 
			
		||||
	enum gbproxy_keep_mode keep_link_infos;
 | 
			
		||||
 | 
			
		||||
	/* IMSI checking/matching */
 | 
			
		||||
	/* IMSI checking/matching for 2-SGSN routing and patching */
 | 
			
		||||
	struct gbproxy_match matches[GBPROX_MATCH_LAST];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -133,7 +142,9 @@ struct gbproxy_patch_state {
 | 
			
		||||
	int logical_link_count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* one peer at NS level that we interact with (BSS/PCU) */
 | 
			
		||||
struct gbproxy_peer {
 | 
			
		||||
	/* linked to gbproxy_config.bts_peers */
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
 | 
			
		||||
	/* point back to the config */
 | 
			
		||||
@@ -144,7 +155,7 @@ struct gbproxy_peer {
 | 
			
		||||
 | 
			
		||||
	/* BVCI used for Point-to-Point to this peer */
 | 
			
		||||
	uint16_t bvci;
 | 
			
		||||
	int blocked;
 | 
			
		||||
	bool blocked;
 | 
			
		||||
 | 
			
		||||
	/* Routeing Area that this peer is part of (raw 04.08 encoding) */
 | 
			
		||||
	uint8_t ra[6];
 | 
			
		||||
@@ -152,6 +163,7 @@ struct gbproxy_peer {
 | 
			
		||||
	/* Counter */
 | 
			
		||||
	struct rate_ctr_group *ctrg;
 | 
			
		||||
 | 
			
		||||
	/* State related to on-the-fly patching of certain messages */
 | 
			
		||||
	struct gbproxy_patch_state patch_state;
 | 
			
		||||
 | 
			
		||||
	/* Fired periodically to clean up stale links from list */
 | 
			
		||||
@@ -159,33 +171,55 @@ struct gbproxy_peer {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct gbproxy_tlli_state {
 | 
			
		||||
	/* currently active TLLI */
 | 
			
		||||
	uint32_t current;
 | 
			
		||||
	/* newly-assigned TLLI (e.g. during P-TMSI allocation procedure) */
 | 
			
		||||
	uint32_t assigned;
 | 
			
		||||
	int bss_validated;
 | 
			
		||||
	int net_validated;
 | 
			
		||||
	/* has the BSS side validated (confirmed) the new TLLI? */
 | 
			
		||||
	bool bss_validated;
 | 
			
		||||
	/* has the SGSN side validated (confirmed) the new TLLI? */
 | 
			
		||||
	bool net_validated;
 | 
			
		||||
	/* NOTE: once both are validated, we set current = assigned and assigned = 0 */
 | 
			
		||||
 | 
			
		||||
	/* The P-TMSI for this subscriber */
 | 
			
		||||
	uint32_t ptmsi;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* One TLLI (= UE, = Subscriber) served via this proxy */
 | 
			
		||||
struct gbproxy_link_info {
 | 
			
		||||
	/* link to gbproxy_peer.patch_state.logical_links */
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
 | 
			
		||||
	/* TLLI on the BSS/PCU side */
 | 
			
		||||
	struct gbproxy_tlli_state tlli;
 | 
			
		||||
	/* TLLI on the SGSN side (can be different in case of P-TMSI patching) */
 | 
			
		||||
	struct gbproxy_tlli_state sgsn_tlli;
 | 
			
		||||
	/* NSEI of the SGSN serving this link */
 | 
			
		||||
	uint32_t sgsn_nsei;
 | 
			
		||||
 | 
			
		||||
	/* timestamp when we last had any contact with this UE */
 | 
			
		||||
	time_t timestamp;
 | 
			
		||||
 | 
			
		||||
	/* IMSI of the subscriber (if/once known) */
 | 
			
		||||
	uint8_t *imsi;
 | 
			
		||||
	size_t imsi_len;
 | 
			
		||||
 | 
			
		||||
	int imsi_acq_pending;
 | 
			
		||||
	/* is the IMSI acquisition still pending? */
 | 
			
		||||
	bool imsi_acq_pending;
 | 
			
		||||
 | 
			
		||||
	/* queue of stored UL messages (until IMSI acquisition completes and we can
 | 
			
		||||
	 * determine which of the SGSNs we should route this to */
 | 
			
		||||
	struct llist_head stored_msgs;
 | 
			
		||||
	uint32_t stored_msgs_len;
 | 
			
		||||
 | 
			
		||||
	/* generated N(U) we use (required due to IMSI acquisition */
 | 
			
		||||
	unsigned vu_gen_tx_bss;
 | 
			
		||||
 | 
			
		||||
	int is_deregistered;
 | 
			
		||||
	/* is this subscriber deregistered (TLLI invalidated)? */
 | 
			
		||||
	bool is_deregistered;
 | 
			
		||||
 | 
			
		||||
	int is_matching[GBPROX_MATCH_LAST];
 | 
			
		||||
	/* does this link match either the (2-SGSN) routing or the patching rule? */
 | 
			
		||||
	bool is_matching[GBPROX_MATCH_LAST];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								include/osmocom/sgsn/gprs_gb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								include/osmocom/sgsn/gprs_gb.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_llc.h>
 | 
			
		||||
 | 
			
		||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
 | 
			
		||||
			   bool drop_cipherable);
 | 
			
		||||
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
 | 
			
		||||
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx);
 | 
			
		||||
 | 
			
		||||
/* page a MS in its routing area */
 | 
			
		||||
int gprs_gb_page_ps_ra(struct sgsn_mm_ctx *mmctx);
 | 
			
		||||
@@ -6,19 +6,16 @@
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
@@ -33,8 +30,6 @@ int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
 | 
			
		||||
 | 
			
		||||
time_t gprs_max_time_to_idle(void);
 | 
			
		||||
 | 
			
		||||
int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp);
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
@@ -42,9 +37,11 @@ int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm);
 | 
			
		||||
 | 
			
		||||
int gprs_gmm_attach_req_ies(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 */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								include/osmocom/sgsn/gprs_gmm_fsm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								include/osmocom/sgsn/gprs_gmm_fsm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/fsm.h>
 | 
			
		||||
 | 
			
		||||
/* 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,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
@@ -96,6 +96,7 @@ 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 +111,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 +146,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 +178,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 +193,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 */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								include/osmocom/sgsn/gprs_mm_state_gb_fsm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								include/osmocom/sgsn/gprs_mm_state_gb_fsm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
#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_GPRS_DETACH, TODO: not used */
 | 
			
		||||
	E_MM_PDU_RECEPTION,
 | 
			
		||||
	E_MM_IMPLICIT_DETACH, /* = E_MM_CANCEL_LOCATION */
 | 
			
		||||
	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;
 | 
			
		||||
							
								
								
									
										25
									
								
								include/osmocom/sgsn/gprs_mm_state_iu_fsm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								include/osmocom/sgsn/gprs_mm_state_iu_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_iu_fsm_states {
 | 
			
		||||
	ST_PMM_DETACHED,
 | 
			
		||||
	ST_PMM_CONNECTED,
 | 
			
		||||
	ST_PMM_IDLE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum mm_state_iu_fsm_events {
 | 
			
		||||
	E_PMM_PS_ATTACH,
 | 
			
		||||
	/* E_PS_DETACH, TODO: not used */
 | 
			
		||||
	E_PMM_PS_CONN_RELEASE,
 | 
			
		||||
	E_PMM_PS_CONN_ESTABLISH,
 | 
			
		||||
	E_PMM_IMPLICIT_DETACH, /* = E_PS_ATTACH_REJECT, E_RAU_REJECT */
 | 
			
		||||
	E_PMM_RA_UPDATE, /* = Serving RNC relocation */
 | 
			
		||||
	E_PMM_USER_INACTIVITY, /* when the inactivity timer runs out */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern struct osmo_fsm mm_state_iu_fsm;
 | 
			
		||||
							
								
								
									
										34
									
								
								include/osmocom/sgsn/gprs_ranap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								include/osmocom/sgsn/gprs_ranap.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sgsn.h>
 | 
			
		||||
 | 
			
		||||
#ifdef BUILD_IU
 | 
			
		||||
#include <osmocom/ranap/ranap_ies_defs.h>
 | 
			
		||||
#include <osmocom/ranap/ranap_msg_factory.h>
 | 
			
		||||
#include <osmocom/ranap/iu_client.h>
 | 
			
		||||
 | 
			
		||||
void activate_pdp_rabs(struct sgsn_mm_ctx *ctx);
 | 
			
		||||
int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data);
 | 
			
		||||
int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp);
 | 
			
		||||
 | 
			
		||||
/* free the Iu UE context */
 | 
			
		||||
void sgsn_ranap_iu_free(struct sgsn_mm_ctx *ctx);
 | 
			
		||||
 | 
			
		||||
/* send a Iu Release Command and free afterwards the UE context */
 | 
			
		||||
void sgsn_ranap_iu_release_free(struct sgsn_mm_ctx *ctx,
 | 
			
		||||
				const struct RANAP_Cause *cause);
 | 
			
		||||
 | 
			
		||||
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id, uint16_t *sai);
 | 
			
		||||
 | 
			
		||||
#else /* ifndef BUILD_IU */
 | 
			
		||||
inline static void sgsn_ranap_iu_free(void *ctx) {};
 | 
			
		||||
inline static void sgsn_ranap_iu_release_free(void *ctx, void *cause) {};
 | 
			
		||||
#endif /* 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)
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/fsm.h>
 | 
			
		||||
#include <osmocom/core/timer.h>
 | 
			
		||||
@@ -22,25 +23,6 @@ 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,
 | 
			
		||||
@@ -108,9 +90,12 @@ enum sgsn_ran_type {
 | 
			
		||||
	MM_CTX_T_GERAN_Gb,
 | 
			
		||||
	/* UMTS via Iu */
 | 
			
		||||
	MM_CTX_T_UTRAN_Iu,
 | 
			
		||||
	/* GPRS/EDGE via 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;
 | 
			
		||||
@@ -134,8 +119,7 @@ struct sgsn_mm_ctx {
 | 
			
		||||
	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 */
 | 
			
		||||
	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;
 | 
			
		||||
@@ -154,6 +138,9 @@ struct sgsn_mm_ctx {
 | 
			
		||||
		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;
 | 
			
		||||
@@ -168,6 +155,8 @@ struct sgsn_mm_ctx {
 | 
			
		||||
		/* 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;
 | 
			
		||||
@@ -260,6 +249,28 @@ static inline bool sgsn_mm_ctx_is_authenticated(struct sgsn_mm_ctx *ctx)
 | 
			
		||||
	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->conn_id, 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 gprs_ra_id *raid);
 | 
			
		||||
@@ -364,7 +375,7 @@ struct sgsn_ggsn_ctx {
 | 
			
		||||
	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;
 | 
			
		||||
	unsigned int echo_interval;
 | 
			
		||||
};
 | 
			
		||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
 | 
			
		||||
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
 | 
			
		||||
@@ -373,10 +384,16 @@ struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
 | 
			
		||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
 | 
			
		||||
void sgsn_ggsn_ctx_drop_pdp(struct sgsn_pdp_ctx *pctx);
 | 
			
		||||
int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *except);
 | 
			
		||||
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn);
 | 
			
		||||
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
 | 
			
		||||
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp);
 | 
			
		||||
void sgsn_ggsn_ctx_check_echo_timer(struct sgsn_ggsn_ctx *ggc);
 | 
			
		||||
 | 
			
		||||
#define LOGGGSN(ggc, level, fmt, args...) { \
 | 
			
		||||
	char _buf[INET_ADDRSTRLEN]; \
 | 
			
		||||
	LOGP(DGTP, level, "GGSN(%" PRIu32 ":%s): " fmt, (ggc)->id, inet_ntop(AF_INET, &(ggc)->remote_addr, _buf, sizeof(_buf)), ## args); \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
struct apn_ctx {
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
	struct sgsn_ggsn_ctx *ggsn;
 | 
			
		||||
@@ -411,7 +428,7 @@ int sgsn_ctrl_cmds_install(void);
 | 
			
		||||
 */
 | 
			
		||||
struct imsi_acl_entry {
 | 
			
		||||
	struct llist_head list;
 | 
			
		||||
	char imsi[16+1];
 | 
			
		||||
	char imsi[OSMO_IMSI_BUF_SIZE];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								include/osmocom/sgsn/gprs_sm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								include/osmocom/sgsn/gprs_sm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sgsn.h>
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
@@ -78,26 +78,16 @@ struct sgsn_config {
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	int dynamic_lookup;
 | 
			
		||||
 | 
			
		||||
@@ -122,6 +112,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 +130,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 */
 | 
			
		||||
@@ -170,7 +159,7 @@ char *sgsn_gtp_ntoa(struct ul16_t *ul);
 | 
			
		||||
/* Main input function for Gb proxy */
 | 
			
		||||
int sgsn_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* sgsn_libgtp.c */
 | 
			
		||||
struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
 | 
			
		||||
					 struct sgsn_mm_ctx *mmctx,
 | 
			
		||||
					 uint16_t nsapi,
 | 
			
		||||
@@ -178,6 +167,7 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
 | 
			
		||||
int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
 | 
			
		||||
void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen);
 | 
			
		||||
void sgsn_ggsn_echo_req(struct sgsn_ggsn_ctx *ggc);
 | 
			
		||||
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx);
 | 
			
		||||
 | 
			
		||||
/* gprs_sndcp.c */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -23,12 +23,12 @@ app_configs = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
apps = [(4246, "src/gprs/osmo-gbproxy", "OsmoGbProxy", "gbproxy"),
 | 
			
		||||
        (4245, "src/gprs/osmo-sgsn", "OsmoSGSN", "sgsn"),
 | 
			
		||||
        (4253, "src/gprs/osmo-gtphub", "OsmoGTPhub", "gtphub")
 | 
			
		||||
apps = [(4246, "src/gbproxy/osmo-gbproxy", "OsmoGbProxy", "gbproxy"),
 | 
			
		||||
        (4245, "src/sgsn/osmo-sgsn", "OsmoSGSN", "sgsn"),
 | 
			
		||||
        (4253, "src/gtphub/osmo-gtphub", "OsmoGTPhub", "gtphub")
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
vty_command = ["./src/gprs/osmo-sgsn", "-c",
 | 
			
		||||
vty_command = ["./src/sgsn/osmo-sgsn", "-c",
 | 
			
		||||
               "doc/examples/osmo-sgsn/osmo-sgsn.cfg"]
 | 
			
		||||
 | 
			
		||||
vty_app = apps[1]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,6 @@
 | 
			
		||||
SUBDIRS = \
 | 
			
		||||
	gprs \
 | 
			
		||||
	sgsn \
 | 
			
		||||
	gbproxy \
 | 
			
		||||
	gtphub \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								src/gbproxy/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/gbproxy/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
AM_CPPFLAGS = \
 | 
			
		||||
	$(all_includes) \
 | 
			
		||||
	-I$(top_srcdir)/include \
 | 
			
		||||
	-I$(top_builddir) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
AM_CFLAGS = \
 | 
			
		||||
	-Wall \
 | 
			
		||||
	-fno-strict-aliasing \
 | 
			
		||||
	$(LIBOSMOCORE_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOGSM_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOVTY_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOCTRL_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOABIS_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOGB_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOGSUPCLIENT_CFLAGS) \
 | 
			
		||||
	$(COVERAGE_CFLAGS) \
 | 
			
		||||
	$(LIBGTP_CFLAGS) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
bin_PROGRAMS = \
 | 
			
		||||
	osmo-gbproxy \
 | 
			
		||||
	$(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 \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
osmo_gbproxy_LDADD = \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_gb_parse.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_llc_parse.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/crc24.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_utils.o \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS) \
 | 
			
		||||
	$(LIBOSMOGSM_LIBS) \
 | 
			
		||||
	$(LIBOSMOVTY_LIBS) \
 | 
			
		||||
	$(LIBOSMOCTRL_LIBS) \
 | 
			
		||||
	$(LIBOSMOGB_LIBS) \
 | 
			
		||||
	$(LIBGTP_LIBS) \
 | 
			
		||||
	-lrt \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
@@ -243,7 +243,7 @@ uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer,
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			bss_ptmsi = bss_ptmsi | 0xC0000000;
 | 
			
		||||
			bss_ptmsi = bss_ptmsi | GSM23003_TMSI_SGSN_MASK;
 | 
			
		||||
 | 
			
		||||
			if (gbproxy_link_info_by_ptmsi(peer, bss_ptmsi))
 | 
			
		||||
				bss_ptmsi = GSM_RESERVED_TMSI;
 | 
			
		||||
@@ -310,7 +310,7 @@ static int gbproxy_restart_imsi_acquisition(struct gbproxy_link_info* link_info)
 | 
			
		||||
		in_progress = 1;
 | 
			
		||||
 | 
			
		||||
	gbproxy_link_info_discard_messages(link_info);
 | 
			
		||||
	link_info->imsi_acq_pending = 0;
 | 
			
		||||
	link_info->imsi_acq_pending = false;
 | 
			
		||||
 | 
			
		||||
	return in_progress;
 | 
			
		||||
}
 | 
			
		||||
@@ -531,7 +531,7 @@ static int gbproxy_imsi_acquisition(struct gbproxy_peer *peer,
 | 
			
		||||
		 * implementation relies on the MS doing proper retransmissions
 | 
			
		||||
		 * of the triggering message instead */
 | 
			
		||||
 | 
			
		||||
		link_info->imsi_acq_pending = 1;
 | 
			
		||||
		link_info->imsi_acq_pending = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -836,11 +836,11 @@ static int block_unblock_peer(struct gbproxy_config *cfg, uint16_t ptp_bvci, uin
 | 
			
		||||
 | 
			
		||||
	switch (pdu_type) {
 | 
			
		||||
	case BSSGP_PDUT_BVC_BLOCK_ACK:
 | 
			
		||||
		peer->blocked = 1;
 | 
			
		||||
		peer->blocked = true;
 | 
			
		||||
		rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_BLOCKED]);
 | 
			
		||||
		break;
 | 
			
		||||
	case BSSGP_PDUT_BVC_UNBLOCK_ACK:
 | 
			
		||||
		peer->blocked = 0;
 | 
			
		||||
		peer->blocked = false;
 | 
			
		||||
		rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_UNBLOCKED]);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
@@ -140,7 +140,7 @@ static void print_help()
 | 
			
		||||
	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("  -V --version. Print the version.\n");
 | 
			
		||||
	printf("  -e --log-level number. Set a global loglevel.\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -196,6 +196,11 @@ static void handle_options(int argc, char **argv)
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (argc > optind) {
 | 
			
		||||
		fprintf(stderr, "Unsupported positional arguments on command line\n");
 | 
			
		||||
		exit(2);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int gbproxy_vty_is_config_node(struct vty *vty, int node)
 | 
			
		||||
@@ -284,9 +289,9 @@ int main(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
	vty_info.copyright = openbsc_copyright;
 | 
			
		||||
	vty_init(&vty_info);
 | 
			
		||||
	logging_vty_add_cmds(NULL);
 | 
			
		||||
	logging_vty_add_cmds();
 | 
			
		||||
	osmo_talloc_vty_add_cmds();
 | 
			
		||||
	osmo_stats_vty_add_cmds(&gprs_log_info);
 | 
			
		||||
	osmo_stats_vty_add_cmds();
 | 
			
		||||
	gbproxy_vty_init();
 | 
			
		||||
 | 
			
		||||
	handle_options(argc, argv);
 | 
			
		||||
@@ -398,7 +398,7 @@ void gbproxy_clear_patch_filter(struct gbproxy_match *match)
 | 
			
		||||
{
 | 
			
		||||
	if (match->enable) {
 | 
			
		||||
		regfree(&match->re_comp);
 | 
			
		||||
		match->enable = 0;
 | 
			
		||||
		match->enable = false;
 | 
			
		||||
	}
 | 
			
		||||
	talloc_free(match->re_str);
 | 
			
		||||
	match->re_str = NULL;
 | 
			
		||||
@@ -419,7 +419,7 @@ int gbproxy_set_patch_filter(struct gbproxy_match *match, const char *filter,
 | 
			
		||||
		     REG_EXTENDED | REG_NOSUB | REG_ICASE);
 | 
			
		||||
 | 
			
		||||
	if (rc == 0) {
 | 
			
		||||
		match->enable = 1;
 | 
			
		||||
		match->enable = true;
 | 
			
		||||
		match->re_str = talloc_strdup(tall_sgsn_ctx, filter);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
@@ -284,8 +284,8 @@ void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
 | 
			
		||||
 | 
			
		||||
	/* Remember assigned TLLI */
 | 
			
		||||
	tlli_state->assigned = new_tlli;
 | 
			
		||||
	tlli_state->bss_validated = 0;
 | 
			
		||||
	tlli_state->net_validated = 0;
 | 
			
		||||
	tlli_state->bss_validated = false;
 | 
			
		||||
	tlli_state->net_validated = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t gbproxy_map_tlli(uint32_t other_tlli,
 | 
			
		||||
@@ -325,9 +325,9 @@ static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
 | 
			
		||||
 | 
			
		||||
	/* See GSM 04.08, 4.7.1.5 */
 | 
			
		||||
	if (to_bss)
 | 
			
		||||
		tlli_state->net_validated = 1;
 | 
			
		||||
		tlli_state->net_validated = true;
 | 
			
		||||
	else
 | 
			
		||||
		tlli_state->bss_validated = 1;
 | 
			
		||||
		tlli_state->bss_validated = true;
 | 
			
		||||
 | 
			
		||||
	if (!tlli_state->bss_validated || !tlli_state->net_validated)
 | 
			
		||||
		return;
 | 
			
		||||
@@ -367,7 +367,7 @@ static int gbproxy_unregister_link_info(struct gbproxy_peer *peer,
 | 
			
		||||
	link_info->sgsn_tlli.current = 0;
 | 
			
		||||
	link_info->sgsn_tlli.assigned = 0;
 | 
			
		||||
 | 
			
		||||
	link_info->is_deregistered = 1;
 | 
			
		||||
	link_info->is_deregistered = true;
 | 
			
		||||
 | 
			
		||||
	gbproxy_reset_link(link_info);
 | 
			
		||||
 | 
			
		||||
@@ -424,7 +424,7 @@ static void gbproxy_assign_imsi(struct gbproxy_peer *peer,
 | 
			
		||||
			&peer->cfg->matches[match_id],
 | 
			
		||||
			parse_ctx->imsi, parse_ctx->imsi_len);
 | 
			
		||||
		if (imsi_matches >= 0)
 | 
			
		||||
			link_info->is_matching[match_id] = imsi_matches;
 | 
			
		||||
			link_info->is_matching[match_id] = imsi_matches ? true : false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -498,7 +498,7 @@ static struct gbproxy_link_info *gbproxy_get_link_info_ul(
 | 
			
		||||
	if (!link_info)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	link_info->is_deregistered = 0;
 | 
			
		||||
	link_info->is_deregistered = false;
 | 
			
		||||
 | 
			
		||||
	return link_info;
 | 
			
		||||
}
 | 
			
		||||
@@ -577,7 +577,7 @@ static struct gbproxy_link_info *gbproxy_get_link_info_dl(
 | 
			
		||||
			peer, parse_ctx->imsi, parse_ctx->imsi_len);
 | 
			
		||||
 | 
			
		||||
	if (link_info)
 | 
			
		||||
		link_info->is_deregistered = 0;
 | 
			
		||||
		link_info->is_deregistered = false;
 | 
			
		||||
 | 
			
		||||
	return link_info;
 | 
			
		||||
}
 | 
			
		||||
@@ -241,7 +241,7 @@ DEFUN(cfg_gbproxy_match_imsi,
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_cfg->acquire_imsi = 1;
 | 
			
		||||
	g_cfg->acquire_imsi = true;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -256,7 +256,7 @@ DEFUN(cfg_gbproxy_no_match_imsi,
 | 
			
		||||
	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;
 | 
			
		||||
	g_cfg->acquire_imsi = false;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -329,7 +329,7 @@ DEFUN(cfg_gbproxy_patch_ptmsi,
 | 
			
		||||
      "patch-ptmsi",
 | 
			
		||||
      GBPROXY_PATCH_PTMSI_STR)
 | 
			
		||||
{
 | 
			
		||||
	g_cfg->patch_ptmsi = 1;
 | 
			
		||||
	g_cfg->patch_ptmsi = true;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -339,7 +339,7 @@ DEFUN(cfg_gbproxy_no_patch_ptmsi,
 | 
			
		||||
      "no patch-ptmsi",
 | 
			
		||||
      NO_STR GBPROXY_PATCH_PTMSI_STR)
 | 
			
		||||
{
 | 
			
		||||
	g_cfg->patch_ptmsi = 0;
 | 
			
		||||
	g_cfg->patch_ptmsi = false;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -355,7 +355,7 @@ DEFUN(cfg_gbproxy_acquire_imsi,
 | 
			
		||||
      "acquire-imsi",
 | 
			
		||||
      GBPROXY_ACQUIRE_IMSI_STR)
 | 
			
		||||
{
 | 
			
		||||
	g_cfg->acquire_imsi = 1;
 | 
			
		||||
	g_cfg->acquire_imsi = true;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -365,7 +365,7 @@ DEFUN(cfg_gbproxy_no_acquire_imsi,
 | 
			
		||||
      "no acquire-imsi",
 | 
			
		||||
      NO_STR GBPROXY_ACQUIRE_IMSI_STR)
 | 
			
		||||
{
 | 
			
		||||
	g_cfg->acquire_imsi = 0;
 | 
			
		||||
	g_cfg->acquire_imsi = false;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -387,10 +387,10 @@ DEFUN(cfg_gbproxy_secondary_sgsn,
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_cfg->route_to_sgsn2 = 1;
 | 
			
		||||
	g_cfg->route_to_sgsn2 = true;
 | 
			
		||||
	g_cfg->nsip_sgsn2_nsei = nsei;
 | 
			
		||||
 | 
			
		||||
	g_cfg->patch_ptmsi = 1;
 | 
			
		||||
	g_cfg->patch_ptmsi = true;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -400,10 +400,10 @@ DEFUN(cfg_gbproxy_no_secondary_sgsn,
 | 
			
		||||
      "no secondary-sgsn",
 | 
			
		||||
      NO_STR GBPROXY_SECOND_SGSN_STR)
 | 
			
		||||
{
 | 
			
		||||
	g_cfg->route_to_sgsn2 = 0;
 | 
			
		||||
	g_cfg->route_to_sgsn2 = false;
 | 
			
		||||
	g_cfg->nsip_sgsn2_nsei = 0xFFFF;
 | 
			
		||||
 | 
			
		||||
	g_cfg->patch_ptmsi = 0;
 | 
			
		||||
	g_cfg->patch_ptmsi = false;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -849,7 +849,7 @@ DEFUN_DEPRECATED(cfg_gbproxy_broken_apn_match,
 | 
			
		||||
		return CMD_WARNING;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_cfg->acquire_imsi = 1;
 | 
			
		||||
	g_cfg->acquire_imsi = true;
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@@ -26,98 +26,21 @@ 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 \
 | 
			
		||||
libcommon_la_SOURCES = \
 | 
			
		||||
	gprs_gb_parse.c \
 | 
			
		||||
	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)
 | 
			
		||||
 
 | 
			
		||||
@@ -383,6 +383,14 @@ int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
 | 
			
		||||
		parse_ctx->invalidate_tlli = 1;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case GSM48_MT_GSM_DEACT_PDP_REQ:
 | 
			
		||||
		parse_ctx->llc_msg_name = "DEACT_PDP_REQ";
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case GSM48_MT_GSM_DEACT_PDP_ACK:
 | 
			
		||||
		parse_ctx->llc_msg_name = "DEACT_PDP_ACK";
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		LOGP(DLLC, LOGL_NOTICE,
 | 
			
		||||
		     "Unhandled GSM 04.08 message type %s for protocol discriminator %s.\n",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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)
 | 
			
		||||
@@ -238,12 +238,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 +322,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 +361,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);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										93
									
								
								src/sgsn/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/sgsn/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
AM_CPPFLAGS = \
 | 
			
		||||
	$(all_includes) \
 | 
			
		||||
	-I$(top_srcdir)/include \
 | 
			
		||||
	-I$(top_builddir) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
AM_CFLAGS = \
 | 
			
		||||
	-Wall \
 | 
			
		||||
	-fno-strict-aliasing \
 | 
			
		||||
	$(LIBOSMOCORE_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOGSM_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOVTY_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOCTRL_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOABIS_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOGB_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOGSUPCLIENT_CFLAGS) \
 | 
			
		||||
	$(COVERAGE_CFLAGS) \
 | 
			
		||||
	$(LIBCARES_CFLAGS) \
 | 
			
		||||
	$(LIBGTP_CFLAGS) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
if BUILD_IU
 | 
			
		||||
AM_CFLAGS += \
 | 
			
		||||
	$(LIBASN1C_CFLAGS) \
 | 
			
		||||
	$(LIBOSMOSIGTRAN_CFLAGS) \
 | 
			
		||||
	$(LIBOSMORANAP_CFLAGS) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
OSMO_LIBS = \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS) \
 | 
			
		||||
	$(LIBOSMOGSM_LIBS) \
 | 
			
		||||
	$(LIBOSMOVTY_LIBS) \
 | 
			
		||||
	$(LIBOSMOCTRL_LIBS) \
 | 
			
		||||
	$(LIBOSMOGB_LIBS) \
 | 
			
		||||
	$(LIBGTP_LIBS) \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
bin_PROGRAMS = \
 | 
			
		||||
	osmo-sgsn \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
osmo_sgsn_SOURCES = \
 | 
			
		||||
	gprs_gb.c \
 | 
			
		||||
	gprs_gmm_attach.c \
 | 
			
		||||
	gprs_gmm.c \
 | 
			
		||||
	gprs_gmm_fsm.c \
 | 
			
		||||
	gprs_mm_state_gb_fsm.c \
 | 
			
		||||
	gprs_sgsn.c \
 | 
			
		||||
	gprs_sm.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_vty.c \
 | 
			
		||||
	sgsn_ctrl.c \
 | 
			
		||||
	sgsn_auth.c \
 | 
			
		||||
	gprs_subscriber.c \
 | 
			
		||||
	sgsn_cdr.c \
 | 
			
		||||
	slhc.c \
 | 
			
		||||
	gprs_llc_xid.c \
 | 
			
		||||
	v42bis.c \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
osmo_sgsn_LDADD = \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_llc_parse.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/crc24.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_utils.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/sgsn_ares.o \
 | 
			
		||||
	$(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)
 | 
			
		||||
 | 
			
		||||
osmo_sgsn_SOURCES += \
 | 
			
		||||
	gprs_mm_state_iu_fsm.c \
 | 
			
		||||
	gprs_ranap.c
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										105
									
								
								src/sgsn/gprs_gb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/sgsn/gprs_gb.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
/* Messages on the Gb interface (A/Gb mode) */
 | 
			
		||||
 | 
			
		||||
/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org>
 | 
			
		||||
 * (C) 2010 by On-Waves
 | 
			
		||||
 * (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 *
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/rate_ctr.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/gprs/gprs_msgb.h>
 | 
			
		||||
#include <osmocom/gprs/gprs_bssgp.h>
 | 
			
		||||
 | 
			
		||||
#include "bscconfig.h"
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sm.h>
 | 
			
		||||
#include <osmocom/sgsn/debug.h>
 | 
			
		||||
 | 
			
		||||
/* Has to be called whenever any PDU (signaling, data, ...) has been received */
 | 
			
		||||
void gprs_gb_recv_pdu(struct sgsn_mm_ctx *mmctx) {
 | 
			
		||||
	if (mmctx->gb.llme)
 | 
			
		||||
		osmo_fsm_inst_dispatch(mmctx->gb.mm_state_fsm, E_MM_PDU_RECEPTION, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Main entry point for incoming 04.08 GPRS messages from Gb */
 | 
			
		||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
 | 
			
		||||
			   bool drop_cipherable)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
 | 
			
		||||
	uint8_t pdisc = gsm48_hdr_pdisc(gh);
 | 
			
		||||
	struct sgsn_mm_ctx *mmctx;
 | 
			
		||||
	struct gprs_ra_id ra_id;
 | 
			
		||||
	int rc = -EINVAL;
 | 
			
		||||
 | 
			
		||||
	bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
 | 
			
		||||
	mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
 | 
			
		||||
	if (mmctx) {
 | 
			
		||||
		msgid2mmctx(mmctx, msg);
 | 
			
		||||
		rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
 | 
			
		||||
		mmctx->gb.llme = llme;
 | 
			
		||||
		gprs_gb_recv_pdu(mmctx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* MMCTX can be NULL */
 | 
			
		||||
 | 
			
		||||
	switch (pdisc) {
 | 
			
		||||
	case GSM48_PDISC_MM_GPRS:
 | 
			
		||||
		rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
 | 
			
		||||
		break;
 | 
			
		||||
	case GSM48_PDISC_SM_GPRS:
 | 
			
		||||
		rc = gsm0408_rcv_gsm(mmctx, msg, llme);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOGMMCTXP(LOGL_NOTICE, mmctx,
 | 
			
		||||
			"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
 | 
			
		||||
			pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
 | 
			
		||||
		/* FIXME: return status message */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* MMCTX can be invalid */
 | 
			
		||||
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int gprs_gb_page_ps_ra(struct sgsn_mm_ctx *mmctx)
 | 
			
		||||
{
 | 
			
		||||
	struct bssgp_paging_info pinfo;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: page whole routing area, not only the last known cell */
 | 
			
		||||
 | 
			
		||||
	/* initiate PS PAGING procedure */
 | 
			
		||||
	memset(&pinfo, 0, sizeof(pinfo));
 | 
			
		||||
	pinfo.mode = BSSGP_PAGING_PS;
 | 
			
		||||
	pinfo.scope = BSSGP_PAGING_BVCI;
 | 
			
		||||
	pinfo.bvci = mmctx->gb.bvci;
 | 
			
		||||
	pinfo.imsi = mmctx->imsi;
 | 
			
		||||
	pinfo.ptmsi = &mmctx->p_tmsi;
 | 
			
		||||
	pinfo.drx_params = mmctx->drx_parms;
 | 
			
		||||
	pinfo.qos[0] = 0; // FIXME
 | 
			
		||||
	rc = bssgp_tx_paging(mmctx->gb.nsei, 0, &pinfo);
 | 
			
		||||
	rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PAGING_PS]);
 | 
			
		||||
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,3 +1,5 @@
 | 
			
		||||
#include <osmocom/core/tdef.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm_attach.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
 | 
			
		||||
@@ -10,6 +12,18 @@
 | 
			
		||||
static int require_identity_imei = 1;
 | 
			
		||||
static int require_auth = 1;
 | 
			
		||||
 | 
			
		||||
static const struct osmo_tdef_state_timeout gmm_attach_fsm_timeouts[32] = {
 | 
			
		||||
	[ST_IDENTIY] = { .T=3370 },
 | 
			
		||||
	[ST_AUTH] = { .T=3360 },
 | 
			
		||||
	[ST_ACCEPT] = { .T=3350 },
 | 
			
		||||
	[ST_ASK_VLR] = { .T=3350 },
 | 
			
		||||
	[ST_IU_SECURITY_CMD] = { .T=3350 },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define gmm_attach_fsm_state_chg(fi, NEXT_STATE) \
 | 
			
		||||
	osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, gmm_attach_fsm_timeouts, sgsn->cfg.T_defs, -1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_mm_ctx *ctx = fi->priv;
 | 
			
		||||
@@ -33,14 +47,14 @@ static void st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
 | 
			
		||||
	if (require_identity_imei) {
 | 
			
		||||
		ctx->gmm_att_req.id_type = GSM_MI_TYPE_IMEI;
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_IDENTIY, sgsn->cfg.timers.T3370, 3370);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_IDENTIY);
 | 
			
		||||
	} else if (!strlen(ctx->imsi)) {
 | 
			
		||||
		ctx->gmm_att_req.id_type = GSM_MI_TYPE_IMSI;
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_IDENTIY, sgsn->cfg.timers.T3370, 3370);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_IDENTIY);
 | 
			
		||||
	} else if (require_auth)
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_AUTH, sgsn->cfg.timers.T3360, 3360);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_AUTH);
 | 
			
		||||
	else
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_identity_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
 | 
			
		||||
@@ -94,11 +108,11 @@ static void st_identity(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
 | 
			
		||||
	if (type == GSM_MI_TYPE_IMEI && !strlen(ctx->imsi)) {
 | 
			
		||||
		ctx->gmm_att_req.id_type = GSM_MI_TYPE_IMSI;
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_IDENTIY, sgsn->cfg.timers.T3370, 3370);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_IDENTIY);
 | 
			
		||||
	} else if (require_auth)
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_AUTH, sgsn->cfg.timers.T3360, 3360);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_AUTH);
 | 
			
		||||
	else
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_auth_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
 | 
			
		||||
@@ -124,19 +138,19 @@ static void st_auth_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
 | 
			
		||||
	switch(auth_state) {
 | 
			
		||||
	case SGSN_AUTH_UMTS_RESYNC: /* ask the vlr for a new vector to match the simcards seq */
 | 
			
		||||
	case SGSN_AUTH_UNKNOWN: /* the SGSN doesn know this MS */
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_ASK_VLR, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_ASK_VLR);
 | 
			
		||||
		break;
 | 
			
		||||
	case SGSN_AUTH_REJECTED:
 | 
			
		||||
		/* TODO: correct GMM cause */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi, E_REJECT, (void *) GMM_CAUSE_GPRS_NOTALLOWED);
 | 
			
		||||
		break;
 | 
			
		||||
	case SGSN_AUTH_ACCEPTED:
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
 | 
			
		||||
		break;
 | 
			
		||||
	case SGSN_AUTH_AUTHENTICATE:
 | 
			
		||||
		if (ctx->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
 | 
			
		||||
			/* invalid key material */
 | 
			
		||||
			osmo_fsm_inst_state_chg(fi, ST_ASK_VLR, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
			gmm_attach_fsm_state_chg(fi, ST_ASK_VLR);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		struct gsm_auth_tuple *at = &ctx->auth_triplet;
 | 
			
		||||
@@ -159,14 +173,14 @@ static void st_auth(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
		sgsn_auth_request(ctx);
 | 
			
		||||
#ifdef BUILD_IU
 | 
			
		||||
		if (ctx->ran_type == MM_CTX_T_UTRAN_Iu && !ctx->iu.ue_ctx->integrity_active)
 | 
			
		||||
			osmo_fsm_inst_state_chg(fi, ST_IU_SECURITY_CMD, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
			gmm_attach_fsm_state_chg(fi, ST_IU_SECURITY_CMD);
 | 
			
		||||
		else
 | 
			
		||||
#endif /* BUILD_IU */
 | 
			
		||||
			osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
			gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_AUTH_RESP_RECV_RESYNC:
 | 
			
		||||
		if (ctx->gmm_att_req.auth_reattempt <= 1)
 | 
			
		||||
			osmo_fsm_inst_state_chg(fi, ST_ASK_VLR, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
			gmm_attach_fsm_state_chg(fi, ST_ASK_VLR);
 | 
			
		||||
		else
 | 
			
		||||
			osmo_fsm_inst_dispatch(fi, E_REJECT, (void *) GMM_CAUSE_SYNC_FAIL);
 | 
			
		||||
		break;
 | 
			
		||||
@@ -234,7 +248,7 @@ static void st_ask_vlr(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_VLR_ANSWERED:
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_AUTH, sgsn->cfg.timers.T3360, 3360);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_AUTH);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -246,7 +260,7 @@ static void st_iu_security_cmd_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_
 | 
			
		||||
 | 
			
		||||
	/* TODO: shouldn't this set always? not only when the integrity_active? */
 | 
			
		||||
	if (ctx->iu.ue_ctx->integrity_active) {
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -259,7 +273,7 @@ static void st_iu_security_cmd(struct osmo_fsm_inst *fi, uint32_t event, void *d
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_IU_SECURITY_CMD_COMPLETE:
 | 
			
		||||
		osmo_fsm_inst_state_chg(fi, ST_ACCEPT, sgsn->cfg.timers.T3350, 3350);
 | 
			
		||||
		gmm_attach_fsm_state_chg(fi, ST_ACCEPT);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -316,16 +330,16 @@ static struct osmo_fsm_state gmm_attach_req_fsm_states[] = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct value_string gmm_attach_req_fsm_event_names[] = {
 | 
			
		||||
	{ E_ATTACH_REQ_RECV,		"Received an attach request" },
 | 
			
		||||
	{ E_IDEN_RESP_RECV,		"Identity Request received" },
 | 
			
		||||
	{ E_AUTH_RESP_RECV_SUCCESS,	"Authentication Response received" },
 | 
			
		||||
	{ E_AUTH_RESP_RECV_RESYNC,	"Authentication Failure with resync received" },
 | 
			
		||||
	{ E_ATTACH_ACCEPTED,		"Attach accepted" },
 | 
			
		||||
	{ E_ATTACH_ACCEPT_SENT,		"Attach accept sent" },
 | 
			
		||||
	{ E_ATTACH_COMPLETE_RECV, 	"Attach complete received." },
 | 
			
		||||
	{ E_IU_SECURITY_CMD_COMPLETE,   "IU Security Command Complete received." },
 | 
			
		||||
	{ E_REJECT,			"Reject the MS"},
 | 
			
		||||
	{ E_VLR_ANSWERED,		"VLR answered"},
 | 
			
		||||
	OSMO_VALUE_STRING(E_ATTACH_REQ_RECV),
 | 
			
		||||
	OSMO_VALUE_STRING(E_IDEN_RESP_RECV),
 | 
			
		||||
	OSMO_VALUE_STRING(E_AUTH_RESP_RECV_SUCCESS),
 | 
			
		||||
	OSMO_VALUE_STRING(E_AUTH_RESP_RECV_RESYNC),
 | 
			
		||||
	OSMO_VALUE_STRING(E_ATTACH_ACCEPTED),
 | 
			
		||||
	OSMO_VALUE_STRING(E_ATTACH_ACCEPT_SENT),
 | 
			
		||||
	OSMO_VALUE_STRING(E_ATTACH_COMPLETE_RECV),
 | 
			
		||||
	OSMO_VALUE_STRING(E_IU_SECURITY_CMD_COMPLETE),
 | 
			
		||||
	OSMO_VALUE_STRING(E_REJECT),
 | 
			
		||||
	OSMO_VALUE_STRING(E_VLR_ANSWERED),
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -373,6 +387,7 @@ int gmm_attach_timer_cb(struct osmo_fsm_inst *fi)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_mm_ctx *ctx = fi->priv;
 | 
			
		||||
	struct gsm_auth_tuple *at = &ctx->auth_triplet;
 | 
			
		||||
	unsigned long t_secs;
 | 
			
		||||
 | 
			
		||||
	ctx->num_T_exp++;
 | 
			
		||||
 | 
			
		||||
@@ -392,7 +407,9 @@ int gmm_attach_timer_cb(struct osmo_fsm_inst *fi)
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		gsm48_tx_gmm_id_req(ctx, ctx->gmm_att_req.id_type);
 | 
			
		||||
		osmo_timer_schedule(&fi->timer, sgsn->cfg.timers.T3370, 0);
 | 
			
		||||
		t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3370, OSMO_TDEF_S, -1);
 | 
			
		||||
		osmo_timer_schedule(&fi->timer, t_secs, 0);
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	case ST_AUTH:
 | 
			
		||||
		/* T3360 */
 | 
			
		||||
@@ -401,7 +418,8 @@ int gmm_attach_timer_cb(struct osmo_fsm_inst *fi)
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		gsm48_tx_gmm_auth_ciph_req(ctx, &at->vec, at->key_seq, false);
 | 
			
		||||
		osmo_timer_schedule(&fi->timer, sgsn->cfg.timers.T3360, 0);
 | 
			
		||||
		t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3360, OSMO_TDEF_S, -1);
 | 
			
		||||
		osmo_timer_schedule(&fi->timer, t_secs, 0);
 | 
			
		||||
		break;
 | 
			
		||||
	case ST_ACCEPT:
 | 
			
		||||
		/* T3350 */
 | 
			
		||||
@@ -410,7 +428,8 @@ int gmm_attach_timer_cb(struct osmo_fsm_inst *fi)
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		gsm48_tx_gmm_att_ack(ctx);
 | 
			
		||||
		osmo_timer_schedule(&fi->timer, sgsn->cfg.timers.T3350, 0);
 | 
			
		||||
		t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3350, OSMO_TDEF_S, -1);
 | 
			
		||||
		osmo_timer_schedule(&fi->timer, t_secs, 0);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -430,7 +449,7 @@ struct osmo_fsm gmm_attach_req_fsm = {
 | 
			
		||||
 | 
			
		||||
static __attribute__((constructor)) void gprs_gmm_fsm_init(void)
 | 
			
		||||
{
 | 
			
		||||
	osmo_fsm_register(&gmm_attach_req_fsm);
 | 
			
		||||
	OSMO_ASSERT(osmo_fsm_register(&gmm_attach_req_fsm) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gmm_att_req_free(struct sgsn_mm_ctx *mm) {
 | 
			
		||||
							
								
								
									
										187
									
								
								src/sgsn/gprs_gmm_fsm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/sgsn/gprs_gmm_fsm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,187 @@
 | 
			
		||||
#include <osmocom/core/tdef.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/debug.h>
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
 | 
			
		||||
#define X(s) (1 << (s))
 | 
			
		||||
 | 
			
		||||
static const struct osmo_tdef_state_timeout gmm_fsm_timeouts[32] = {
 | 
			
		||||
	[ST_GMM_DEREGISTERED] = { },
 | 
			
		||||
	[ST_GMM_COMMON_PROC_INIT] = { },
 | 
			
		||||
	[ST_GMM_REGISTERED_NORMAL] = { },
 | 
			
		||||
	[ST_GMM_REGISTERED_SUSPENDED] = { },
 | 
			
		||||
	[ST_GMM_DEREGISTERED_INIT] = { },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define gmm_fsm_state_chg(fi, NEXT_STATE) \
 | 
			
		||||
	osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, gmm_fsm_timeouts, sgsn->cfg.T_defs, -1)
 | 
			
		||||
 | 
			
		||||
static void st_gmm_deregistered(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_GMM_COMMON_PROC_INIT_REQ:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_COMMON_PROC_INIT);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_GMM_ATTACH_SUCCESS:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_gmm_common_proc_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	/* TODO: events not used
 | 
			
		||||
	case E_GMM_LOWER_LAYER_FAILED:
 | 
			
		||||
	case E_GMM_COMMON_PROC_FAILED:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
 | 
			
		||||
		break;
 | 
			
		||||
	*/
 | 
			
		||||
	case E_GMM_COMMON_PROC_SUCCESS:
 | 
			
		||||
	case E_GMM_ATTACH_SUCCESS:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_gmm_registered_normal(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_GMM_COMMON_PROC_INIT_REQ:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_COMMON_PROC_INIT);
 | 
			
		||||
		break;
 | 
			
		||||
	/* case E_GMM_NET_INIT_DETACH_REQ:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED_INIT);
 | 
			
		||||
		break; */
 | 
			
		||||
	/* case E_GMM_MS_INIT_DETACH_REQ:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
 | 
			
		||||
		break; */
 | 
			
		||||
	case E_GMM_SUSPEND:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_SUSPENDED);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_gmm_registered_suspended(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_GMM_RESUME:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_REGISTERED_NORMAL);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_gmm_deregistered_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	/* TODO: events not used in osmo-sgsn code
 | 
			
		||||
	case E_GMM_DETACH_ACCEPTED:
 | 
			
		||||
	case E_GMM_LOWER_LAYER_FAILED:
 | 
			
		||||
		gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
 | 
			
		||||
		break;
 | 
			
		||||
	*/
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct osmo_fsm_state gmm_fsm_states[] = {
 | 
			
		||||
	[ST_GMM_DEREGISTERED] = {
 | 
			
		||||
		.in_event_mask =
 | 
			
		||||
			X(E_GMM_COMMON_PROC_INIT_REQ) |
 | 
			
		||||
			X(E_GMM_ATTACH_SUCCESS),
 | 
			
		||||
		.out_state_mask = X(ST_GMM_COMMON_PROC_INIT),
 | 
			
		||||
		.name = "Deregistered",
 | 
			
		||||
		.action = st_gmm_deregistered,
 | 
			
		||||
	},
 | 
			
		||||
	[ST_GMM_COMMON_PROC_INIT] = {
 | 
			
		||||
		.in_event_mask =
 | 
			
		||||
			/* X(E_GMM_LOWER_LAYER_FAILED) | */
 | 
			
		||||
			/* X(E_GMM_COMMON_PROC_FAILED) | */
 | 
			
		||||
			X(E_GMM_COMMON_PROC_SUCCESS) |
 | 
			
		||||
			X(E_GMM_ATTACH_SUCCESS),
 | 
			
		||||
		.out_state_mask =
 | 
			
		||||
			X(ST_GMM_DEREGISTERED) |
 | 
			
		||||
			X(ST_GMM_REGISTERED_NORMAL),
 | 
			
		||||
		.name = "CommonProcedureInitiated",
 | 
			
		||||
		.action = st_gmm_common_proc_init,
 | 
			
		||||
	},
 | 
			
		||||
	[ST_GMM_REGISTERED_NORMAL] = {
 | 
			
		||||
		.in_event_mask =
 | 
			
		||||
			X(E_GMM_COMMON_PROC_INIT_REQ) |
 | 
			
		||||
			/* X(E_GMM_NET_INIT_DETACH_REQ) | */
 | 
			
		||||
			/* X(E_GMM_MS_INIT_DETACH_REQ) | */
 | 
			
		||||
			X(E_GMM_SUSPEND),
 | 
			
		||||
		.out_state_mask =
 | 
			
		||||
			X(ST_GMM_DEREGISTERED) |
 | 
			
		||||
			X(ST_GMM_COMMON_PROC_INIT) |
 | 
			
		||||
			X(ST_GMM_DEREGISTERED_INIT) |
 | 
			
		||||
			X(ST_GMM_REGISTERED_SUSPENDED),
 | 
			
		||||
		.name = "Registered.NORMAL",
 | 
			
		||||
		.action = st_gmm_registered_normal,
 | 
			
		||||
	},
 | 
			
		||||
	[ST_GMM_REGISTERED_SUSPENDED] = {
 | 
			
		||||
		.in_event_mask = X(E_GMM_RESUME),
 | 
			
		||||
		.out_state_mask =
 | 
			
		||||
			X(ST_GMM_DEREGISTERED) |
 | 
			
		||||
			X(ST_GMM_REGISTERED_NORMAL),
 | 
			
		||||
		.name = "Registered.SUSPENDED",
 | 
			
		||||
		.action = st_gmm_registered_suspended,
 | 
			
		||||
	},
 | 
			
		||||
	[ST_GMM_DEREGISTERED_INIT] = {
 | 
			
		||||
		.in_event_mask = 0
 | 
			
		||||
			/* X(E_GMM_DETACH_ACCEPTED) | */
 | 
			
		||||
			/* X(E_GMM_LOWER_LAYER_FAILED) */,
 | 
			
		||||
		.out_state_mask = X(ST_GMM_DEREGISTERED),
 | 
			
		||||
		.name = "DeregisteredInitiated",
 | 
			
		||||
		.action = st_gmm_deregistered_init,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct value_string gmm_fsm_event_names[] = {
 | 
			
		||||
	OSMO_VALUE_STRING(E_GMM_COMMON_PROC_INIT_REQ),
 | 
			
		||||
	/* OSMO_VALUE_STRING(E_GMM_COMMON_PROC_FAILED), */
 | 
			
		||||
	/*  OSMO_VALUE_STRING(E_GMM_LOWER_LAYER_FAILED),  */
 | 
			
		||||
	OSMO_VALUE_STRING(E_GMM_COMMON_PROC_SUCCESS),
 | 
			
		||||
	OSMO_VALUE_STRING(E_GMM_ATTACH_SUCCESS),
 | 
			
		||||
	/*  OSMO_VALUE_STRING(E_GMM_NET_INIT_DETACH_REQ), */
 | 
			
		||||
	/*  OSMO_VALUE_STRING(E_GMM_MS_INIT_DETACH_REQ), */
 | 
			
		||||
	/* OSMO_VALUE_STRING(E_GMM_DETACH_ACCEPTED), */
 | 
			
		||||
	OSMO_VALUE_STRING(E_GMM_SUSPEND),
 | 
			
		||||
	OSMO_VALUE_STRING(E_GMM_CLEANUP),
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void gmm_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) {
 | 
			
		||||
	switch (event) {
 | 
			
		||||
	case E_GMM_CLEANUP:
 | 
			
		||||
		switch (fi->state) {
 | 
			
		||||
		case ST_GMM_DEREGISTERED:
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			gmm_fsm_state_chg(fi, ST_GMM_DEREGISTERED);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int gmm_fsm_timer_cb(struct osmo_fsm_inst *fi)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct osmo_fsm gmm_fsm = {
 | 
			
		||||
	.name = "GMM",
 | 
			
		||||
	.states = gmm_fsm_states,
 | 
			
		||||
	.num_states = ARRAY_SIZE(gmm_fsm_states),
 | 
			
		||||
	.event_names = gmm_fsm_event_names,
 | 
			
		||||
	.allstate_event_mask = X(E_GMM_CLEANUP),
 | 
			
		||||
	.allstate_action = gmm_fsm_allstate_action,
 | 
			
		||||
	.log_subsys = DMM,
 | 
			
		||||
	.timer_cb = gmm_fsm_timer_cb,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static __attribute__((constructor)) void gmm_fsm_init(void)
 | 
			
		||||
{
 | 
			
		||||
	OSMO_ASSERT(osmo_fsm_register(&gmm_fsm) == 0);
 | 
			
		||||
}
 | 
			
		||||
@@ -22,6 +22,7 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/core/linuxlist.h>
 | 
			
		||||
@@ -41,9 +42,16 @@
 | 
			
		||||
#include <osmocom/sgsn/gprs_sndcp_comp.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sndcp.h>
 | 
			
		||||
 | 
			
		||||
const struct value_string gprs_llc_llme_state_names[] = {
 | 
			
		||||
	{ GPRS_LLMS_UNASSIGNED,	"UNASSIGNED" },
 | 
			
		||||
	{ GPRS_LLMS_ASSIGNED,	"ASSIGNED" },
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct gprs_llc_llme *llme_alloc(uint32_t tlli);
 | 
			
		||||
static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
 | 
			
		||||
			   int command);
 | 
			
		||||
static int gprs_llc_tx_dm(struct gprs_llc_lle *lle);
 | 
			
		||||
static int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi,
 | 
			
		||||
			 int command, enum gprs_llc_u_cmd u_cmd, int pf_bit);
 | 
			
		||||
 | 
			
		||||
@@ -52,7 +60,7 @@ static int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi,
 | 
			
		||||
/* Generate XID message */
 | 
			
		||||
static int gprs_llc_generate_xid(uint8_t *bytes, int bytes_len,
 | 
			
		||||
				 struct gprs_llc_xid_field *l3_xid_field,
 | 
			
		||||
				 struct gprs_llc_llme *llme)
 | 
			
		||||
				 struct gprs_llc_lle *lle)
 | 
			
		||||
{
 | 
			
		||||
	/* Note: Called by gprs_ll_xid_req() */
 | 
			
		||||
 | 
			
		||||
@@ -61,17 +69,20 @@ static int gprs_llc_generate_xid(uint8_t *bytes, int bytes_len,
 | 
			
		||||
	struct gprs_llc_xid_field xid_version;
 | 
			
		||||
	struct gprs_llc_xid_field xid_n201u;
 | 
			
		||||
	struct gprs_llc_xid_field xid_n201i;
 | 
			
		||||
	uint16_t n201_u, n201_i;
 | 
			
		||||
 | 
			
		||||
	xid_version.type = GPRS_LLC_XID_T_VERSION;
 | 
			
		||||
	xid_version.data = (uint8_t *) "\x00";
 | 
			
		||||
	xid_version.data_len = 1;
 | 
			
		||||
 | 
			
		||||
	n201_u = htons(lle->params.n201_u);
 | 
			
		||||
	xid_n201u.type = GPRS_LLC_XID_T_N201_U;
 | 
			
		||||
	xid_n201u.data = (uint8_t *) "\x05\xf0";
 | 
			
		||||
	xid_n201u.data = (uint8_t *) &n201_u;
 | 
			
		||||
	xid_n201u.data_len = 2;
 | 
			
		||||
 | 
			
		||||
	n201_i = htons(lle->params.n201_i);
 | 
			
		||||
	xid_n201i.type = GPRS_LLC_XID_T_N201_I;
 | 
			
		||||
	xid_n201i.data = (uint8_t *) "\x05\xf0";
 | 
			
		||||
	xid_n201i.data = (uint8_t *) &n201_i;
 | 
			
		||||
	xid_n201i.data_len = 2;
 | 
			
		||||
 | 
			
		||||
	/* Add locally managed XID Fields */
 | 
			
		||||
@@ -89,8 +100,8 @@ static int gprs_llc_generate_xid(uint8_t *bytes, int bytes_len,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Store generated XID for later reference */
 | 
			
		||||
	talloc_free(llme->xid);
 | 
			
		||||
	llme->xid = gprs_llc_copy_xid(llme, &xid_fields);
 | 
			
		||||
	talloc_free(lle->xid);
 | 
			
		||||
	lle->xid = gprs_llc_copy_xid(lle->llme, &xid_fields);
 | 
			
		||||
 | 
			
		||||
	return gprs_llc_compile_xid(bytes, bytes_len, &xid_fields);
 | 
			
		||||
}
 | 
			
		||||
@@ -98,7 +109,7 @@ static int gprs_llc_generate_xid(uint8_t *bytes, int bytes_len,
 | 
			
		||||
/* Generate XID message that will cause the GMM to reset */
 | 
			
		||||
static int gprs_llc_generate_xid_for_gmm_reset(uint8_t *bytes,
 | 
			
		||||
					       int bytes_len, uint32_t iov_ui,
 | 
			
		||||
					       struct gprs_llc_llme *llme)
 | 
			
		||||
					       struct gprs_llc_lle *lle)
 | 
			
		||||
{
 | 
			
		||||
	/* Called by gprs_llgmm_reset() and
 | 
			
		||||
	 * gprs_llgmm_reset_oldmsg() */
 | 
			
		||||
@@ -123,8 +134,8 @@ static int gprs_llc_generate_xid_for_gmm_reset(uint8_t *bytes,
 | 
			
		||||
	llist_add(&xid_reset.list, &xid_fields);
 | 
			
		||||
 | 
			
		||||
	/* Store generated XID for later reference */
 | 
			
		||||
	talloc_free(llme->xid);
 | 
			
		||||
	llme->xid = gprs_llc_copy_xid(llme, &xid_fields);
 | 
			
		||||
	talloc_free(lle->xid);
 | 
			
		||||
	lle->xid = gprs_llc_copy_xid(lle->llme, &xid_fields);
 | 
			
		||||
 | 
			
		||||
	return gprs_llc_compile_xid(bytes, bytes_len, &xid_fields);
 | 
			
		||||
}
 | 
			
		||||
@@ -143,8 +154,8 @@ static int gprs_llc_process_xid_conf(uint8_t *bytes, int bytes_len,
 | 
			
		||||
	struct gprs_llc_xid_field *xid_field_request_l3 = NULL;
 | 
			
		||||
 | 
			
		||||
	/* Pick layer3 XID from the XID request we have sent last */
 | 
			
		||||
	if (lle->llme->xid) {
 | 
			
		||||
		llist_for_each_entry(xid_field_request, lle->llme->xid, list) {
 | 
			
		||||
	if (lle->xid) {
 | 
			
		||||
		llist_for_each_entry(xid_field_request, lle->xid, list) {
 | 
			
		||||
			if (xid_field_request->type == GPRS_LLC_XID_T_L3_PAR)
 | 
			
		||||
				xid_field_request_l3 = xid_field_request;
 | 
			
		||||
		}
 | 
			
		||||
@@ -188,8 +199,8 @@ static int gprs_llc_process_xid_conf(uint8_t *bytes, int bytes_len,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Flush pending XID fields */
 | 
			
		||||
	talloc_free(lle->llme->xid);
 | 
			
		||||
	lle->llme->xid = NULL;
 | 
			
		||||
	talloc_free(lle->xid);
 | 
			
		||||
	lle->xid = NULL;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -324,8 +335,7 @@ int gprs_ll_xid_req(struct gprs_llc_lle *lle,
 | 
			
		||||
 | 
			
		||||
	/* Generate XID */
 | 
			
		||||
	xid_bytes_len =
 | 
			
		||||
	    gprs_llc_generate_xid(xid_bytes, sizeof(xid_bytes),
 | 
			
		||||
				  l3_xid_field, lle->llme);
 | 
			
		||||
	    gprs_llc_generate_xid(xid_bytes, sizeof(xid_bytes), l3_xid_field, lle);
 | 
			
		||||
 | 
			
		||||
	/* Only perform XID sending if the XID message contains something */
 | 
			
		||||
	if (xid_bytes_len > 0) {
 | 
			
		||||
@@ -522,7 +532,7 @@ static struct gprs_llc_lle *lle_for_rx_by_tlli_sapi(const uint32_t tlli,
 | 
			
		||||
		struct gprs_llc_llme *llme;
 | 
			
		||||
		/* FIXME: don't use the TLLI but the 0xFFFF unassigned? */
 | 
			
		||||
		llme = llme_alloc(tlli);
 | 
			
		||||
		LOGP(DLLC, LOGL_NOTICE, "LLC RX: unknown TLLI 0x%08x, "
 | 
			
		||||
		LOGGBP(llme, DLLC, LOGL_NOTICE, "LLC RX: unknown TLLI 0x%08x, "
 | 
			
		||||
			"creating LLME on the fly\n", tlli);
 | 
			
		||||
		lle = &llme->lle[sapi];
 | 
			
		||||
		return lle;
 | 
			
		||||
@@ -556,7 +566,7 @@ static struct gprs_llc_llme *llme_alloc(uint32_t tlli)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	llme->tlli = tlli;
 | 
			
		||||
	llme->old_tlli = 0xffffffff;
 | 
			
		||||
	llme->old_tlli = TLLI_UNASSIGNED;
 | 
			
		||||
	llme->state = GPRS_LLMS_UNASSIGNED;
 | 
			
		||||
	llme->age_timestamp = GPRS_LLME_RESET_AGE;
 | 
			
		||||
	llme->cksn = GSM_KEY_SEQ_INVAL;
 | 
			
		||||
@@ -576,7 +586,6 @@ static void llme_free(struct gprs_llc_llme *llme)
 | 
			
		||||
{
 | 
			
		||||
	gprs_sndcp_comp_free(llme->comp.proto);
 | 
			
		||||
	gprs_sndcp_comp_free(llme->comp.data);
 | 
			
		||||
	talloc_free(llme->xid);
 | 
			
		||||
	llist_del(&llme->list);
 | 
			
		||||
	talloc_free(llme);
 | 
			
		||||
}
 | 
			
		||||
@@ -676,6 +685,18 @@ static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg,
 | 
			
		||||
	return gprs_llc_tx_u(msg, lle->sapi, command, GPRS_LLC_U_XID, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int gprs_llc_tx_dm(struct gprs_llc_lle *lle)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_DM");
 | 
			
		||||
 | 
			
		||||
	/* copy identifiers from LLE to ensure lower layers can route */
 | 
			
		||||
	msgb_tlli(msg) = lle->llme->tlli;
 | 
			
		||||
	msgb_bvci(msg) = lle->llme->bvci;
 | 
			
		||||
	msgb_nsei(msg) = lle->llme->nsei;
 | 
			
		||||
 | 
			
		||||
	return gprs_llc_tx_u(msg, lle->sapi, 0, GPRS_LLC_U_DM_RESP, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* encrypt information field + FCS, if needed! */
 | 
			
		||||
static int apply_gea(struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu,
 | 
			
		||||
		     uint32_t oc, uint8_t sapi, uint8_t *fcs, uint8_t *data)
 | 
			
		||||
@@ -802,6 +823,8 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
 | 
			
		||||
			   struct gprs_llc_lle *lle)
 | 
			
		||||
{
 | 
			
		||||
	switch (gph->cmd) {
 | 
			
		||||
#if 0
 | 
			
		||||
	/* we don't fully imoplement ABM, so refuse it properly (OS#3953) */
 | 
			
		||||
	case GPRS_LLC_SABM: /* Section 6.4.1.1 */
 | 
			
		||||
		lle->v_sent = lle->v_ack = lle->v_recv = 0;
 | 
			
		||||
		if (lle->state == GPRS_LLES_ASSIGNED_ADM) {
 | 
			
		||||
@@ -827,6 +850,13 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
 | 
			
		||||
		break;
 | 
			
		||||
	case GPRS_LLC_FRMR: /* Section 6.4.1.5 */
 | 
			
		||||
		break;
 | 
			
		||||
#else
 | 
			
		||||
	case GPRS_LLC_SABM:
 | 
			
		||||
	case GPRS_LLC_DISC:
 | 
			
		||||
		/* send DM to properly signal we don't do ABM */
 | 
			
		||||
		gprs_llc_tx_dm(lle);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	case GPRS_LLC_XID: /* Section 6.4.1.6 */
 | 
			
		||||
		rx_llc_xid(lle, gph);
 | 
			
		||||
		break;
 | 
			
		||||
@@ -860,6 +890,9 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
 | 
			
		||||
		if ((gph->seq_tx + 1) / 512)
 | 
			
		||||
			lle->oc_ui_recv += 512;
 | 
			
		||||
		break;
 | 
			
		||||
	case GPRS_LLC_NULL:
 | 
			
		||||
		LOGP(DLLC, LOGL_DEBUG, "TLLI=%08x sends us LLC NULL\n", lle->llme ? lle->llme->tlli : -1);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOGP(DLLC, LOGL_NOTICE, "Unhandled command: %d\n", gph->cmd);
 | 
			
		||||
		break;
 | 
			
		||||
@@ -945,9 +978,6 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
 | 
			
		||||
		LOGP(DLLC, LOGL_INFO, "Dropping frame with invalid FCS\n");
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
	/* set l3 layer & remove the fcs */
 | 
			
		||||
	msg->l3h = llhp.data;
 | 
			
		||||
	msgb_l3trim(msg, llhp.data_len);
 | 
			
		||||
 | 
			
		||||
	/* Update LLE's (BVCI, NSEI) tuple */
 | 
			
		||||
	lle->llme->bvci = msgb_bvci(msg);
 | 
			
		||||
@@ -958,6 +988,14 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
 | 
			
		||||
	if (rc < 0)
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
	/* there are many frame types that don't carry user information
 | 
			
		||||
	 * and which hence have llhp.data = NULL */
 | 
			
		||||
	if (llhp.data)  {
 | 
			
		||||
		/* set l3 layer & remove the fcs */
 | 
			
		||||
		msg->l3h = llhp.data;
 | 
			
		||||
		msgb_l3trim(msg, llhp.data_len);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_LLC_UL_PACKETS]);
 | 
			
		||||
	rate_ctr_add(&sgsn->rate_ctrs->ctr[CTR_LLC_UL_BYTES], msg->len);
 | 
			
		||||
 | 
			
		||||
@@ -1013,20 +1051,24 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme,
 | 
			
		||||
		      uint32_t old_tlli, uint32_t new_tlli)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
	bool free = false;
 | 
			
		||||
 | 
			
		||||
	if (old_tlli == 0xffffffff && new_tlli != 0xffffffff) {
 | 
			
		||||
	LOGGBP(llme, DLLC, LOGL_NOTICE, "LLGM Assign pre (%08x => %08x)\n",
 | 
			
		||||
	       old_tlli, new_tlli);
 | 
			
		||||
 | 
			
		||||
	if (old_tlli == TLLI_UNASSIGNED && new_tlli != TLLI_UNASSIGNED) {
 | 
			
		||||
		/* TLLI Assignment 8.3.1 */
 | 
			
		||||
		/* New TLLI shall be assigned and used when (re)transmitting LLC frames */
 | 
			
		||||
		/* If old TLLI != 0xffffffff was assigned to LLME, then TLLI
 | 
			
		||||
		/* If old TLLI != TLLI_UNASSIGNED was assigned to LLME, then TLLI
 | 
			
		||||
		 * old is unassigned.  Only TLLI new shall be accepted when
 | 
			
		||||
		 * received from peer. */
 | 
			
		||||
		if (llme->old_tlli != 0xffffffff) {
 | 
			
		||||
			llme->old_tlli = 0xffffffff;
 | 
			
		||||
		if (llme->old_tlli != TLLI_UNASSIGNED) {
 | 
			
		||||
			llme->old_tlli = TLLI_UNASSIGNED;
 | 
			
		||||
			llme->tlli = new_tlli;
 | 
			
		||||
		} else {
 | 
			
		||||
			/* If TLLI old == 0xffffffff was assigned to LLME, then this is
 | 
			
		||||
			/* If TLLI old == TLLI_UNASSIGNED was assigned to LLME, then this is
 | 
			
		||||
			 * TLLI assignmemt according to 8.3.1 */
 | 
			
		||||
			llme->old_tlli = 0xffffffff;
 | 
			
		||||
			llme->old_tlli = TLLI_UNASSIGNED;
 | 
			
		||||
			llme->tlli = new_tlli;
 | 
			
		||||
			llme->state = GPRS_LLMS_ASSIGNED;
 | 
			
		||||
			/* 8.5.3.1 For all LLE's */
 | 
			
		||||
@@ -1038,14 +1080,14 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme,
 | 
			
		||||
				/* FIXME Set parameters according to table 9 */
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else if (old_tlli != 0xffffffff && new_tlli != 0xffffffff) {
 | 
			
		||||
	} else if (old_tlli != TLLI_UNASSIGNED && new_tlli != TLLI_UNASSIGNED) {
 | 
			
		||||
		/* TLLI Change 8.3.2 */
 | 
			
		||||
		/* Both TLLI Old and TLLI New are assigned; use New when
 | 
			
		||||
		 * (re)transmitting.  Accept both Old and New on Rx */
 | 
			
		||||
		llme->old_tlli = old_tlli;
 | 
			
		||||
		llme->tlli = new_tlli;
 | 
			
		||||
		llme->state = GPRS_LLMS_ASSIGNED;
 | 
			
		||||
	} else if (old_tlli != 0xffffffff && new_tlli == 0xffffffff) {
 | 
			
		||||
	} else if (old_tlli != TLLI_UNASSIGNED && new_tlli == TLLI_UNASSIGNED) {
 | 
			
		||||
		/* TLLI Unassignment 8.3.3) */
 | 
			
		||||
		llme->tlli = llme->old_tlli = 0;
 | 
			
		||||
		llme->state = GPRS_LLMS_UNASSIGNED;
 | 
			
		||||
@@ -1053,39 +1095,47 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme,
 | 
			
		||||
			struct gprs_llc_lle *l = &llme->lle[i];
 | 
			
		||||
			l->state = GPRS_LLES_UNASSIGNED;
 | 
			
		||||
		}
 | 
			
		||||
		llme_free(llme);
 | 
			
		||||
		free = true;
 | 
			
		||||
	} else
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	LOGGBP(llme, DLLC, LOGL_NOTICE, "LLGM Assign post (%08x => %08x)\n",
 | 
			
		||||
	       old_tlli, new_tlli);
 | 
			
		||||
 | 
			
		||||
	if (free)
 | 
			
		||||
		llme_free(llme);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* TLLI unassignment */
 | 
			
		||||
int gprs_llgmm_unassign(struct gprs_llc_llme *llme)
 | 
			
		||||
{
 | 
			
		||||
	return gprs_llgmm_assign(llme, llme->tlli, 0xffffffff);
 | 
			
		||||
	return gprs_llgmm_assign(llme, llme->tlli, TLLI_UNASSIGNED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Chapter 7.2.1.2 LLGMM-RESET.req */
 | 
			
		||||
int gprs_llgmm_reset(struct gprs_llc_llme *llme)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_XID");
 | 
			
		||||
	struct gprs_llc_lle *lle = &llme->lle[1];
 | 
			
		||||
	struct gprs_llc_lle *lle = &llme->lle[GPRS_SAPI_GMM];
 | 
			
		||||
	uint8_t xid_bytes[1024];
 | 
			
		||||
	int xid_bytes_len, rc;
 | 
			
		||||
	uint8_t *xid;
 | 
			
		||||
 | 
			
		||||
	LOGP(DLLC, LOGL_NOTICE, "LLGM Reset\n");
 | 
			
		||||
	LOGGBP(llme, DLLC, LOGL_NOTICE, "LLGM Reset\n");
 | 
			
		||||
 | 
			
		||||
	rc = osmo_get_rand_id((uint8_t *) &llme->iov_ui, 4);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		LOGP(DLLC, LOGL_ERROR, "osmo_get_rand_id() failed for LLC XID reset: %s\n", strerror(-rc));
 | 
			
		||||
		LOGGBP(llme, DLLC, LOGL_ERROR,
 | 
			
		||||
		       "osmo_get_rand_id() failed for LLC XID reset: %s\n",
 | 
			
		||||
		       strerror(-rc));
 | 
			
		||||
		return rc;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Generate XID message */
 | 
			
		||||
	xid_bytes_len = gprs_llc_generate_xid_for_gmm_reset(xid_bytes,
 | 
			
		||||
					sizeof(xid_bytes),llme->iov_ui,llme);
 | 
			
		||||
	xid_bytes_len = gprs_llc_generate_xid_for_gmm_reset(xid_bytes, sizeof(xid_bytes),
 | 
			
		||||
							    llme->iov_ui, lle);
 | 
			
		||||
	if (xid_bytes_len < 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	xid = msgb_put(msg, xid_bytes_len);
 | 
			
		||||
@@ -1105,21 +1155,24 @@ int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi,
 | 
			
		||||
			    struct gprs_llc_llme *llme)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_XID");
 | 
			
		||||
	struct gprs_llc_lle *lle = &llme->lle[sapi];
 | 
			
		||||
	uint8_t xid_bytes[1024];
 | 
			
		||||
	int xid_bytes_len, rc;
 | 
			
		||||
	uint8_t *xid;
 | 
			
		||||
 | 
			
		||||
	LOGP(DLLC, LOGL_NOTICE, "LLGM Reset\n");
 | 
			
		||||
	LOGGBP(llme, DLLC, LOGL_NOTICE, "LLGM Reset (SAPI=%" PRIu8 ")\n", sapi);
 | 
			
		||||
 | 
			
		||||
	rc = osmo_get_rand_id((uint8_t *) &llme->iov_ui, 4);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		LOGP(DLLC, LOGL_ERROR, "osmo_get_rand_id() failed for LLC XID reset: %s\n", strerror(-rc));
 | 
			
		||||
		LOGGBP(llme, DLLC, LOGL_ERROR,
 | 
			
		||||
		       "osmo_get_rand_id() failed for LLC XID reset: %s\n",
 | 
			
		||||
		       strerror(-rc));
 | 
			
		||||
		return rc;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Generate XID message */
 | 
			
		||||
	xid_bytes_len = gprs_llc_generate_xid_for_gmm_reset(xid_bytes,
 | 
			
		||||
					sizeof(xid_bytes),llme->iov_ui,llme);
 | 
			
		||||
	xid_bytes_len = gprs_llc_generate_xid_for_gmm_reset(xid_bytes, sizeof(xid_bytes),
 | 
			
		||||
							    llme->iov_ui, lle);
 | 
			
		||||
	if (xid_bytes_len < 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	xid = msgb_put(msg, xid_bytes_len);
 | 
			
		||||
@@ -41,7 +41,7 @@ const struct value_string gprs_llc_xid_type_names[] = {
 | 
			
		||||
	{ GPRS_LLC_XID_T_IOV_I,		"IOV_I"},
 | 
			
		||||
	{ GPRS_LLC_XID_T_T200,		"T200"},
 | 
			
		||||
	{ GPRS_LLC_XID_T_N200,		"N200"},
 | 
			
		||||
	{ GPRS_LLC_XID_T_N201_U,	"N201_"},
 | 
			
		||||
	{ GPRS_LLC_XID_T_N201_U,	"N201_U"},
 | 
			
		||||
	{ GPRS_LLC_XID_T_N201_I,	"N201_I"},
 | 
			
		||||
	{ GPRS_LLC_XID_T_mD,		"mD"},
 | 
			
		||||
	{ GPRS_LLC_XID_T_mU,		"mU"},
 | 
			
		||||
							
								
								
									
										129
									
								
								src/sgsn/gprs_mm_state_gb_fsm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								src/sgsn/gprs_mm_state_gb_fsm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
			
		||||
#include <osmocom/core/tdef.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_llc.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/debug.h>
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
 | 
			
		||||
#define X(s) (1 << (s))
 | 
			
		||||
 | 
			
		||||
static const struct osmo_tdef_state_timeout mm_state_gb_fsm_timeouts[32] = {
 | 
			
		||||
	[ST_MM_IDLE] = { },
 | 
			
		||||
	[ST_MM_READY] = { .T=3314 },
 | 
			
		||||
	[ST_MM_STANDBY] = { },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define mm_state_gb_fsm_state_chg(fi, NEXT_STATE) \
 | 
			
		||||
	osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, mm_state_gb_fsm_timeouts, sgsn->cfg.T_defs, -1)
 | 
			
		||||
 | 
			
		||||
static void st_mm_idle_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) {
 | 
			
		||||
	struct sgsn_mm_ctx *ctx = fi->priv;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: remove this timer when RAU has it's own fsm */
 | 
			
		||||
	if (ctx->T == 3350 && osmo_timer_pending(&ctx->timer))
 | 
			
		||||
		osmo_timer_del(&ctx->timer);
 | 
			
		||||
 | 
			
		||||
	if (ctx->gb.llme) {
 | 
			
		||||
		gprs_llgmm_unassign(ctx->gb.llme);
 | 
			
		||||
		ctx->gb.llme = NULL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_mm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_MM_GPRS_ATTACH:
 | 
			
		||||
		mm_state_gb_fsm_state_chg(fi, ST_MM_READY);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_MM_PDU_RECEPTION:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_mm_ready(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long t_secs;
 | 
			
		||||
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_MM_READY_TIMER_EXPIRY:
 | 
			
		||||
		mm_state_gb_fsm_state_chg(fi, ST_MM_STANDBY);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_MM_IMPLICIT_DETACH:
 | 
			
		||||
		mm_state_gb_fsm_state_chg(fi, ST_MM_IDLE);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_MM_PDU_RECEPTION:
 | 
			
		||||
		/* RE-arm the READY timer upon receival of Gb PDUs */
 | 
			
		||||
		t_secs = osmo_tdef_get(sgsn->cfg.T_defs, 3314, OSMO_TDEF_S, -1);
 | 
			
		||||
		osmo_timer_schedule(&fi->timer, t_secs, 0);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_MM_RA_UPDATE:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_mm_standby(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_MM_PDU_RECEPTION:
 | 
			
		||||
		mm_state_gb_fsm_state_chg(fi, ST_MM_READY);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct osmo_fsm_state mm_state_gb_fsm_states[] = {
 | 
			
		||||
	[ST_MM_IDLE] = {
 | 
			
		||||
		.in_event_mask = X(E_MM_GPRS_ATTACH) | X(E_MM_PDU_RECEPTION),
 | 
			
		||||
		.out_state_mask = X(ST_MM_READY),
 | 
			
		||||
		.onenter = st_mm_idle_on_enter,
 | 
			
		||||
		.name = "Idle",
 | 
			
		||||
		.action = st_mm_idle,
 | 
			
		||||
	},
 | 
			
		||||
	[ST_MM_READY] = {
 | 
			
		||||
		.in_event_mask = X(E_MM_READY_TIMER_EXPIRY) | X(E_MM_RA_UPDATE) | X(E_MM_IMPLICIT_DETACH) | X(E_MM_PDU_RECEPTION),
 | 
			
		||||
		.out_state_mask = X(ST_MM_IDLE) | X(ST_MM_STANDBY),
 | 
			
		||||
		.name = "Ready",
 | 
			
		||||
		.action = st_mm_ready,
 | 
			
		||||
	},
 | 
			
		||||
	[ST_MM_STANDBY] = {
 | 
			
		||||
		.in_event_mask = X(E_MM_PDU_RECEPTION),
 | 
			
		||||
		.out_state_mask = X(ST_MM_IDLE) | X(ST_MM_READY),
 | 
			
		||||
		.name = "Standby",
 | 
			
		||||
		.action = st_mm_standby,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct value_string mm_state_gb_fsm_event_names[] = {
 | 
			
		||||
	OSMO_VALUE_STRING(E_MM_GPRS_ATTACH),
 | 
			
		||||
	OSMO_VALUE_STRING(E_MM_PDU_RECEPTION),
 | 
			
		||||
	OSMO_VALUE_STRING(E_MM_IMPLICIT_DETACH),
 | 
			
		||||
	OSMO_VALUE_STRING(E_MM_READY_TIMER_EXPIRY),
 | 
			
		||||
	OSMO_VALUE_STRING(E_MM_RA_UPDATE),
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int mm_state_gb_fsm_timer_cb(struct osmo_fsm_inst *fi)
 | 
			
		||||
{
 | 
			
		||||
	switch(fi->state) {
 | 
			
		||||
	case ST_MM_READY:
 | 
			
		||||
		/* timer for mm state. state=READY: T3314 (aka TS 23.060 "READY timer") */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi, E_MM_READY_TIMER_EXPIRY, NULL);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct osmo_fsm mm_state_gb_fsm = {
 | 
			
		||||
	.name = "MM_STATE_Gb",
 | 
			
		||||
	.states = mm_state_gb_fsm_states,
 | 
			
		||||
	.num_states = ARRAY_SIZE(mm_state_gb_fsm_states),
 | 
			
		||||
	.event_names = mm_state_gb_fsm_event_names,
 | 
			
		||||
	.log_subsys = DMM,
 | 
			
		||||
	.timer_cb = mm_state_gb_fsm_timer_cb,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static __attribute__((constructor)) void mm_state_gb_fsm_init(void)
 | 
			
		||||
{
 | 
			
		||||
	OSMO_ASSERT(osmo_fsm_register(&mm_state_gb_fsm) == 0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										150
									
								
								src/sgsn/gprs_mm_state_iu_fsm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								src/sgsn/gprs_mm_state_iu_fsm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/tdef.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/debug.h>
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_ranap.h>
 | 
			
		||||
 | 
			
		||||
#define X(s) (1 << (s))
 | 
			
		||||
 | 
			
		||||
static const struct osmo_tdef_state_timeout mm_state_iu_fsm_timeouts[32] = {
 | 
			
		||||
	[ST_PMM_DETACHED] = { },
 | 
			
		||||
	/* non-spec -T3314 (User inactivity timer) */
 | 
			
		||||
	[ST_PMM_CONNECTED] = { .T=-3314 },
 | 
			
		||||
	[ST_PMM_IDLE] = { },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define mm_state_iu_fsm_state_chg(fi, NEXT_STATE) \
 | 
			
		||||
	osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, mm_state_iu_fsm_timeouts, sgsn->cfg.T_defs, -1)
 | 
			
		||||
 | 
			
		||||
static void mmctx_change_gtpu_endpoints_to_sgsn(struct sgsn_mm_ctx *mm_ctx)
 | 
			
		||||
{
 | 
			
		||||
	char buf[INET_ADDRSTRLEN];
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp;
 | 
			
		||||
	llist_for_each_entry(pdp, &mm_ctx->pdp_list, list) {
 | 
			
		||||
		LOGMMCTXP(LOGL_INFO, mm_ctx, "Changing GTP-U endpoints %s -> %s\n",
 | 
			
		||||
			  sgsn_gtp_ntoa(&pdp->lib->gsnlu),
 | 
			
		||||
			  inet_ntop(AF_INET, &sgsn->cfg.gtp_listenaddr.sin_addr, buf, sizeof(buf)));
 | 
			
		||||
		sgsn_pdp_upd_gtp_u(pdp,
 | 
			
		||||
				   &sgsn->cfg.gtp_listenaddr.sin_addr,
 | 
			
		||||
				   sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_pmm_detached(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_PMM_PS_ATTACH:
 | 
			
		||||
		mm_state_iu_fsm_state_chg(fi, ST_PMM_CONNECTED);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_PMM_IMPLICIT_DETACH:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_pmm_connected(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_mm_ctx *ctx = fi->priv;
 | 
			
		||||
	const struct RANAP_Cause user_inactive_cause = {
 | 
			
		||||
		.present = RANAP_Cause_PR_radioNetwork,
 | 
			
		||||
		.choice.radioNetwork = RANAP_CauseRadioNetwork_user_inactivity,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_PMM_PS_CONN_RELEASE:
 | 
			
		||||
		sgsn_ranap_iu_free(ctx);
 | 
			
		||||
		mm_state_iu_fsm_state_chg(fi, ST_PMM_IDLE);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_PMM_IMPLICIT_DETACH:
 | 
			
		||||
		sgsn_ranap_iu_release_free(ctx, NULL);
 | 
			
		||||
		mm_state_iu_fsm_state_chg(fi, ST_PMM_DETACHED);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_PMM_USER_INACTIVITY:
 | 
			
		||||
		sgsn_ranap_iu_release_free(ctx, &user_inactive_cause);
 | 
			
		||||
		mm_state_iu_fsm_state_chg(fi, ST_PMM_DETACHED);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_PMM_RA_UPDATE:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_pmm_idle_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_mm_ctx *ctx = fi->priv;
 | 
			
		||||
 | 
			
		||||
	mmctx_change_gtpu_endpoints_to_sgsn(ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void st_pmm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	switch(event) {
 | 
			
		||||
	case E_PMM_PS_CONN_ESTABLISH:
 | 
			
		||||
		mm_state_iu_fsm_state_chg(fi, ST_PMM_CONNECTED);
 | 
			
		||||
		break;
 | 
			
		||||
	case E_PMM_IMPLICIT_DETACH:
 | 
			
		||||
		mm_state_iu_fsm_state_chg(fi, ST_PMM_DETACHED);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int pmm_state_fsm_timer_cb(struct osmo_fsm_inst *fi)
 | 
			
		||||
{
 | 
			
		||||
	switch(fi->state) {
 | 
			
		||||
	case ST_PMM_CONNECTED:
 | 
			
		||||
		/* timer for pmm state. state=CONNECTED: -T3314 (User inactivity timer) */
 | 
			
		||||
		osmo_fsm_inst_dispatch(fi, E_PMM_USER_INACTIVITY, NULL);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct osmo_fsm_state mm_state_iu_fsm_states[] = {
 | 
			
		||||
	[ST_PMM_DETACHED] = {
 | 
			
		||||
		.in_event_mask = X(E_PMM_PS_ATTACH) | X(E_PMM_IMPLICIT_DETACH),
 | 
			
		||||
		.out_state_mask = X(ST_PMM_CONNECTED),
 | 
			
		||||
		.name = "Detached",
 | 
			
		||||
		.action = st_pmm_detached,
 | 
			
		||||
	},
 | 
			
		||||
	[ST_PMM_CONNECTED] = {
 | 
			
		||||
		.in_event_mask = X(E_PMM_PS_CONN_RELEASE) | X(E_PMM_RA_UPDATE)
 | 
			
		||||
			| X(E_PMM_IMPLICIT_DETACH) | X(E_PMM_USER_INACTIVITY),
 | 
			
		||||
		.out_state_mask = X(ST_PMM_DETACHED) | X(ST_PMM_IDLE),
 | 
			
		||||
		.name = "Connected",
 | 
			
		||||
		.action = st_pmm_connected,
 | 
			
		||||
	},
 | 
			
		||||
	[ST_PMM_IDLE] = {
 | 
			
		||||
		.in_event_mask = X(E_PMM_IMPLICIT_DETACH) | X(E_PMM_PS_CONN_ESTABLISH),
 | 
			
		||||
		.out_state_mask = X(ST_PMM_DETACHED) | X(ST_PMM_CONNECTED),
 | 
			
		||||
		.name = "Idle",
 | 
			
		||||
		.onenter = st_pmm_idle_on_enter,
 | 
			
		||||
		.action = st_pmm_idle,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct value_string mm_state_iu_fsm_event_names[] = {
 | 
			
		||||
	OSMO_VALUE_STRING(E_PMM_PS_ATTACH),
 | 
			
		||||
	OSMO_VALUE_STRING(E_PMM_PS_CONN_RELEASE),
 | 
			
		||||
	OSMO_VALUE_STRING(E_PMM_PS_CONN_ESTABLISH),
 | 
			
		||||
	OSMO_VALUE_STRING(E_PMM_IMPLICIT_DETACH),
 | 
			
		||||
	OSMO_VALUE_STRING(E_PMM_RA_UPDATE),
 | 
			
		||||
	OSMO_VALUE_STRING(E_PMM_USER_INACTIVITY),
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct osmo_fsm mm_state_iu_fsm = {
 | 
			
		||||
	.name = "MM_STATE_Iu",
 | 
			
		||||
	.states = mm_state_iu_fsm_states,
 | 
			
		||||
	.num_states = ARRAY_SIZE(mm_state_iu_fsm_states),
 | 
			
		||||
	.event_names = mm_state_iu_fsm_event_names,
 | 
			
		||||
	.timer_cb = pmm_state_fsm_timer_cb,
 | 
			
		||||
	.log_subsys = DMM,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static __attribute__((constructor)) void mm_state_iu_fsm_init(void)
 | 
			
		||||
{
 | 
			
		||||
	OSMO_ASSERT(osmo_fsm_register(&mm_state_iu_fsm) == 0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										260
									
								
								src/sgsn/gprs_ranap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								src/sgsn/gprs_ranap.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,260 @@
 | 
			
		||||
/* Messages on the RANAP interface (Iu mode) */
 | 
			
		||||
 | 
			
		||||
/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org>
 | 
			
		||||
 * (C) 2015 by Holger Hans Peter Freyther
 | 
			
		||||
 * (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 *
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "bscconfig.h"
 | 
			
		||||
#include <gtp.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/rate_ctr.h>
 | 
			
		||||
#include <osmocom/core/tdef.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/ranap/ranap_common.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sm.h>
 | 
			
		||||
#include <osmocom/sgsn/debug.h>
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_ranap.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm_attach.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
 | 
			
		||||
 | 
			
		||||
/* Send RAB activation requests for all PDP contexts */
 | 
			
		||||
void activate_pdp_rabs(struct sgsn_mm_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp;
 | 
			
		||||
	if (ctx->ran_type != MM_CTX_T_UTRAN_Iu)
 | 
			
		||||
		return;
 | 
			
		||||
	llist_for_each_entry(pdp, &ctx->pdp_list, list) {
 | 
			
		||||
		iu_rab_act_ps(pdp->nsapi, pdp);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Callback for RAB assignment response */
 | 
			
		||||
static int sgsn_ranap_rab_ass_resp(struct sgsn_mm_ctx *ctx, RANAP_RAB_SetupOrModifiedItemIEs_t *setup_ies)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t rab_id;
 | 
			
		||||
	bool require_pdp_update = false;
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp = NULL;
 | 
			
		||||
	RANAP_RAB_SetupOrModifiedItem_t *item = &setup_ies->raB_SetupOrModifiedItem;
 | 
			
		||||
 | 
			
		||||
	rab_id = item->rAB_ID.buf[0];
 | 
			
		||||
 | 
			
		||||
	pdp = sgsn_pdp_ctx_by_nsapi(ctx, rab_id);
 | 
			
		||||
	if (!pdp) {
 | 
			
		||||
		LOGP(DRANAP, LOGL_ERROR, "RAB Assignment Response for unknown RAB/NSAPI=%u\n", rab_id);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (item->transportLayerAddress) {
 | 
			
		||||
		LOGPC(DRANAP, LOGL_INFO, " Setup: (%u/%s)", rab_id, osmo_hexdump(item->transportLayerAddress->buf,
 | 
			
		||||
								     item->transportLayerAddress->size));
 | 
			
		||||
		switch (item->transportLayerAddress->size) {
 | 
			
		||||
		case 7:
 | 
			
		||||
			/* It must be IPv4 inside a X213 NSAP */
 | 
			
		||||
			memcpy(pdp->lib->gsnlu.v, &item->transportLayerAddress->buf[3], 4);
 | 
			
		||||
			break;
 | 
			
		||||
		case 4:
 | 
			
		||||
			/* It must be a raw IPv4 address */
 | 
			
		||||
			memcpy(pdp->lib->gsnlu.v, item->transportLayerAddress->buf, 4);
 | 
			
		||||
			break;
 | 
			
		||||
		case 16:
 | 
			
		||||
			/* TODO: It must be a raw IPv6 address */
 | 
			
		||||
		case 19:
 | 
			
		||||
			/* TODO: It must be IPv6 inside a X213 NSAP */
 | 
			
		||||
		default:
 | 
			
		||||
			LOGP(DRANAP, LOGL_ERROR, "RAB Assignment Resp: Unknown "
 | 
			
		||||
				"transport layer address size %u\n",
 | 
			
		||||
				item->transportLayerAddress->size);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		require_pdp_update = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The TEI on the RNC side might have changed, too */
 | 
			
		||||
	if (item->iuTransportAssociation &&
 | 
			
		||||
	    item->iuTransportAssociation->present == RANAP_IuTransportAssociation_PR_gTP_TEI &&
 | 
			
		||||
	    item->iuTransportAssociation->choice.gTP_TEI.buf &&
 | 
			
		||||
	    item->iuTransportAssociation->choice.gTP_TEI.size >= 4) {
 | 
			
		||||
		uint32_t tei = osmo_load32be(item->iuTransportAssociation->choice.gTP_TEI.buf);
 | 
			
		||||
		LOGP(DRANAP, LOGL_DEBUG, "Updating TEID on RNC side from 0x%08x to 0x%08x\n",
 | 
			
		||||
			pdp->lib->teid_own, tei);
 | 
			
		||||
		pdp->lib->teid_own = tei;
 | 
			
		||||
		require_pdp_update = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (require_pdp_update)
 | 
			
		||||
		gtp_update_context(pdp->ggsn->gsn, pdp->lib, pdp, &pdp->lib->hisaddr0);
 | 
			
		||||
 | 
			
		||||
	if (pdp->state != PDP_STATE_CR_CONF) {
 | 
			
		||||
		send_act_pdp_cont_acc(pdp);
 | 
			
		||||
		pdp->state = PDP_STATE_CR_CONF;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_mm_ctx *mm;
 | 
			
		||||
	int rc = -1;
 | 
			
		||||
 | 
			
		||||
	mm = sgsn_mm_ctx_by_ue_ctx(ctx);
 | 
			
		||||
	if (!mm) {
 | 
			
		||||
		LOGIUP(ctx, LOGL_NOTICE, "Cannot find mm ctx for IU event %d\n", type);
 | 
			
		||||
		ranap_iu_free_ue(ctx);
 | 
			
		||||
		return rc;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case RANAP_IU_EVENT_RAB_ASSIGN:
 | 
			
		||||
		rc = sgsn_ranap_rab_ass_resp(mm, (RANAP_RAB_SetupOrModifiedItemIEs_t *)data);
 | 
			
		||||
		break;
 | 
			
		||||
	case RANAP_IU_EVENT_IU_RELEASE:
 | 
			
		||||
		/* fall thru */
 | 
			
		||||
	case RANAP_IU_EVENT_LINK_INVALIDATED:
 | 
			
		||||
		/* Clean up ranap_ue_conn_ctx here */
 | 
			
		||||
		LOGMMCTXP(LOGL_INFO, mm, "IU release for imsi %s\n", mm->imsi);
 | 
			
		||||
		if (mm->iu.mm_state_fsm->state == ST_PMM_CONNECTED)
 | 
			
		||||
			osmo_fsm_inst_dispatch(mm->iu.mm_state_fsm, E_PMM_PS_CONN_RELEASE, NULL);
 | 
			
		||||
		else
 | 
			
		||||
			sgsn_ranap_iu_free(mm);
 | 
			
		||||
 | 
			
		||||
		/* TODO: move this into FSM */
 | 
			
		||||
		if (mm->ran_type == MM_CTX_T_UTRAN_Iu && mm->gmm_att_req.fsm->state != ST_INIT)
 | 
			
		||||
			osmo_fsm_inst_dispatch(mm->gmm_att_req.fsm, E_REJECT, (void *) GMM_DISCARD_MS_WITHOUT_REJECT);
 | 
			
		||||
		rc = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	case RANAP_IU_EVENT_SECURITY_MODE_COMPLETE:
 | 
			
		||||
		/* Continue authentication here */
 | 
			
		||||
		mm->iu.ue_ctx->integrity_active = 1;
 | 
			
		||||
		ranap_iu_tx_common_id(mm->iu.ue_ctx, mm->imsi);
 | 
			
		||||
 | 
			
		||||
		/* FIXME: remove gmm_authorize */
 | 
			
		||||
		if (mm->pending_req != GSM48_MT_GMM_ATTACH_REQ)
 | 
			
		||||
			gsm48_gmm_authorize(mm);
 | 
			
		||||
		else
 | 
			
		||||
			osmo_fsm_inst_dispatch(mm->gmm_att_req.fsm, E_IU_SECURITY_CMD_COMPLETE, NULL);
 | 
			
		||||
		rc = 0;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOGMMCTXP(LOGL_NOTICE, mm, "Unknown event received: %i\n", type);
 | 
			
		||||
		rc = -1;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sgsn_ranap_iu_free(struct sgsn_mm_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	if (!ctx)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (!ctx->iu.ue_ctx)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	ranap_iu_free_ue(ctx->iu.ue_ctx);
 | 
			
		||||
	ctx->iu.ue_ctx = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sgsn_ranap_iu_release_free(struct sgsn_mm_ctx *ctx,
 | 
			
		||||
				const struct RANAP_Cause *cause)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long X1001;
 | 
			
		||||
 | 
			
		||||
	if (!ctx)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (!ctx->iu.ue_ctx)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	X1001 = osmo_tdef_get(sgsn->cfg.T_defs, -1001, OSMO_TDEF_S, -1);
 | 
			
		||||
 | 
			
		||||
	ranap_iu_tx_release_free(ctx->iu.ue_ctx,
 | 
			
		||||
				 cause,
 | 
			
		||||
				 (int) X1001);
 | 
			
		||||
	ctx->iu.ue_ctx = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg;
 | 
			
		||||
	struct sgsn_mm_ctx *mm = pdp->mm;
 | 
			
		||||
	struct ranap_ue_conn_ctx *uectx;
 | 
			
		||||
	uint32_t ggsn_ip;
 | 
			
		||||
	bool use_x213_nsap;
 | 
			
		||||
 | 
			
		||||
	uectx = mm->iu.ue_ctx;
 | 
			
		||||
	use_x213_nsap = (uectx->rab_assign_addr_enc == RANAP_NSAP_ADDR_ENC_X213);
 | 
			
		||||
 | 
			
		||||
	/* Get the IP address for ggsn user plane */
 | 
			
		||||
	memcpy(&ggsn_ip, pdp->lib->gsnru.v, pdp->lib->gsnru.l);
 | 
			
		||||
	ggsn_ip = htonl(ggsn_ip);
 | 
			
		||||
 | 
			
		||||
	LOGP(DRANAP, LOGL_DEBUG, "Assigning RAB: rab_id=%d, ggsn_ip=%x,"
 | 
			
		||||
	     " teid_gn=%x, use_x213_nsap=%d\n",
 | 
			
		||||
	     rab_id, ggsn_ip, pdp->lib->teid_gn, use_x213_nsap);
 | 
			
		||||
 | 
			
		||||
	msg = ranap_new_msg_rab_assign_data(rab_id, ggsn_ip,
 | 
			
		||||
					    pdp->lib->teid_gn, use_x213_nsap);
 | 
			
		||||
	msg->l2h = msg->data;
 | 
			
		||||
	return ranap_iu_rab_act(uectx, msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Main entry point for incoming 04.08 GPRS messages from Iu */
 | 
			
		||||
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id,
 | 
			
		||||
			   uint16_t *sai)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
 | 
			
		||||
	uint8_t pdisc = gsm48_hdr_pdisc(gh);
 | 
			
		||||
	struct sgsn_mm_ctx *mmctx;
 | 
			
		||||
	int rc = -EINVAL;
 | 
			
		||||
 | 
			
		||||
	mmctx = sgsn_mm_ctx_by_ue_ctx(MSG_IU_UE_CTX(msg));
 | 
			
		||||
	if (mmctx) {
 | 
			
		||||
		rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
 | 
			
		||||
		if (ra_id)
 | 
			
		||||
			memcpy(&mmctx->ra, ra_id, sizeof(mmctx->ra));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* MMCTX can be NULL */
 | 
			
		||||
 | 
			
		||||
	switch (pdisc) {
 | 
			
		||||
	case GSM48_PDISC_MM_GPRS:
 | 
			
		||||
		rc = gsm0408_rcv_gmm(mmctx, msg, NULL, false);
 | 
			
		||||
#pragma message "set drop_cipherable arg for gsm0408_rcv_gmm() from IuPS?"
 | 
			
		||||
		break;
 | 
			
		||||
	case GSM48_PDISC_SM_GPRS:
 | 
			
		||||
		rc = gsm0408_rcv_gsm(mmctx, msg, NULL);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOGMMCTXP(LOGL_NOTICE, mmctx,
 | 
			
		||||
			"Unknown GSM 04.08 discriminator 0x%02x: %s\n",
 | 
			
		||||
			pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
 | 
			
		||||
		/* FIXME: return status message */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* MMCTX can be invalid */
 | 
			
		||||
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
@@ -39,9 +39,13 @@
 | 
			
		||||
#include <osmocom/sgsn/gprs_sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_utils.h>
 | 
			
		||||
#include <osmocom/sgsn/signal.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm_attach.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_mm_state_iu_fsm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_llc.h>
 | 
			
		||||
 | 
			
		||||
#include <pdp.h>
 | 
			
		||||
@@ -50,10 +54,6 @@
 | 
			
		||||
 | 
			
		||||
#include "../../bscconfig.h"
 | 
			
		||||
 | 
			
		||||
#if BUILD_IU
 | 
			
		||||
#include <osmocom/ranap/iu_client.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define GPRS_LLME_CHECK_TICK 30
 | 
			
		||||
 | 
			
		||||
extern struct sgsn_instance *sgsn;
 | 
			
		||||
@@ -64,6 +64,15 @@ LLIST_HEAD(sgsn_ggsn_ctxts);
 | 
			
		||||
LLIST_HEAD(sgsn_apn_ctxts);
 | 
			
		||||
LLIST_HEAD(sgsn_pdp_ctxts);
 | 
			
		||||
 | 
			
		||||
const struct value_string sgsn_ran_type_names[] = {
 | 
			
		||||
	{ MM_CTX_T_GERAN_Gb, "GPRS/EDGE via Gb" },
 | 
			
		||||
	{ MM_CTX_T_UTRAN_Iu, "UMTS via Iu" },
 | 
			
		||||
#if 0
 | 
			
		||||
	{ MM_CTX_T_GERAN_Iu, "GPRS/EDGE via Iu" },
 | 
			
		||||
#endif
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct rate_ctr_desc mmctx_ctr_description[] = {
 | 
			
		||||
	{ "sign:packets:in",	"Signalling Messages ( In)" },
 | 
			
		||||
	{ "sign:packets:out",	"Signalling Messages (Out)" },
 | 
			
		||||
@@ -103,9 +112,9 @@ static const struct rate_ctr_group_desc pdpctx_ctrg_desc = {
 | 
			
		||||
 | 
			
		||||
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)" },
 | 
			
		||||
	{ "llc:ul_bytes", "Count successful received LLC bytes (encrypt & fcs correct)" },
 | 
			
		||||
	{ "llc:dl_packets", "Count successful sent LLC packets before giving it to the bssgp layer" },
 | 
			
		||||
	{ "llc:ul_packets", "Count successful received LLC packets (encrypt & fcs correct)" },
 | 
			
		||||
	{ "gprs:attach_requested", "Received attach requests" },
 | 
			
		||||
	{ "gprs:attach_accepted", "Sent attach accepts" },
 | 
			
		||||
	{ "gprs:attach_rejected", "Sent attach rejects" },
 | 
			
		||||
@@ -218,72 +227,99 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Allocate a new SGSN MM context, generic part */
 | 
			
		||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t rate_ctr_id)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_mm_ctx *ctx;
 | 
			
		||||
 | 
			
		||||
	ctx = talloc_zero(tall_sgsn_ctx, struct sgsn_mm_ctx);
 | 
			
		||||
	if (!ctx)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
 | 
			
		||||
	ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, rate_ctr_id);
 | 
			
		||||
	if (!ctx->ctrg) {
 | 
			
		||||
		LOGMMCTXP(LOGL_ERROR, ctx, "Cannot allocate counter group\n");
 | 
			
		||||
		talloc_free(ctx);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx->gmm_fsm = osmo_fsm_inst_alloc(&gmm_fsm, ctx, ctx, LOGL_DEBUG, "gmm_fsm");
 | 
			
		||||
	if (!ctx->gmm_fsm)
 | 
			
		||||
		goto out;
 | 
			
		||||
	ctx->gmm_att_req.fsm = osmo_fsm_inst_alloc(&gmm_attach_req_fsm, ctx, ctx, LOGL_DEBUG, "gb_gmm_req");
 | 
			
		||||
	if (!ctx->gmm_att_req.fsm)
 | 
			
		||||
		goto out;
 | 
			
		||||
	ctx->gb.mm_state_fsm = osmo_fsm_inst_alloc(&mm_state_gb_fsm, ctx, ctx, LOGL_DEBUG, NULL);
 | 
			
		||||
	if (!ctx->gb.mm_state_fsm)
 | 
			
		||||
		goto out;
 | 
			
		||||
#ifdef BUILD_IU
 | 
			
		||||
	ctx->iu.mm_state_fsm = osmo_fsm_inst_alloc(&mm_state_iu_fsm, ctx, ctx, LOGL_DEBUG, NULL);
 | 
			
		||||
	if (!ctx->iu.mm_state_fsm)
 | 
			
		||||
		goto out;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	INIT_LLIST_HEAD(&ctx->pdp_list);
 | 
			
		||||
 | 
			
		||||
	llist_add(&ctx->list, &sgsn_mm_ctxts);
 | 
			
		||||
 | 
			
		||||
	return ctx;
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	if (ctx->iu.mm_state_fsm)
 | 
			
		||||
		osmo_fsm_inst_free(ctx->iu.mm_state_fsm);
 | 
			
		||||
	if (ctx->gb.mm_state_fsm)
 | 
			
		||||
		osmo_fsm_inst_free(ctx->gb.mm_state_fsm);
 | 
			
		||||
	if (ctx->gmm_att_req.fsm)
 | 
			
		||||
		osmo_fsm_inst_free(ctx->gmm_att_req.fsm);
 | 
			
		||||
	if (ctx->gmm_fsm)
 | 
			
		||||
		osmo_fsm_inst_free(ctx->gmm_fsm);
 | 
			
		||||
 | 
			
		||||
	rate_ctr_group_free(ctx->ctrg);
 | 
			
		||||
	talloc_free(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);
 | 
			
		||||
	ctx = sgsn_mm_ctx_alloc(tlli);
 | 
			
		||||
	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;
 | 
			
		||||
	osmo_fsm_inst_update_id_f(ctx->gb.mm_state_fsm, "%" PRIu32, tlli);
 | 
			
		||||
 | 
			
		||||
	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 */
 | 
			
		||||
/* Allocate a new SGSN MM context for UTRAN_Iu */
 | 
			
		||||
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);
 | 
			
		||||
	ctx = sgsn_mm_ctx_alloc(ue_ctx->conn_id);
 | 
			
		||||
	if (!ctx)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	/* Need to get RAID from IU conn */
 | 
			
		||||
	ctx->ra = ue_ctx->ra_id;
 | 
			
		||||
	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");
 | 
			
		||||
	osmo_fsm_inst_update_id_f(ctx->iu.mm_state_fsm, "%" PRIu32, ue_ctx->conn_id);
 | 
			
		||||
 | 
			
		||||
	/* 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
 | 
			
		||||
@@ -313,7 +349,6 @@ static void sgsn_mm_ctx_free(struct sgsn_mm_ctx *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;
 | 
			
		||||
 | 
			
		||||
@@ -356,13 +391,20 @@ void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *mm)
 | 
			
		||||
 | 
			
		||||
	if (mm->gmm_att_req.fsm)
 | 
			
		||||
		gmm_att_req_free(mm);
 | 
			
		||||
	if (mm->gb.mm_state_fsm)
 | 
			
		||||
		osmo_fsm_inst_free(mm->gb.mm_state_fsm);
 | 
			
		||||
	if (mm->iu.mm_state_fsm)
 | 
			
		||||
		osmo_fsm_inst_free(mm->iu.mm_state_fsm);
 | 
			
		||||
	if (mm->gmm_fsm)
 | 
			
		||||
		osmo_fsm_inst_free(mm->gmm_fsm);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
		if (gprs_llgmm_unassign(llme) < 0)
 | 
			
		||||
			LOGMMCTXP(LOGL_ERROR, mm, "gprs_llgmm_unassign failed, llme not freed!\n");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -442,6 +484,7 @@ void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp)
 | 
			
		||||
 | 
			
		||||
	if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
 | 
			
		||||
		/* Force the deactivation of the SNDCP layer */
 | 
			
		||||
		if (pdp->mm->gb.llme)
 | 
			
		||||
			sndcp_sm_deactivate_ind(&pdp->mm->gb.llme->lle[pdp->sapi], pdp->nsapi);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -492,12 +535,15 @@ void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *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))
 | 
			
		||||
	bool pending = osmo_timer_pending(&ggc->echo_timer);
 | 
			
		||||
 | 
			
		||||
	/* Only enable if allowed by policy and at least 1 pdp ctx exists against ggsn */
 | 
			
		||||
	if (!llist_empty(&ggc->pdp_list) && ggc->echo_interval) {
 | 
			
		||||
		if (!pending)
 | 
			
		||||
			osmo_timer_schedule(&ggc->echo_timer, ggc->echo_interval, 0);
 | 
			
		||||
	} else {
 | 
			
		||||
		if (pending)
 | 
			
		||||
			osmo_timer_del(&ggc->echo_timer);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -520,7 +566,6 @@ struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id)
 | 
			
		||||
	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);
 | 
			
		||||
@@ -689,12 +734,12 @@ restart:
 | 
			
		||||
	 * 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 (ptmsi >= GSM23003_TMSI_SGSN_MASK) {
 | 
			
		||||
		if (!max_retries--)
 | 
			
		||||
			goto failed;
 | 
			
		||||
		goto restart;
 | 
			
		||||
	}
 | 
			
		||||
	ptmsi |= 0xC0000000;
 | 
			
		||||
	ptmsi |= GSM23003_TMSI_SGSN_MASK;
 | 
			
		||||
 | 
			
		||||
	if (ptmsi == GSM_RESERVED_TMSI) {
 | 
			
		||||
		if (!max_retries--)
 | 
			
		||||
@@ -721,7 +766,7 @@ 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) {
 | 
			
		||||
	if (pctx->mm && pctx->mm->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL) {
 | 
			
		||||
		gsm48_tx_gsm_deact_pdp_req(pctx, GSM_CAUSE_NET_FAIL, true);
 | 
			
		||||
		sgsn_ggsn_ctx_remove_pdp(pctx->ggsn, pctx);
 | 
			
		||||
	} else  {
 | 
			
		||||
@@ -752,11 +797,15 @@ int sgsn_ggsn_ctx_drop_all_pdp_except(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pd
 | 
			
		||||
	return num;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn)
 | 
			
		||||
{
 | 
			
		||||
	return sgsn_ggsn_ctx_drop_all_pdp_except(ggsn, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sgsn_ggsn_ctx_add_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
 | 
			
		||||
{
 | 
			
		||||
	sgsn_ggsn_ctx_check_echo_timer(ggc);
 | 
			
		||||
 | 
			
		||||
	llist_add(&pdp->ggsn_list, &ggc->pdp_list);
 | 
			
		||||
	sgsn_ggsn_ctx_check_echo_timer(ggc);
 | 
			
		||||
}
 | 
			
		||||
void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pdp)
 | 
			
		||||
{
 | 
			
		||||
@@ -918,6 +967,7 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
 | 
			
		||||
		LOGMMCTXP(LOGL_NOTICE, mmctx,
 | 
			
		||||
			"No static GGSN configured. Selected APN '%s'\n",
 | 
			
		||||
			selected_apn_str);
 | 
			
		||||
		*gsm_cause = GSM_CAUSE_MISSING_APN;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -985,6 +1035,7 @@ struct sgsn_instance *sgsn_instance_alloc(void *talloc_ctx)
 | 
			
		||||
	inst = talloc_zero(talloc_ctx, struct sgsn_instance);
 | 
			
		||||
	inst->cfg.gtp_statedir = talloc_strdup(inst, "./");
 | 
			
		||||
	inst->cfg.auth_policy = SGSN_AUTH_POLICY_CLOSED;
 | 
			
		||||
	inst->cfg.require_authentication = true; /* only applies if auth_policy is REMOTE */
 | 
			
		||||
	inst->cfg.gsup_server_port = OSMO_GSUP_PORT;
 | 
			
		||||
	return inst;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										754
									
								
								src/sgsn/gprs_sm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										754
									
								
								src/sgsn/gprs_sm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,754 @@
 | 
			
		||||
/* Section "9.5 GPRS Session Management Messages"
 | 
			
		||||
 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
 | 
			
		||||
 | 
			
		||||
/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org>
 | 
			
		||||
 * (C) 2010 by On-Waves
 | 
			
		||||
 * (C) 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
			
		||||
 *
 | 
			
		||||
 * All Rights Reserved
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Affero General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
 | 
			
		||||
#include "bscconfig.h"
 | 
			
		||||
 | 
			
		||||
#include <osmocom/core/rate_ctr.h>
 | 
			
		||||
#include <osmocom/core/tdef.h>
 | 
			
		||||
#include <osmocom/gsm/apn.h>
 | 
			
		||||
#include <osmocom/gprs/gprs_bssgp.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/gprs_sm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_utils.h>
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/debug.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_llc.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sndcp.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_ranap.h>
 | 
			
		||||
 | 
			
		||||
extern void *tall_sgsn_ctx;
 | 
			
		||||
 | 
			
		||||
/* 3GPP TS 04.08 sec 6.1.3.4.3(.a) "Abnormal cases" */
 | 
			
		||||
#define T339X_MAX_RETRANS 4
 | 
			
		||||
 | 
			
		||||
static const struct tlv_definition gsm48_sm_att_tlvdef = {
 | 
			
		||||
	.def = {
 | 
			
		||||
		[GSM48_IE_GSM_APN]		= { TLV_TYPE_TLV, 0 },
 | 
			
		||||
		[GSM48_IE_GSM_PROTO_CONF_OPT]	= { TLV_TYPE_TLV, 0 },
 | 
			
		||||
		[GSM48_IE_GSM_PDP_ADDR]		= { TLV_TYPE_TLV, 0 },
 | 
			
		||||
		[GSM48_IE_GSM_AA_TMR]		= { TLV_TYPE_TV, 1 },
 | 
			
		||||
		[GSM48_IE_GSM_NAME_FULL]	= { TLV_TYPE_TLV, 0 },
 | 
			
		||||
		[GSM48_IE_GSM_NAME_SHORT]	= { TLV_TYPE_TLV, 0 },
 | 
			
		||||
		[GSM48_IE_GSM_TIMEZONE]		= { TLV_TYPE_FIXED, 1 },
 | 
			
		||||
		[GSM48_IE_GSM_UTC_AND_TZ]	= { TLV_TYPE_FIXED, 7 },
 | 
			
		||||
		[GSM48_IE_GSM_LSA_ID]		= { TLV_TYPE_TLV, 0 },
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct gsm48_qos default_qos = {
 | 
			
		||||
	.delay_class = 4,	/* best effort */
 | 
			
		||||
	.reliab_class = GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT,
 | 
			
		||||
	.peak_tput = GSM48_QOS_PEAK_TPUT_32000bps,
 | 
			
		||||
	.preced_class = GSM48_QOS_PC_NORMAL,
 | 
			
		||||
	.mean_tput = GSM48_QOS_MEAN_TPUT_BEST_EFFORT,
 | 
			
		||||
	.traf_class = GSM48_QOS_TC_INTERACTIVE,
 | 
			
		||||
	.deliv_order = GSM48_QOS_DO_UNORDERED,
 | 
			
		||||
	.deliv_err_sdu = GSM48_QOS_ERRSDU_YES,
 | 
			
		||||
	.max_sdu_size = GSM48_QOS_MAXSDU_1520,
 | 
			
		||||
	.max_bitrate_up = GSM48_QOS_MBRATE_63k,
 | 
			
		||||
	.max_bitrate_down = GSM48_QOS_MBRATE_63k,
 | 
			
		||||
	.resid_ber = GSM48_QOS_RBER_5e_2,
 | 
			
		||||
	.sdu_err_ratio = GSM48_QOS_SERR_1e_2,
 | 
			
		||||
	.handling_prio = 3,
 | 
			
		||||
	.xfer_delay = 0x10,	/* 200ms */
 | 
			
		||||
	.guar_bitrate_up = GSM48_QOS_MBRATE_0k,
 | 
			
		||||
	.guar_bitrate_down = GSM48_QOS_MBRATE_0k,
 | 
			
		||||
	.sig_ind = 0,	/* not optimised for signalling */
 | 
			
		||||
	.max_bitrate_down_ext = 0,	/* use octet 9 */
 | 
			
		||||
	.guar_bitrate_down_ext = 0,	/* use octet 13 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* GPRS SESSION MANAGEMENT */
 | 
			
		||||
 | 
			
		||||
static void pdpctx_timer_cb(void *_mm);
 | 
			
		||||
 | 
			
		||||
static void pdpctx_timer_rearm(struct sgsn_pdp_ctx *pdp, unsigned int T)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long seconds;
 | 
			
		||||
	if (osmo_timer_pending(&pdp->timer))
 | 
			
		||||
		LOGPDPCTXP(LOGL_ERROR, pdp, "Scheduling PDP timer %u while old "
 | 
			
		||||
			"timer %u pending\n", T, pdp->T);
 | 
			
		||||
	seconds = osmo_tdef_get(sgsn->cfg.T_defs, T, OSMO_TDEF_S, -1);
 | 
			
		||||
	osmo_timer_schedule(&pdp->timer, seconds, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pdpctx_timer_start(struct sgsn_pdp_ctx *pdp, unsigned int T)
 | 
			
		||||
{
 | 
			
		||||
	if (osmo_timer_pending(&pdp->timer))
 | 
			
		||||
		LOGPDPCTXP(LOGL_ERROR, pdp, "Starting PDP timer %u while old "
 | 
			
		||||
			"timer %u pending\n", T, pdp->T);
 | 
			
		||||
	pdp->T = T;
 | 
			
		||||
	pdp->num_T_exp = 0;
 | 
			
		||||
 | 
			
		||||
	osmo_timer_setup(&pdp->timer, pdpctx_timer_cb, pdp);
 | 
			
		||||
	pdpctx_timer_rearm(pdp, pdp->T);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pdpctx_timer_stop(struct sgsn_pdp_ctx *pdp, unsigned int T)
 | 
			
		||||
{
 | 
			
		||||
	if (pdp->T != T)
 | 
			
		||||
		LOGPDPCTXP(LOGL_ERROR, pdp, "Stopping PDP timer %u but "
 | 
			
		||||
			"%u is running\n", T, pdp->T);
 | 
			
		||||
	osmo_timer_del(&pdp->timer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pdp_ctx_detach_mm_ctx(struct sgsn_pdp_ctx *pdp)
 | 
			
		||||
{
 | 
			
		||||
	/* Detach from MM context */
 | 
			
		||||
	llist_del(&pdp->list);
 | 
			
		||||
	pdp->mm = NULL;
 | 
			
		||||
 | 
			
		||||
	/* stop timer 3395 */
 | 
			
		||||
	pdpctx_timer_stop(pdp, 3395);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static void msgb_put_pdp_addr_ipv4(struct msgb *msg, uint32_t ipaddr)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t v[6];
 | 
			
		||||
 | 
			
		||||
	v[0] = PDP_TYPE_ORG_IETF;
 | 
			
		||||
	v[1] = PDP_TYPE_N_IETF_IPv4;
 | 
			
		||||
	*(uint32_t *)(v+2) = htonl(ipaddr);
 | 
			
		||||
 | 
			
		||||
	msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void msgb_put_pdp_addr_ppp(struct msgb *msg)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t v[2];
 | 
			
		||||
 | 
			
		||||
	v[0] = PDP_TYPE_ORG_ETSI;
 | 
			
		||||
	v[1] = PDP_TYPE_N_ETSI_PPP;
 | 
			
		||||
 | 
			
		||||
	msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Chapter 9.4.18 */
 | 
			
		||||
static int _tx_status(struct msgb *msg, uint8_t cause,
 | 
			
		||||
		      struct sgsn_mm_ctx *mmctx)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm48_hdr *gh;
 | 
			
		||||
 | 
			
		||||
	/* MMCTX might be NULL! */
 | 
			
		||||
 | 
			
		||||
	DEBUGP(DMM, "<- GPRS MM STATUS (cause: %s)\n",
 | 
			
		||||
		get_value_string(gsm48_gmm_cause_names, cause));
 | 
			
		||||
 | 
			
		||||
	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
 | 
			
		||||
	gh->proto_discr = GSM48_PDISC_SM_GPRS;
 | 
			
		||||
	gh->msg_type = GSM48_MT_GSM_STATUS;
 | 
			
		||||
	gh->data[0] = cause;
 | 
			
		||||
 | 
			
		||||
	return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int gsm48_tx_sm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SM STATUS");
 | 
			
		||||
 | 
			
		||||
	mmctx2msgid(msg, mmctx);
 | 
			
		||||
	return _tx_status(msg, cause, mmctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 3GPP TS 24.008 § 9.5.2: Activate PDP Context Accept */
 | 
			
		||||
int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP ACC");
 | 
			
		||||
	struct gsm48_hdr *gh;
 | 
			
		||||
	uint8_t transaction_id = pdp->ti ^ 0x8; /* flip */
 | 
			
		||||
 | 
			
		||||
	LOGPDPCTXP(LOGL_INFO, pdp, "<- ACTIVATE PDP CONTEXT ACK\n");
 | 
			
		||||
	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_ACCEPT]);
 | 
			
		||||
 | 
			
		||||
	mmctx2msgid(msg, pdp->mm);
 | 
			
		||||
 | 
			
		||||
	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 | 
			
		||||
	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
 | 
			
		||||
	gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK;
 | 
			
		||||
 | 
			
		||||
	/* Negotiated LLC SAPI */
 | 
			
		||||
	msgb_v_put(msg, pdp->sapi);
 | 
			
		||||
 | 
			
		||||
	/* FIXME: copy QoS parameters from original request */
 | 
			
		||||
	//msgb_lv_put(msg, pdp->lib->qos_neg.l, pdp->lib->qos_neg.v);
 | 
			
		||||
	msgb_lv_put(msg, sizeof(default_qos), (uint8_t *)&default_qos);
 | 
			
		||||
 | 
			
		||||
	/* Radio priority 10.5.7.2 */
 | 
			
		||||
	msgb_v_put(msg, pdp->lib->radio_pri);
 | 
			
		||||
 | 
			
		||||
	/* PDP address */
 | 
			
		||||
	/* Highest 4 bits of first byte need to be set to 1, otherwise
 | 
			
		||||
	 * the IE is identical with the 04.08 PDP Address IE */
 | 
			
		||||
	pdp->lib->eua.v[0] &= ~0xf0;
 | 
			
		||||
	msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR,
 | 
			
		||||
		     pdp->lib->eua.l, pdp->lib->eua.v);
 | 
			
		||||
	pdp->lib->eua.v[0] |= 0xf0;
 | 
			
		||||
 | 
			
		||||
	/* Optional: Protocol configuration options (FIXME: why 'req') */
 | 
			
		||||
	if (pdp->lib->pco_req.l)
 | 
			
		||||
		msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT,
 | 
			
		||||
			     pdp->lib->pco_req.l, pdp->lib->pco_req.v);
 | 
			
		||||
 | 
			
		||||
	/* Optional: Packet Flow Identifier */
 | 
			
		||||
 | 
			
		||||
	return gsm48_gmm_sendmsg(msg, 0, pdp->mm, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 3GPP TS 24.008 § 9.5.3: Activate PDP Context reject */
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP REJ");
 | 
			
		||||
	struct gsm48_hdr *gh;
 | 
			
		||||
	uint8_t transaction_id = tid ^ 0x8; /* flip */
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_NOTICE, mm, "<- ACTIVATE PDP CONTEXT REJ: %s\n",
 | 
			
		||||
		  get_value_string(gsm48_gsm_cause_names, cause));
 | 
			
		||||
	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_REJECT]);
 | 
			
		||||
 | 
			
		||||
	mmctx2msgid(msg, mm);
 | 
			
		||||
 | 
			
		||||
	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 | 
			
		||||
	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
 | 
			
		||||
	gh->msg_type = GSM48_MT_GSM_ACT_PDP_REJ;
 | 
			
		||||
 | 
			
		||||
	msgb_v_put(msg, cause);
 | 
			
		||||
	if (pco_len && pco_v)
 | 
			
		||||
		msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT, pco_len, pco_v);
 | 
			
		||||
 | 
			
		||||
	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 3GPP TS 24.008 § 9.5.8: Deactivate PDP Context Request */
 | 
			
		||||
static int _gsm48_tx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, uint8_t tid,
 | 
			
		||||
					uint8_t sm_cause, bool teardown)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP DET REQ");
 | 
			
		||||
	struct gsm48_hdr *gh;
 | 
			
		||||
	uint8_t transaction_id = tid ^ 0x8; /* flip */
 | 
			
		||||
	uint8_t tear_down_ind = (0x9 << 4) | (!!teardown);
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_INFO, mm, "<- DEACTIVATE PDP CONTEXT REQ\n");
 | 
			
		||||
	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_DL_DEACTIVATE_REQUEST]);
 | 
			
		||||
 | 
			
		||||
	mmctx2msgid(msg, mm);
 | 
			
		||||
 | 
			
		||||
	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 | 
			
		||||
	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
 | 
			
		||||
	gh->msg_type = GSM48_MT_GSM_DEACT_PDP_REQ;
 | 
			
		||||
 | 
			
		||||
	msgb_v_put(msg, sm_cause);
 | 
			
		||||
	msgb_v_put(msg, tear_down_ind);
 | 
			
		||||
 | 
			
		||||
	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 | 
			
		||||
}
 | 
			
		||||
int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause, bool teardown)
 | 
			
		||||
{
 | 
			
		||||
	pdpctx_timer_start(pdp, 3395);
 | 
			
		||||
 | 
			
		||||
	return _gsm48_tx_gsm_deact_pdp_req(pdp->mm, pdp->ti, sm_cause, teardown);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 3GPP TS 24.008 § 9.5.9: Deactivate PDP Context Accept */
 | 
			
		||||
static int _gsm48_tx_gsm_deact_pdp_acc(struct sgsn_mm_ctx *mm, uint8_t tid)
 | 
			
		||||
{
 | 
			
		||||
	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP DET ACC");
 | 
			
		||||
	struct gsm48_hdr *gh;
 | 
			
		||||
	uint8_t transaction_id = tid ^ 0x8; /* flip */
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_INFO, mm, "<- DEACTIVATE PDP CONTEXT ACK\n");
 | 
			
		||||
	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_DL_DEACTIVATE_ACCEPT]);
 | 
			
		||||
 | 
			
		||||
	mmctx2msgid(msg, mm);
 | 
			
		||||
 | 
			
		||||
	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
 | 
			
		||||
	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
 | 
			
		||||
	gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
 | 
			
		||||
 | 
			
		||||
	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 | 
			
		||||
}
 | 
			
		||||
int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp)
 | 
			
		||||
{
 | 
			
		||||
	return _gsm48_tx_gsm_deact_pdp_acc(pdp->mm, pdp->ti);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int activate_ggsn(struct sgsn_mm_ctx *mmctx,
 | 
			
		||||
		struct sgsn_ggsn_ctx *ggsn, const uint8_t transaction_id,
 | 
			
		||||
		const uint8_t req_nsapi, const uint8_t req_llc_sapi,
 | 
			
		||||
		struct tlv_parsed *tp, int destroy_ggsn)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp;
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_DEBUG, mmctx, "Using GGSN %u\n", ggsn->id);
 | 
			
		||||
	ggsn->gsn = sgsn->gsn;
 | 
			
		||||
	pdp = sgsn_create_pdp_ctx(ggsn, mmctx, req_nsapi, tp);
 | 
			
		||||
	if (!pdp)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	/* Store SAPI and Transaction Identifier */
 | 
			
		||||
	pdp->sapi = req_llc_sapi;
 | 
			
		||||
	pdp->ti = transaction_id;
 | 
			
		||||
	pdp->destroy_ggsn = destroy_ggsn;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ggsn_lookup_cb(void *arg, int status, int timeouts, struct hostent *hostent)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_ggsn_ctx *ggsn;
 | 
			
		||||
	struct sgsn_ggsn_lookup *lookup = arg;
 | 
			
		||||
	struct in_addr *addr = NULL;
 | 
			
		||||
	char buf[INET_ADDRSTRLEN];
 | 
			
		||||
 | 
			
		||||
	/* The context is gone while we made a request */
 | 
			
		||||
	if (!lookup->mmctx) {
 | 
			
		||||
		talloc_free(lookup->orig_msg);
 | 
			
		||||
		talloc_free(lookup);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (status != ARES_SUCCESS) {
 | 
			
		||||
		struct sgsn_mm_ctx *mmctx = lookup->mmctx;
 | 
			
		||||
 | 
			
		||||
		LOGMMCTXP(LOGL_ERROR, mmctx, "DNS query failed.\n");
 | 
			
		||||
 | 
			
		||||
		/* Need to try with three digits now */
 | 
			
		||||
		if (lookup->state == SGSN_GGSN_2DIGIT) {
 | 
			
		||||
			char *hostname;
 | 
			
		||||
			int rc;
 | 
			
		||||
 | 
			
		||||
			lookup->state = SGSN_GGSN_3DIGIT;
 | 
			
		||||
			hostname = osmo_apn_qualify_from_imsi(mmctx->imsi,
 | 
			
		||||
					lookup->apn_str, 1);
 | 
			
		||||
			LOGMMCTXP(LOGL_DEBUG, mmctx,
 | 
			
		||||
				"Going to query %s\n", hostname);
 | 
			
		||||
			rc = sgsn_ares_query(sgsn, hostname,
 | 
			
		||||
					ggsn_lookup_cb, lookup);
 | 
			
		||||
			if (rc != 0) {
 | 
			
		||||
				LOGMMCTXP(LOGL_ERROR, mmctx, "Couldn't start GGSN\n");
 | 
			
		||||
				goto reject_due_failure;
 | 
			
		||||
			}
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		LOGMMCTXP(LOGL_ERROR, mmctx, "Couldn't resolve GGSN\n");
 | 
			
		||||
		goto reject_due_failure;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (hostent->h_length != sizeof(struct in_addr)) {
 | 
			
		||||
		LOGMMCTXP(LOGL_ERROR, lookup->mmctx,
 | 
			
		||||
			"Wrong addr size(%zu)\n", sizeof(struct in_addr));
 | 
			
		||||
		goto reject_due_failure;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get the first addr from the list */
 | 
			
		||||
	addr = (struct in_addr *) hostent->h_addr_list[0];
 | 
			
		||||
	if (!addr) {
 | 
			
		||||
		LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "No host address.\n");
 | 
			
		||||
		goto reject_due_failure;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ggsn = sgsn_ggsn_ctx_alloc(UINT32_MAX);
 | 
			
		||||
	if (!ggsn) {
 | 
			
		||||
		LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "Failed to create ggsn.\n");
 | 
			
		||||
		goto reject_due_failure;
 | 
			
		||||
	}
 | 
			
		||||
	ggsn->remote_addr = *addr;
 | 
			
		||||
	LOGMMCTXP(LOGL_NOTICE, lookup->mmctx,
 | 
			
		||||
		  "Selected %s as GGSN.\n",
 | 
			
		||||
		  inet_ntop(AF_INET, addr, buf, sizeof(buf)));
 | 
			
		||||
 | 
			
		||||
	/* forget about the ggsn look-up */
 | 
			
		||||
	lookup->mmctx->ggsn_lookup = NULL;
 | 
			
		||||
 | 
			
		||||
	activate_ggsn(lookup->mmctx, ggsn, lookup->ti, lookup->nsapi,
 | 
			
		||||
			lookup->sapi, &lookup->tp, 1);
 | 
			
		||||
 | 
			
		||||
	/* Now free it */
 | 
			
		||||
	talloc_free(lookup->orig_msg);
 | 
			
		||||
	talloc_free(lookup);
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
reject_due_failure:
 | 
			
		||||
	gsm48_tx_gsm_act_pdp_rej(lookup->mmctx, lookup->ti,
 | 
			
		||||
				GMM_CAUSE_NET_FAIL, 0, NULL);
 | 
			
		||||
	lookup->mmctx->ggsn_lookup = NULL;
 | 
			
		||||
	talloc_free(lookup->orig_msg);
 | 
			
		||||
	talloc_free(lookup);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_act_pdp_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg, bool *delete)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
 | 
			
		||||
	struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data;
 | 
			
		||||
	uint8_t req_qos_len, req_pdpa_len;
 | 
			
		||||
	uint8_t *req_qos, *req_pdpa;
 | 
			
		||||
	struct tlv_parsed tp;
 | 
			
		||||
	uint8_t transaction_id = gsm48_hdr_trans_id(gh);
 | 
			
		||||
	struct sgsn_ggsn_ctx *ggsn;
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp;
 | 
			
		||||
	enum gsm48_gsm_cause gsm_cause;
 | 
			
		||||
	char apn_str[GSM_APN_LENGTH] = { 0, };
 | 
			
		||||
	char *hostname;
 | 
			
		||||
	int rc;
 | 
			
		||||
	struct gprs_llc_lle *lle;
 | 
			
		||||
	char buf[INET_ADDRSTRLEN];
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_INFO, mmctx, "-> ACTIVATE PDP CONTEXT REQ: SAPI=%u NSAPI=%u ",
 | 
			
		||||
		act_req->req_llc_sapi, act_req->req_nsapi);
 | 
			
		||||
 | 
			
		||||
	/* FIXME: length checks! */
 | 
			
		||||
	req_qos_len = act_req->data[0];
 | 
			
		||||
	req_qos = act_req->data + 1;	/* 10.5.6.5 */
 | 
			
		||||
	req_pdpa_len = act_req->data[1 + req_qos_len];
 | 
			
		||||
	req_pdpa = act_req->data + 1 + req_qos_len + 1;	/* 10.5.6.4 */
 | 
			
		||||
 | 
			
		||||
	switch (req_pdpa[0] & 0xf) {
 | 
			
		||||
	case 0x0:
 | 
			
		||||
		DEBUGPC(DMM, "ETSI ");
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x1:
 | 
			
		||||
		DEBUGPC(DMM, "IETF ");
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xf:
 | 
			
		||||
		DEBUGPC(DMM, "Empty ");
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (req_pdpa[1]) {
 | 
			
		||||
	case 0x21:
 | 
			
		||||
		DEBUGPC(DMM, "IPv4 ");
 | 
			
		||||
		if (req_pdpa_len >= 6) {
 | 
			
		||||
			struct in_addr ia;
 | 
			
		||||
			ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2)));
 | 
			
		||||
			DEBUGPC(DMM, "%s ", inet_ntop(AF_INET, &ia, buf, sizeof(buf)));
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x57:
 | 
			
		||||
		DEBUGPC(DMM, "IPv6 ");
 | 
			
		||||
		if (req_pdpa_len >= 18) {
 | 
			
		||||
			/* FIXME: print IPv6 address */
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		DEBUGPC(DMM, "0x%02x ", req_pdpa[1]);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LOGPC(DMM, LOGL_INFO, "\n");
 | 
			
		||||
 | 
			
		||||
	/* Check if NSAPI is out of range (TS 04.65 / 7.2) */
 | 
			
		||||
	if (act_req->req_nsapi < 5 || act_req->req_nsapi > 15) {
 | 
			
		||||
		/* Send reject with GSM_CAUSE_INV_MAND_INFO */
 | 
			
		||||
		return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
 | 
			
		||||
						GSM_CAUSE_INV_MAND_INFO,
 | 
			
		||||
						0, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Optional: Access Point Name, Protocol Config Options */
 | 
			
		||||
	if (req_pdpa + req_pdpa_len < msg->data + msg->len)
 | 
			
		||||
		tlv_parse(&tp, &gsm48_sm_att_tlvdef, req_pdpa + req_pdpa_len,
 | 
			
		||||
			  (msg->data + msg->len) - (req_pdpa + req_pdpa_len), 0, 0);
 | 
			
		||||
	else
 | 
			
		||||
		memset(&tp, 0, sizeof(tp));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* put the non-TLV elements in the TLV parser structure to
 | 
			
		||||
	 * pass them on to the SGSN / GTP code */
 | 
			
		||||
	tp.lv[OSMO_IE_GSM_REQ_QOS].len = req_qos_len;
 | 
			
		||||
	tp.lv[OSMO_IE_GSM_REQ_QOS].val = req_qos;
 | 
			
		||||
	tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].len = req_pdpa_len;
 | 
			
		||||
	tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].val = req_pdpa;
 | 
			
		||||
 | 
			
		||||
	/* Check if NSAPI is already in use */
 | 
			
		||||
	pdp = sgsn_pdp_ctx_by_nsapi(mmctx, act_req->req_nsapi);
 | 
			
		||||
	if (pdp) {
 | 
			
		||||
		/* Make sure pdp ctx was not already torn down on GTP side */
 | 
			
		||||
		if (!pdp->lib) {
 | 
			
		||||
			gsm_cause = GSM_CAUSE_REACT_RQD;
 | 
			
		||||
			goto no_context;
 | 
			
		||||
		}
 | 
			
		||||
		/* We already have a PDP context for this TLLI + NSAPI tuple */
 | 
			
		||||
		if (pdp->sapi == act_req->req_llc_sapi &&
 | 
			
		||||
		    pdp->ti == transaction_id) {
 | 
			
		||||
			/* This apparently is a re-transmission of a PDP CTX
 | 
			
		||||
			 * ACT REQ (our ACT ACK must have got dropped) */
 | 
			
		||||
			rc = gsm48_tx_gsm_act_pdp_acc(pdp);
 | 
			
		||||
			if (rc < 0)
 | 
			
		||||
				return rc;
 | 
			
		||||
 | 
			
		||||
			if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
 | 
			
		||||
				/* Also re-transmit the SNDCP XID message */
 | 
			
		||||
				lle = &pdp->mm->gb.llme->lle[pdp->sapi];
 | 
			
		||||
				rc = sndcp_sn_xid_req(lle,pdp->nsapi);
 | 
			
		||||
				if (rc < 0)
 | 
			
		||||
					return rc;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Send reject with GSM_CAUSE_NSAPI_IN_USE */
 | 
			
		||||
		return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
 | 
			
		||||
						GSM_CAUSE_NSAPI_IN_USE,
 | 
			
		||||
						0, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mmctx->ggsn_lookup) {
 | 
			
		||||
		if (mmctx->ggsn_lookup->sapi == act_req->req_llc_sapi &&
 | 
			
		||||
			mmctx->ggsn_lookup->ti == transaction_id) {
 | 
			
		||||
			LOGMMCTXP(LOGL_NOTICE, mmctx,
 | 
			
		||||
				"Re-transmission while doing look-up. Ignoring.\n");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Only increment counter for a real activation, after we checked
 | 
			
		||||
	 * for re-transmissions */
 | 
			
		||||
	rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PDP_CTX_ACT]);
 | 
			
		||||
 | 
			
		||||
	/* Determine GGSN based on APN and subscription options */
 | 
			
		||||
	ggsn = sgsn_mm_ctx_find_ggsn_ctx(mmctx, &tp, &gsm_cause, apn_str);
 | 
			
		||||
	if (ggsn)
 | 
			
		||||
		return activate_ggsn(mmctx, ggsn, transaction_id,
 | 
			
		||||
				act_req->req_nsapi, act_req->req_llc_sapi,
 | 
			
		||||
				&tp, 0);
 | 
			
		||||
 | 
			
		||||
	if (strlen(apn_str) == 0)
 | 
			
		||||
		goto no_context;
 | 
			
		||||
	if (!sgsn->cfg.dynamic_lookup)
 | 
			
		||||
		goto no_context;
 | 
			
		||||
 | 
			
		||||
	/* schedule a dynamic look-up */
 | 
			
		||||
	mmctx->ggsn_lookup = talloc_zero(tall_sgsn_ctx, struct sgsn_ggsn_lookup);
 | 
			
		||||
	if (!mmctx->ggsn_lookup)
 | 
			
		||||
		goto no_context;
 | 
			
		||||
 | 
			
		||||
	mmctx->ggsn_lookup->state = SGSN_GGSN_2DIGIT;
 | 
			
		||||
	mmctx->ggsn_lookup->mmctx = mmctx;
 | 
			
		||||
	strcpy(mmctx->ggsn_lookup->apn_str, apn_str);
 | 
			
		||||
 | 
			
		||||
	mmctx->ggsn_lookup->orig_msg = msg;
 | 
			
		||||
	mmctx->ggsn_lookup->tp = tp;
 | 
			
		||||
 | 
			
		||||
	mmctx->ggsn_lookup->ti = transaction_id;
 | 
			
		||||
	mmctx->ggsn_lookup->nsapi = act_req->req_nsapi;
 | 
			
		||||
	mmctx->ggsn_lookup->sapi = act_req->req_llc_sapi;
 | 
			
		||||
 | 
			
		||||
	hostname = osmo_apn_qualify_from_imsi(mmctx->imsi,
 | 
			
		||||
				mmctx->ggsn_lookup->apn_str, 0);
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_DEBUG, mmctx, "Going to query %s\n", hostname);
 | 
			
		||||
	rc = sgsn_ares_query(sgsn, hostname,
 | 
			
		||||
				ggsn_lookup_cb, mmctx->ggsn_lookup);
 | 
			
		||||
	if (rc != 0) {
 | 
			
		||||
		LOGMMCTXP(LOGL_ERROR, mmctx, "Failed to start ares query.\n");
 | 
			
		||||
		goto no_context;
 | 
			
		||||
	}
 | 
			
		||||
	*delete = 0;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
no_context:
 | 
			
		||||
	LOGMMCTXP(LOGL_ERROR, mmctx, "No GGSN context found!\n");
 | 
			
		||||
	return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
 | 
			
		||||
					gsm_cause, 0, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 3GPP TS 24.008 § 9.5.1: Activate PDP Context Request */
 | 
			
		||||
static int gsm48_rx_gsm_act_pdp_req(struct sgsn_mm_ctx *mmctx,
 | 
			
		||||
				    struct msgb *_msg)
 | 
			
		||||
{
 | 
			
		||||
	bool delete = 1;
 | 
			
		||||
	struct msgb *msg;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_REQUEST]);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * This is painful. We might not have a static GGSN
 | 
			
		||||
	 * configuration and then would need to copy the msg
 | 
			
		||||
	 * and re-do most of this routine (or call it again
 | 
			
		||||
	 * and make sure it only goes through the dynamic
 | 
			
		||||
	 * resolving. The question is what to optimize for
 | 
			
		||||
	 * and the dynamic resolution will be the right thing
 | 
			
		||||
	 * in the long run.
 | 
			
		||||
	 */
 | 
			
		||||
	msg = bssgp_msgb_copy(_msg, __func__);
 | 
			
		||||
	if (!msg) {
 | 
			
		||||
		struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(_msg);
 | 
			
		||||
		uint8_t transaction_id = gsm48_hdr_trans_id(gh);
 | 
			
		||||
 | 
			
		||||
		LOGMMCTXP(LOGL_ERROR, mmctx, "-> ACTIVATE PDP CONTEXT REQ failed copy.\n");
 | 
			
		||||
		/* Send reject with GSM_CAUSE_INV_MAND_INFO */
 | 
			
		||||
		return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
 | 
			
		||||
						GSM_CAUSE_NET_FAIL,
 | 
			
		||||
						0, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = do_act_pdp_req(mmctx, msg, &delete);
 | 
			
		||||
	if (delete)
 | 
			
		||||
		msgb_free(msg);
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 3GPP TS 24.008 § 9.5.8: Deactivate PDP Context Request */
 | 
			
		||||
static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, struct msgb *msg)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
 | 
			
		||||
	uint8_t transaction_id = gsm48_hdr_trans_id(gh);
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp;
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_INFO, mm, "-> DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
 | 
			
		||||
		get_value_string(gsm48_gsm_cause_names, gh->data[0]));
 | 
			
		||||
	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_UL_DEACTIVATE_REQUEST]);
 | 
			
		||||
 | 
			
		||||
	pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
 | 
			
		||||
	if (!pdp) {
 | 
			
		||||
		LOGMMCTXP(LOGL_NOTICE, mm, "Deactivate PDP Context Request for "
 | 
			
		||||
			"non-existing PDP Context (IMSI=%s, TI=%u)\n",
 | 
			
		||||
			mm->imsi, transaction_id);
 | 
			
		||||
		return _gsm48_tx_gsm_deact_pdp_acc(mm, transaction_id);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return sgsn_delete_pdp_ctx(pdp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 3GPP TS 24.008 § 9.5.9: Deactivate PDP Context Accept */
 | 
			
		||||
static int gsm48_rx_gsm_deact_pdp_ack(struct sgsn_mm_ctx *mm, struct msgb *msg)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
 | 
			
		||||
	uint8_t transaction_id = gsm48_hdr_trans_id(gh);
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp;
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_INFO, mm, "-> DEACTIVATE PDP CONTEXT ACK\n");
 | 
			
		||||
	rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_UL_DEACTIVATE_ACCEPT]);
 | 
			
		||||
 | 
			
		||||
	pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
 | 
			
		||||
	if (!pdp) {
 | 
			
		||||
		LOGMMCTXP(LOGL_NOTICE, mm, "Deactivate PDP Context Accept for "
 | 
			
		||||
			"non-existing PDP Context (IMSI=%s, TI=%u)\n",
 | 
			
		||||
			mm->imsi, transaction_id);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	/* stop timer 3395 */
 | 
			
		||||
	pdpctx_timer_stop(pdp, 3395);
 | 
			
		||||
	if (pdp->ggsn)
 | 
			
		||||
		return sgsn_delete_pdp_ctx(pdp);
 | 
			
		||||
	/* GTP side already detached, freeing */
 | 
			
		||||
	sgsn_pdp_ctx_free(pdp);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm48_hdr *gh = msgb_l3(msg);
 | 
			
		||||
 | 
			
		||||
	LOGMMCTXP(LOGL_INFO, ctx, "-> GPRS SM STATUS (cause: %s)\n",
 | 
			
		||||
		get_value_string(gsm48_gsm_cause_names, gh->data[0]));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pdpctx_timer_cb(void *_pdp)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp = _pdp;
 | 
			
		||||
 | 
			
		||||
	pdp->num_T_exp++;
 | 
			
		||||
 | 
			
		||||
	switch (pdp->T) {
 | 
			
		||||
	case 3395:	/* waiting for PDP CTX DEACT ACK */
 | 
			
		||||
		if (pdp->num_T_exp > T339X_MAX_RETRANS) {
 | 
			
		||||
			LOGPDPCTXP(LOGL_NOTICE, pdp, "T3395 expired > %d times\n", T339X_MAX_RETRANS);
 | 
			
		||||
			pdp->state = PDP_STATE_INACTIVE;
 | 
			
		||||
			if (pdp->ggsn)
 | 
			
		||||
				sgsn_delete_pdp_ctx(pdp);
 | 
			
		||||
			else
 | 
			
		||||
				sgsn_pdp_ctx_free(pdp);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		_gsm48_tx_gsm_deact_pdp_req(pdp->mm, pdp->ti, GSM_CAUSE_NET_FAIL, true);
 | 
			
		||||
		pdpctx_timer_rearm(pdp, 3395);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOGPDPCTXP(LOGL_ERROR, pdp, "timer expired in unknown mode %u\n",
 | 
			
		||||
			pdp->T);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* GPRS Session Management */
 | 
			
		||||
int gsm0408_rcv_gsm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
 | 
			
		||||
			   struct gprs_llc_llme *llme)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	/* MMCTX can be NULL when called */
 | 
			
		||||
 | 
			
		||||
	if (!mmctx) {
 | 
			
		||||
		LOGGBIUP(llme, msg, LOGL_NOTICE, "Cannot handle SM for unknown MM CTX\n");
 | 
			
		||||
		/* 6.1.3.6 */
 | 
			
		||||
		if (gh->msg_type == GSM48_MT_GSM_STATUS)
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		return gsm0408_gprs_force_reattach_oldmsg(msg, llme);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (gh->msg_type) {
 | 
			
		||||
	case GSM48_MT_GSM_ACT_PDP_REQ:
 | 
			
		||||
		rc = gsm48_rx_gsm_act_pdp_req(mmctx, msg);
 | 
			
		||||
		break;
 | 
			
		||||
	case GSM48_MT_GSM_DEACT_PDP_REQ:
 | 
			
		||||
		rc = gsm48_rx_gsm_deact_pdp_req(mmctx, msg);
 | 
			
		||||
		break;
 | 
			
		||||
	case GSM48_MT_GSM_DEACT_PDP_ACK:
 | 
			
		||||
		rc = gsm48_rx_gsm_deact_pdp_ack(mmctx, msg);
 | 
			
		||||
		break;
 | 
			
		||||
	case GSM48_MT_GSM_STATUS:
 | 
			
		||||
		rc = gsm48_rx_gsm_status(mmctx, msg);
 | 
			
		||||
		break;
 | 
			
		||||
	case GSM48_MT_GSM_REQ_PDP_ACT_REJ:
 | 
			
		||||
	case GSM48_MT_GSM_ACT_AA_PDP_REQ:
 | 
			
		||||
	case GSM48_MT_GSM_DEACT_AA_PDP_REQ:
 | 
			
		||||
		LOGMMCTXP(LOGL_NOTICE, mmctx, "Unimplemented GSM 04.08 GSM msg type 0x%02x: %s\n",
 | 
			
		||||
			gh->msg_type, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
 | 
			
		||||
		rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOGMMCTXP(LOGL_NOTICE, mmctx, "Unknown GSM 04.08 GSM msg type 0x%02x: %s\n",
 | 
			
		||||
			gh->msg_type, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
 | 
			
		||||
		rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
@@ -31,6 +31,7 @@
 | 
			
		||||
#include <osmocom/gprs/gprs_bssgp.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/sgsn/debug.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gb.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_llc.h>
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sndcp.h>
 | 
			
		||||
@@ -745,6 +746,7 @@ int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
 | 
			
		||||
	struct sndcp_common_hdr *sch = (struct sndcp_common_hdr *)hdr;
 | 
			
		||||
	struct sndcp_comp_hdr *scomph = NULL;
 | 
			
		||||
	struct sndcp_udata_hdr *suh;
 | 
			
		||||
	struct sgsn_mm_ctx *mmctx;
 | 
			
		||||
	uint8_t *npdu;
 | 
			
		||||
	uint16_t npdu_num __attribute__((unused));
 | 
			
		||||
	int npdu_len;
 | 
			
		||||
@@ -778,6 +780,15 @@ int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
 | 
			
		||||
	/* FIXME: move this RA_ID up to the LLME or even higher */
 | 
			
		||||
	bssgp_parse_cell_id(&sne->ra_id, msgb_bcid(msg));
 | 
			
		||||
 | 
			
		||||
	mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &sne->ra_id);
 | 
			
		||||
	if (!mmctx) {
 | 
			
		||||
		LOGP(DSNDCP, LOGL_ERROR, "Message for non-existing MM ctx "
 | 
			
		||||
				"(lle=%p, TLLI=%08x, SAPI=%u, NSAPI=%u)\n",
 | 
			
		||||
				lle, lle->llme->tlli, lle->sapi, sch->nsapi);
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
	gprs_gb_recv_pdu(mmctx);
 | 
			
		||||
 | 
			
		||||
	if (scomph) {
 | 
			
		||||
		sne->defrag.pcomp = scomph->pcomp;
 | 
			
		||||
		sne->defrag.dcomp = scomph->dcomp;
 | 
			
		||||
@@ -989,8 +1000,8 @@ int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi)
 | 
			
		||||
	gprs_sndcp_comp_free(lle->llme->comp.data);
 | 
			
		||||
	lle->llme->comp.proto = gprs_sndcp_comp_alloc(lle->llme);
 | 
			
		||||
	lle->llme->comp.data = gprs_sndcp_comp_alloc(lle->llme);
 | 
			
		||||
	talloc_free(lle->llme->xid);
 | 
			
		||||
	lle->llme->xid = NULL;
 | 
			
		||||
	talloc_free(lle->xid);
 | 
			
		||||
	lle->xid = NULL;
 | 
			
		||||
 | 
			
		||||
	/* Generate compression parameter bytestream */
 | 
			
		||||
	xid_len = gprs_llc_gen_sndcp_xid(l3params, sizeof(l3params), nsapi);
 | 
			
		||||
@@ -1120,6 +1131,14 @@ int sndcp_sn_xid_ind(struct gprs_llc_xid_field *xid_field_indication,
 | 
			
		||||
	OSMO_ASSERT(xid_field_response);
 | 
			
		||||
	OSMO_ASSERT(lle);
 | 
			
		||||
 | 
			
		||||
	/* Some phones send zero byte length SNDCP frames
 | 
			
		||||
	 * and do require a confirmation response. */
 | 
			
		||||
	if (xid_field_indication->data_len == 0) {
 | 
			
		||||
		xid_field_response->type = GPRS_LLC_XID_T_L3_PAR;
 | 
			
		||||
		xid_field_response->data_len = 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Parse SNDCP-CID XID-Field */
 | 
			
		||||
	comp_fields = gprs_sndcp_parse_xid(&version, lle->llme,
 | 
			
		||||
					   xid_field_indication->data,
 | 
			
		||||
@@ -160,16 +160,23 @@ void gprs_sndcp_comp_free(struct llist_head *comp_entities)
 | 
			
		||||
 | 
			
		||||
	llist_for_each_entry(comp_entity, comp_entities, list) {
 | 
			
		||||
		/* Free compression entity */
 | 
			
		||||
		if (comp_entity->compclass == SNDCP_XID_PROTOCOL_COMPRESSION) {
 | 
			
		||||
		switch (comp_entity->compclass) {
 | 
			
		||||
		case SNDCP_XID_PROTOCOL_COMPRESSION:
 | 
			
		||||
			LOGP(DSNDCP, LOGL_INFO,
 | 
			
		||||
			     "Deleting header compression entity %d ...\n",
 | 
			
		||||
			     comp_entity->entity);
 | 
			
		||||
			gprs_sndcp_pcomp_term(comp_entity);
 | 
			
		||||
		} else {
 | 
			
		||||
			break;
 | 
			
		||||
		case SNDCP_XID_DATA_COMPRESSION:
 | 
			
		||||
			LOGP(DSNDCP, LOGL_INFO,
 | 
			
		||||
			     "Deleting data compression entity %d ...\n",
 | 
			
		||||
			     comp_entity->entity);
 | 
			
		||||
			gprs_sndcp_dcomp_term(comp_entity);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			LOGP(DSNDCP, LOGL_INFO,
 | 
			
		||||
			     "Invalid compression class %d!\n", comp_entity->compclass);
 | 
			
		||||
			OSMO_ASSERT(false);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -94,7 +94,7 @@ int gprs_sndcp_dcomp_init(const void *ctx, struct gprs_sndcp_comp *comp_entity,
 | 
			
		||||
				&rx_v42bis_data_handler, NULL,
 | 
			
		||||
				V42BIS_MAX_OUTPUT_LENGTH);
 | 
			
		||||
		LOGP(DSNDCP, LOGL_INFO,
 | 
			
		||||
		     "V.42bis data compression initalized.\n");
 | 
			
		||||
		     "V.42bis data compression initialized.\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -59,7 +59,7 @@ int gprs_sndcp_pcomp_init(const void *ctx, struct gprs_sndcp_comp *comp_entity,
 | 
			
		||||
		    slhc_init(ctx, comp_field->rfc1144_params->s01 + 1,
 | 
			
		||||
			      comp_field->rfc1144_params->s01 + 1);
 | 
			
		||||
		LOGP(DSNDCP, LOGL_INFO,
 | 
			
		||||
		     "RFC1144 header compression initalized.\n");
 | 
			
		||||
		     "RFC1144 header compression initialized.\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -153,9 +153,9 @@ static int cdr_snprintf_pdp(char *buf, size_t size, const char *ev,
 | 
			
		||||
			struct sgsn_pdp_ctx *pdp)
 | 
			
		||||
{
 | 
			
		||||
	char apni[(pdp->lib ? pdp->lib->apn_use.l : 0) + 1];
 | 
			
		||||
	char ggsn_addr[INET_ADDRSTRLEN + 1];
 | 
			
		||||
	char sgsn_addr[INET_ADDRSTRLEN + 1];
 | 
			
		||||
	char eua_addr[INET6_ADDRSTRLEN + 1];
 | 
			
		||||
	char ggsn_addr[INET_ADDRSTRLEN];
 | 
			
		||||
	char sgsn_addr[INET_ADDRSTRLEN];
 | 
			
		||||
	char eua_addr[INET6_ADDRSTRLEN];
 | 
			
		||||
	struct tm tm;
 | 
			
		||||
	struct timeval tv;
 | 
			
		||||
	time_t duration;
 | 
			
		||||
@@ -45,16 +45,16 @@
 | 
			
		||||
#include <osmocom/sgsn/signal.h>
 | 
			
		||||
#include <osmocom/sgsn/debug.h>
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gb.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_llc.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_subscriber.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_sndcp.h>
 | 
			
		||||
 | 
			
		||||
#ifdef BUILD_IU
 | 
			
		||||
#include <osmocom/ranap/iu_client.h>
 | 
			
		||||
#include <osmocom/ranap/ranap_ies_defs.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <osmocom/sgsn/gprs_ranap.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_mm_state_gb_fsm.h>
 | 
			
		||||
 | 
			
		||||
#include <gtp.h>
 | 
			
		||||
#include <pdp.h>
 | 
			
		||||
@@ -153,7 +153,7 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
 | 
			
		||||
 | 
			
		||||
	imsi_ui64 = imsi_str2gtp(mmctx->imsi);
 | 
			
		||||
 | 
			
		||||
	rc = pdp_newpdp(&pdp, imsi_ui64, nsapi, NULL);
 | 
			
		||||
	rc = gtp_pdp_newpdp(ggsn->gsn, &pdp, imsi_ui64, nsapi, NULL);
 | 
			
		||||
	if (rc) {
 | 
			
		||||
		LOGP(DGPRS, LOGL_ERROR, "Out of libgtp PDP Contexts\n");
 | 
			
		||||
		return NULL;
 | 
			
		||||
@@ -279,7 +279,9 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
 | 
			
		||||
	pdp->userloc.l = 8;
 | 
			
		||||
	switch (mmctx->ran_type) {
 | 
			
		||||
	case MM_CTX_T_GERAN_Gb:
 | 
			
		||||
#if 0
 | 
			
		||||
	case MM_CTX_T_GERAN_Iu:
 | 
			
		||||
#endif
 | 
			
		||||
		pdp->rattype.v[0] = 2;
 | 
			
		||||
		/* User Location Information */
 | 
			
		||||
		pdp->userloc_given = 1;
 | 
			
		||||
@@ -357,7 +359,7 @@ static const struct cause_map gtp2sm_cause_map[] = {
 | 
			
		||||
	{ 0, 0 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx)
 | 
			
		||||
int send_act_pdp_cont_acc(struct sgsn_pdp_ctx *pctx)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_signal_data sig_data;
 | 
			
		||||
	int rc;
 | 
			
		||||
@@ -467,75 +469,10 @@ 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)
 | 
			
		||||
{
 | 
			
		||||
	gtp_echo_req(ggc->gsn, ggc->gtp_version, NULL, &ggc->remote_addr);
 | 
			
		||||
	LOGGGSN(ggc, LOGL_INFO, "GTP Tx Echo Request\n");
 | 
			
		||||
	gtp_echo_req(ggc->gsn, ggc->gtp_version, ggc, &ggc->remote_addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef BUILD_IU
 | 
			
		||||
/* Callback for RAB assignment response */
 | 
			
		||||
int sgsn_ranap_rab_ass_resp(struct sgsn_mm_ctx *ctx, RANAP_RAB_SetupOrModifiedItemIEs_t *setup_ies)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t rab_id;
 | 
			
		||||
	bool require_pdp_update = false;
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp = NULL;
 | 
			
		||||
	RANAP_RAB_SetupOrModifiedItem_t *item = &setup_ies->raB_SetupOrModifiedItem;
 | 
			
		||||
 | 
			
		||||
	rab_id = item->rAB_ID.buf[0];
 | 
			
		||||
 | 
			
		||||
	pdp = sgsn_pdp_ctx_by_nsapi(ctx, rab_id);
 | 
			
		||||
	if (!pdp) {
 | 
			
		||||
		LOGP(DRANAP, LOGL_ERROR, "RAB Assignment Response for unknown RAB/NSAPI=%u\n", rab_id);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (item->transportLayerAddress) {
 | 
			
		||||
		LOGPC(DRANAP, LOGL_INFO, " Setup: (%u/%s)", rab_id, osmo_hexdump(item->transportLayerAddress->buf,
 | 
			
		||||
								     item->transportLayerAddress->size));
 | 
			
		||||
		switch (item->transportLayerAddress->size) {
 | 
			
		||||
		case 7:
 | 
			
		||||
			/* It must be IPv4 inside a X213 NSAP */
 | 
			
		||||
			memcpy(pdp->lib->gsnlu.v, &item->transportLayerAddress->buf[3], 4);
 | 
			
		||||
			break;
 | 
			
		||||
		case 4:
 | 
			
		||||
			/* It must be a raw IPv4 address */
 | 
			
		||||
			memcpy(pdp->lib->gsnlu.v, item->transportLayerAddress->buf, 4);
 | 
			
		||||
			break;
 | 
			
		||||
		case 16:
 | 
			
		||||
			/* TODO: It must be a raw IPv6 address */
 | 
			
		||||
		case 19:
 | 
			
		||||
			/* TODO: It must be IPv6 inside a X213 NSAP */
 | 
			
		||||
		default:
 | 
			
		||||
			LOGP(DRANAP, LOGL_ERROR, "RAB Assignment Resp: Unknown "
 | 
			
		||||
				"transport layer address size %u\n",
 | 
			
		||||
				item->transportLayerAddress->size);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		require_pdp_update = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* The TEI on the RNC side might have changed, too */
 | 
			
		||||
	if (item->iuTransportAssociation &&
 | 
			
		||||
	    item->iuTransportAssociation->present == RANAP_IuTransportAssociation_PR_gTP_TEI &&
 | 
			
		||||
	    item->iuTransportAssociation->choice.gTP_TEI.buf &&
 | 
			
		||||
	    item->iuTransportAssociation->choice.gTP_TEI.size >= 4) {
 | 
			
		||||
		uint32_t tei = osmo_load32be(item->iuTransportAssociation->choice.gTP_TEI.buf);
 | 
			
		||||
		LOGP(DRANAP, LOGL_DEBUG, "Updating TEID on RNC side from 0x%08x to 0x%08x\n",
 | 
			
		||||
			pdp->lib->teid_own, tei);
 | 
			
		||||
		pdp->lib->teid_own = tei;
 | 
			
		||||
		require_pdp_update = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (require_pdp_update)
 | 
			
		||||
		gtp_update_context(pdp->ggsn->gsn, pdp->lib, pdp, &pdp->lib->hisaddr0);
 | 
			
		||||
 | 
			
		||||
	if (pdp->state != PDP_STATE_CR_CONF) {
 | 
			
		||||
		send_act_pdp_cont_acc(pdp);
 | 
			
		||||
		pdp->state = PDP_STATE_CR_CONF;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Confirmation of a PDP Context Delete */
 | 
			
		||||
static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
 | 
			
		||||
{
 | 
			
		||||
@@ -577,13 +514,15 @@ static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Confirmation of an GTP ECHO request */
 | 
			
		||||
static int echo_conf(struct pdp_t *pdp, void *cbp, int recovery)
 | 
			
		||||
static int echo_conf(void *cbp, bool timeout)
 | 
			
		||||
{
 | 
			
		||||
	if (recovery < 0) {
 | 
			
		||||
		LOGP(DGPRS, LOGL_NOTICE, "GTP Echo Request timed out\n");
 | 
			
		||||
	struct sgsn_ggsn_ctx *ggc = (struct sgsn_ggsn_ctx *)cbp;
 | 
			
		||||
	if (timeout) {
 | 
			
		||||
		LOGGGSN(ggc, LOGL_NOTICE, "GTP Echo Request timed out\n");
 | 
			
		||||
		/* FIXME: if version == 1, retry with version 0 */
 | 
			
		||||
		sgsn_ggsn_ctx_drop_all_pdp(ggc);
 | 
			
		||||
	} else {
 | 
			
		||||
		DEBUGP(DGPRS, "GTP Rx Echo Response\n");
 | 
			
		||||
		LOGGGSN(ggc, LOGL_INFO, "GTP Rx Echo Response\n");
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -628,8 +567,8 @@ static int cb_conf(int type, int cause, struct pdp_t *pdp, void *cbp)
 | 
			
		||||
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case GTP_ECHO_REQ:
 | 
			
		||||
		/* libgtp hands us the RECOVERY number instead of a cause */
 | 
			
		||||
		return echo_conf(pdp, cbp, cause);
 | 
			
		||||
		/* libgtp hands us the RECOVERY number instead of a cause (EOF on timeout) */
 | 
			
		||||
		return echo_conf(cbp, cause == EOF);
 | 
			
		||||
	case GTP_CREATE_PDP_REQ:
 | 
			
		||||
		return create_pdp_conf(pdp, cbp, cause);
 | 
			
		||||
	case GTP_DELETE_PDP_REQ:
 | 
			
		||||
@@ -647,8 +586,9 @@ static int cb_delete_context(struct pdp_t *pdp)
 | 
			
		||||
 | 
			
		||||
	LOGPDPX(DGPRS, LOGL_INFO, pdp, "Context %p was deleted\n", pdp);
 | 
			
		||||
 | 
			
		||||
	/* unlink the now non-existing library handle from the pdp
 | 
			
		||||
	 * context */
 | 
			
		||||
	/* unlink the now non-existing library handle from the pdp context.
 | 
			
		||||
	   This way we avoid calling pdp_freepdp() on it, since after returning
 | 
			
		||||
	   from cb_delete_context callback, libgtp is already doing so. */
 | 
			
		||||
	pctx->lib = NULL;
 | 
			
		||||
 | 
			
		||||
	sgsn_ggsn_ctx_drop_pdp(pctx);
 | 
			
		||||
@@ -676,7 +616,6 @@ static int cb_extheader_ind(struct sockaddr_in *peer)
 | 
			
		||||
/* Called whenever we receive a DATA packet */
 | 
			
		||||
static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	struct bssgp_paging_info pinfo;
 | 
			
		||||
	struct sgsn_pdp_ctx *pdp;
 | 
			
		||||
	struct sgsn_mm_ctx *mm;
 | 
			
		||||
	struct msgb *msg;
 | 
			
		||||
@@ -719,26 +658,22 @@ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len)
 | 
			
		||||
	msgb_bvci(msg) = mm->gb.bvci;
 | 
			
		||||
	msgb_nsei(msg) = mm->gb.nsei;
 | 
			
		||||
 | 
			
		||||
	switch (mm->gmm_state) {
 | 
			
		||||
	case GMM_REGISTERED_SUSPENDED:
 | 
			
		||||
	switch (mm->gmm_fsm->state) {
 | 
			
		||||
	case ST_GMM_REGISTERED_SUSPENDED:
 | 
			
		||||
		/* initiate PS PAGING procedure */
 | 
			
		||||
		memset(&pinfo, 0, sizeof(pinfo));
 | 
			
		||||
		pinfo.mode = BSSGP_PAGING_PS;
 | 
			
		||||
		pinfo.scope = BSSGP_PAGING_BVCI;
 | 
			
		||||
		pinfo.bvci = mm->gb.bvci;
 | 
			
		||||
		pinfo.imsi = mm->imsi;
 | 
			
		||||
		pinfo.ptmsi = &mm->p_tmsi;
 | 
			
		||||
		pinfo.drx_params = mm->drx_parms;
 | 
			
		||||
		pinfo.qos[0] = 0; // FIXME
 | 
			
		||||
		bssgp_tx_paging(mm->gb.nsei, 0, &pinfo);
 | 
			
		||||
		rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PAGING_PS]);
 | 
			
		||||
		gprs_gb_page_ps_ra(mm);
 | 
			
		||||
		/* FIXME: queue the packet we received from GTP */
 | 
			
		||||
		break;
 | 
			
		||||
	case GMM_REGISTERED_NORMAL:
 | 
			
		||||
	case ST_GMM_REGISTERED_NORMAL:
 | 
			
		||||
		OSMO_ASSERT(mm->gb.mm_state_fsm->state != ST_MM_IDLE);
 | 
			
		||||
		if (mm->gb.mm_state_fsm->state == ST_MM_STANDBY)
 | 
			
		||||
			gprs_gb_page_ps_ra(mm);
 | 
			
		||||
 | 
			
		||||
		/* FIXME: queue the packet we received from GTP */
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state "
 | 
			
		||||
			"%u\n", mm->gb.tlli, mm->gmm_state);
 | 
			
		||||
			"%s\n", mm->gb.tlli, osmo_fsm_inst_state_name(mm->gmm_fsm));
 | 
			
		||||
		msgb_free(msg);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -818,28 +753,6 @@ static int sgsn_gtp_fd_cb(struct osmo_fd *fd, unsigned int what)
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sgsn_gtp_tmr_start(struct sgsn_instance *sgi)
 | 
			
		||||
{
 | 
			
		||||
	struct timeval next;
 | 
			
		||||
 | 
			
		||||
	/* Retrieve next retransmission as struct timeval */
 | 
			
		||||
	gtp_retranstimeout(sgi->gsn, &next);
 | 
			
		||||
 | 
			
		||||
	/* re-schedule the timer */
 | 
			
		||||
	osmo_timer_schedule(&sgi->gtp_timer, next.tv_sec, next.tv_usec/1000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* timer callback for libgtp retransmissions and ping */
 | 
			
		||||
static void sgsn_gtp_tmr_cb(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct sgsn_instance *sgi = data;
 | 
			
		||||
 | 
			
		||||
	/* Do all the retransmissions as needed */
 | 
			
		||||
	gtp_retrans(sgi->gsn);
 | 
			
		||||
 | 
			
		||||
	sgsn_gtp_tmr_start(sgi);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int sgsn_gtp_init(struct sgsn_instance *sgi)
 | 
			
		||||
{
 | 
			
		||||
	int rc;
 | 
			
		||||
@@ -890,10 +803,6 @@ int sgsn_gtp_init(struct sgsn_instance *sgi)
 | 
			
		||||
		return rc;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Start GTP re-transmission timer */
 | 
			
		||||
	osmo_timer_setup(&sgi->gtp_timer, sgsn_gtp_tmr_cb, sgi);
 | 
			
		||||
	sgsn_gtp_tmr_start(sgi);
 | 
			
		||||
 | 
			
		||||
	/* Register callbackcs with libgtp */
 | 
			
		||||
	gtp_set_cb_delete_context(gsn, cb_delete_context);
 | 
			
		||||
	gtp_set_cb_conf(gsn, cb_conf);
 | 
			
		||||
@@ -57,6 +57,7 @@
 | 
			
		||||
#include <osmocom/sgsn/sgsn.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_llc.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_ranap.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/ctrl/control_if.h>
 | 
			
		||||
#include <osmocom/ctrl/ports.h>
 | 
			
		||||
@@ -209,6 +210,7 @@ static void print_help(void)
 | 
			
		||||
{
 | 
			
		||||
	printf("Some useful help...\n");
 | 
			
		||||
	printf("  -h --help\tthis text\n");
 | 
			
		||||
	printf("  -V --version\tPrint the version\n");
 | 
			
		||||
	printf("  -D --daemonize\tFork the process into a background daemon\n");
 | 
			
		||||
	printf("  -d option --debug\tenable Debugging\n");
 | 
			
		||||
	printf("  -s --disable-color\n");
 | 
			
		||||
@@ -269,6 +271,11 @@ static void handle_options(int argc, char **argv)
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (argc > optind) {
 | 
			
		||||
		fprintf(stderr, "Unsupported positional arguments on command line\n");
 | 
			
		||||
		exit(2);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* default categories */
 | 
			
		||||
@@ -339,7 +346,12 @@ static struct log_info_cat gprs_categories[] = {
 | 
			
		||||
		.name = "DV42BIS",
 | 
			
		||||
		.description = "V.42bis data compression (SNDCP)",
 | 
			
		||||
		.enabled = 1, .loglevel = LOGL_NOTICE,
 | 
			
		||||
	}
 | 
			
		||||
	},
 | 
			
		||||
	[DGTP] = {
 | 
			
		||||
		.name = "DGTP",
 | 
			
		||||
		.description = "GPRS Tunnelling Protocol (GTP)",
 | 
			
		||||
		.enabled = 1, .loglevel = LOGL_NOTICE,
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct log_info gprs_log_info = {
 | 
			
		||||
@@ -348,10 +360,6 @@ static const struct log_info gprs_log_info = {
 | 
			
		||||
	.num_cat = ARRAY_SIZE(gprs_categories),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if BUILD_IU
 | 
			
		||||
int sgsn_ranap_iu_event(struct ranap_ue_conn_ctx *ctx, enum ranap_iu_event_type type, void *data);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static bool file_exists(const char *path)
 | 
			
		||||
{
 | 
			
		||||
	struct stat sb;
 | 
			
		||||
@@ -383,14 +391,14 @@ int main(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
	vty_info.copyright = openbsc_copyright;
 | 
			
		||||
	vty_init(&vty_info);
 | 
			
		||||
	logging_vty_add_cmds(NULL);
 | 
			
		||||
	logging_vty_add_cmds();
 | 
			
		||||
	osmo_talloc_vty_add_cmds();
 | 
			
		||||
	osmo_stats_vty_add_cmds(&gprs_log_info);
 | 
			
		||||
	osmo_stats_vty_add_cmds();
 | 
			
		||||
	sgsn_vty_init(&sgsn->cfg);
 | 
			
		||||
	ctrl_vty_init(tall_sgsn_ctx);
 | 
			
		||||
 | 
			
		||||
#if BUILD_IU
 | 
			
		||||
	osmo_ss7_init();
 | 
			
		||||
	OSMO_ASSERT(osmo_ss7_init() == 0);
 | 
			
		||||
	osmo_ss7_vty_init_asp(tall_sgsn_ctx);
 | 
			
		||||
	osmo_sccp_vty_init();
 | 
			
		||||
#endif
 | 
			
		||||
@@ -499,7 +507,9 @@ int main(int argc, char **argv)
 | 
			
		||||
 | 
			
		||||
#if BUILD_IU
 | 
			
		||||
	/* Note that these are mostly defaults and can be overriden from the VTY */
 | 
			
		||||
	sccp = osmo_sccp_simple_client(tall_sgsn_ctx, "OsmoSGSN",
 | 
			
		||||
	sccp = osmo_sccp_simple_client_on_ss7_id(tall_sgsn_ctx,
 | 
			
		||||
						 sgsn->cfg.iu.cs7_instance,
 | 
			
		||||
						 "OsmoSGSN",
 | 
			
		||||
						 (23 << 3) + 4,
 | 
			
		||||
						 OSMO_SS7_ASP_PROT_M3UA,
 | 
			
		||||
						 0, NULL,
 | 
			
		||||
@@ -28,6 +28,7 @@
 | 
			
		||||
#include <osmocom/core/talloc.h>
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/core/rate_ctr.h>
 | 
			
		||||
#include <osmocom/core/tdef.h>
 | 
			
		||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
 | 
			
		||||
#include <osmocom/gsm/apn.h>
 | 
			
		||||
 | 
			
		||||
@@ -39,6 +40,7 @@
 | 
			
		||||
#include <osmocom/sgsn/vty.h>
 | 
			
		||||
#include <osmocom/gsupclient/gsup_client.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/vty/tdef_vty.h>
 | 
			
		||||
#include <osmocom/vty/command.h>
 | 
			
		||||
#include <osmocom/vty/vty.h>
 | 
			
		||||
#include <osmocom/vty/misc.h>
 | 
			
		||||
@@ -88,39 +90,49 @@ const struct value_string sgsn_auth_pol_strs[] = {
 | 
			
		||||
#define GSM0408_T3395_SECS	8	/* wait for DEACT PDP CTX ACK */
 | 
			
		||||
#define GSM0408_T3397_SECS	8	/* wait for DEACT AA PDP CTX ACK */
 | 
			
		||||
 | 
			
		||||
#define DECLARE_TIMER(number, doc) \
 | 
			
		||||
    DEFUN(cfg_sgsn_T##number,					\
 | 
			
		||||
      cfg_sgsn_T##number##_cmd,					\
 | 
			
		||||
      "timer t" #number  " <0-65535>",				\
 | 
			
		||||
      "Configure GPRS Timers\n"					\
 | 
			
		||||
      doc "\nTimer Value in seconds\n")				\
 | 
			
		||||
{								\
 | 
			
		||||
	int value = atoi(argv[0]);				\
 | 
			
		||||
								\
 | 
			
		||||
	if (value < 0 || value > 65535) {			\
 | 
			
		||||
		vty_out(vty, "Timer value %s out of range.%s",	\
 | 
			
		||||
		        argv[0], VTY_NEWLINE);			\
 | 
			
		||||
		return CMD_WARNING;				\
 | 
			
		||||
	}							\
 | 
			
		||||
								\
 | 
			
		||||
	g_cfg->timers.T##number = value;			\
 | 
			
		||||
	return CMD_SUCCESS;					\
 | 
			
		||||
/* Non spec timer */
 | 
			
		||||
#define NONSPEC_X1001_SECS     5       /* wait for a RANAP Release Complete */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static struct osmo_tdef sgsn_T_defs[] = {
 | 
			
		||||
	{ .T=3312, .default_val=GSM0408_T3312_SECS, .desc="Periodic RA Update timer (s)" },
 | 
			
		||||
	{ .T=3313, .default_val=GSM0408_T3313_SECS, .desc="Waiting for paging response timer (s)" },
 | 
			
		||||
	{ .T=3314, .default_val=GSM0408_T3314_SECS, .desc="READY timer. Force to STANDBY on expiry timer (s)" },
 | 
			
		||||
	{ .T=3316, .default_val=GSM0408_T3316_SECS, .desc="AA-Ready timer (s)" },
 | 
			
		||||
	{ .T=3322, .default_val=GSM0408_T3322_SECS, .desc="Detach request -> accept timer (s)" },
 | 
			
		||||
	{ .T=3350, .default_val=GSM0408_T3350_SECS, .desc="Waiting for ATT/RAU/TMSI_COMPL timer (s)" },
 | 
			
		||||
	{ .T=3360, .default_val=GSM0408_T3360_SECS, .desc="Waiting for AUTH/CIPH response timer (s)" },
 | 
			
		||||
	{ .T=3370, .default_val=GSM0408_T3370_SECS, .desc="Waiting for IDENTITY response timer (s)" },
 | 
			
		||||
	{ .T=3385, .default_val=GSM0408_T3385_SECS, .desc="Wait for ACT PDP CTX REQ timer (s)" },
 | 
			
		||||
	{ .T=3386, .default_val=GSM0408_T3386_SECS, .desc="Wait for MODIFY PDP CTX ACK timer (s)" },
 | 
			
		||||
	{ .T=3395, .default_val=GSM0408_T3395_SECS, .desc="Wait for DEACT PDP CTX ACK timer (s)" },
 | 
			
		||||
	{ .T=3397, .default_val=GSM0408_T3397_SECS, .desc="Wait for DEACT AA PDP CTX ACK timer (s)" },
 | 
			
		||||
	/* non spec timers */
 | 
			
		||||
	{ .T=-1001, .default_val=NONSPEC_X1001_SECS, .desc="RANAP Release timeout. Wait for RANAP Release Complete."
 | 
			
		||||
							   "On expiry release Iu connection (s)" },
 | 
			
		||||
	{ .T=-3314, .default_val=GSM0408_T3314_SECS, .desc="Iu User inactivity timer. On expiry release Iu connection (s)" },
 | 
			
		||||
	{}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DEFUN(show_timer, show_timer_cmd,
 | 
			
		||||
      "show timer " OSMO_TDEF_VTY_ARG_T_OPTIONAL,
 | 
			
		||||
      SHOW_STR "Show timers\n"
 | 
			
		||||
      OSMO_TDEF_VTY_DOC_T)
 | 
			
		||||
{
 | 
			
		||||
	const char *T_arg = argc > 0 ? argv[0] : NULL;
 | 
			
		||||
	return osmo_tdef_vty_show_cmd(vty, g_cfg->T_defs, T_arg, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DECLARE_TIMER(3312, "Periodic RA Update timer (s)")
 | 
			
		||||
DECLARE_TIMER(3322, "Detach request -> accept timer (s)")
 | 
			
		||||
DECLARE_TIMER(3350, "Waiting for ATT/RAU/TMSI_COMPL timer (s)")
 | 
			
		||||
DECLARE_TIMER(3360, "Waiting for AUTH/CIPH response timer (s)")
 | 
			
		||||
DECLARE_TIMER(3370, "Waiting for IDENTITY response timer (s)")
 | 
			
		||||
 | 
			
		||||
DECLARE_TIMER(3313, "Waiting for paging response timer (s)")
 | 
			
		||||
DECLARE_TIMER(3314, "Force to STANDBY on expiry timer (s)")
 | 
			
		||||
DECLARE_TIMER(3316, "AA-Ready timer (s)")
 | 
			
		||||
 | 
			
		||||
DECLARE_TIMER(3385, "Wait for ACT PDP CTX REQ timer (s)")
 | 
			
		||||
DECLARE_TIMER(3386, "Wait for MODIFY PDP CTX ACK timer (s)")
 | 
			
		||||
DECLARE_TIMER(3395, "Wait for DEACT PDP CTX ACK timer (s)")
 | 
			
		||||
DECLARE_TIMER(3397, "Wait for DEACT AA PDP CTX ACK timer (s)")
 | 
			
		||||
DEFUN(cfg_sgsn_timer, cfg_sgsn_timer_cmd,
 | 
			
		||||
      "timer " OSMO_TDEF_VTY_ARG_SET_OPTIONAL,
 | 
			
		||||
      "Configure or show timers\n"
 | 
			
		||||
      OSMO_TDEF_VTY_DOC_SET)
 | 
			
		||||
{
 | 
			
		||||
	/* If any arguments are missing, redirect to 'show' */
 | 
			
		||||
	if (argc < 2)
 | 
			
		||||
		return show_timer(self, vty, argc, argv);
 | 
			
		||||
	return osmo_tdef_vty_set_cmd(vty, g_cfg->T_defs, argv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len)
 | 
			
		||||
{
 | 
			
		||||
@@ -185,8 +197,8 @@ static int config_write_sgsn(struct vty *vty)
 | 
			
		||||
			inet_ntoa(gctx->remote_addr), VTY_NEWLINE);
 | 
			
		||||
		vty_out(vty, " ggsn %u gtp-version %u%s", gctx->id,
 | 
			
		||||
			gctx->gtp_version, VTY_NEWLINE);
 | 
			
		||||
		if (gctx->echo_interval != -1)
 | 
			
		||||
			vty_out(vty, " ggsn %u echo-interval %"PRId32"%s",
 | 
			
		||||
		if (gctx->echo_interval)
 | 
			
		||||
			vty_out(vty, " ggsn %u echo-interval %u%s",
 | 
			
		||||
				gctx->id, gctx->echo_interval, VTY_NEWLINE);
 | 
			
		||||
		else
 | 
			
		||||
			vty_out(vty, " ggsn %u no echo-interval%s",
 | 
			
		||||
@@ -211,6 +223,8 @@ static int config_write_sgsn(struct vty *vty)
 | 
			
		||||
	if (g_cfg->gsup_server_port)
 | 
			
		||||
		vty_out(vty, " gsup remote-port %d%s",
 | 
			
		||||
			g_cfg->gsup_server_port, VTY_NEWLINE);
 | 
			
		||||
	if (g_cfg->auth_policy == SGSN_AUTH_POLICY_REMOTE && !g_cfg->require_authentication)
 | 
			
		||||
		vty_out(vty, " authentication optional%s", VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " auth-policy %s%s",
 | 
			
		||||
		get_value_string(sgsn_auth_pol_strs, g_cfg->auth_policy),
 | 
			
		||||
		VTY_NEWLINE);
 | 
			
		||||
@@ -251,18 +265,7 @@ static int config_write_sgsn(struct vty *vty)
 | 
			
		||||
		vty_out(vty, " no cdr trap%s", VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " cdr interval %d%s", g_cfg->cdr.interval, VTY_NEWLINE);
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, " timer t3312 %d%s", g_cfg->timers.T3312, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3322 %d%s", g_cfg->timers.T3322, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3350 %d%s", g_cfg->timers.T3350, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3360 %d%s", g_cfg->timers.T3360, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3370 %d%s", g_cfg->timers.T3370, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3313 %d%s", g_cfg->timers.T3313, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3314 %d%s", g_cfg->timers.T3314, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3316 %d%s", g_cfg->timers.T3316, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3385 %d%s", g_cfg->timers.T3385, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3386 %d%s", g_cfg->timers.T3386, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3395 %d%s", g_cfg->timers.T3395, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " timer t3397 %d%s", g_cfg->timers.T3397, VTY_NEWLINE);
 | 
			
		||||
	osmo_tdef_vty_write(vty, g_cfg->T_defs, " timer ");
 | 
			
		||||
 | 
			
		||||
	if (g_cfg->pcomp_rfc1144.active) {
 | 
			
		||||
		vty_out(vty, " compression rfc1144 active slots %d%s",
 | 
			
		||||
@@ -293,6 +296,8 @@ static int config_write_sgsn(struct vty *vty)
 | 
			
		||||
		vty_out(vty, " no compression v42bis%s", VTY_NEWLINE);
 | 
			
		||||
 | 
			
		||||
#ifdef BUILD_IU
 | 
			
		||||
	vty_out(vty, " cs7-instance-iu %u%s", g_cfg->iu.cs7_instance,
 | 
			
		||||
		VTY_NEWLINE);
 | 
			
		||||
	ranap_iu_vty_config_write(vty, " ");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -381,7 +386,7 @@ DEFUN(cfg_ggsn_echo_interval, cfg_ggsn_echo_interval_cmd,
 | 
			
		||||
	ggc->echo_interval = atoi(argv[1]);
 | 
			
		||||
 | 
			
		||||
	if (ggc->echo_interval < 60)
 | 
			
		||||
		vty_out(vty, "%% 3GPP TS 29.060 section states inteval should " \
 | 
			
		||||
		vty_out(vty, "%% 3GPP TS 29.060 section 7.2.1 states interval should " \
 | 
			
		||||
			     "not be lower than 60 seconds, use this value for " \
 | 
			
		||||
			     "testing purposes only!%s", VTY_NEWLINE);
 | 
			
		||||
 | 
			
		||||
@@ -397,7 +402,7 @@ DEFUN(cfg_ggsn_no_echo_interval, cfg_ggsn_no_echo_interval_cmd,
 | 
			
		||||
	uint32_t id = atoi(argv[0]);
 | 
			
		||||
	struct sgsn_ggsn_ctx *ggc = sgsn_ggsn_ctx_find_alloc(id);
 | 
			
		||||
 | 
			
		||||
	ggc->echo_interval = -1;
 | 
			
		||||
	ggc->echo_interval = 0;
 | 
			
		||||
	sgsn_ggsn_ctx_check_echo_timer(ggc);
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
@@ -478,15 +483,6 @@ DEFUN(cfg_apn_imsi_ggsn, cfg_apn_imsi_ggsn_cmd,
 | 
			
		||||
	return add_apn_ggsn_mapping(vty, argv[0], argv[1], atoi(argv[2]));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct value_string gprs_mm_st_strs[] = {
 | 
			
		||||
	{ GMM_DEREGISTERED, "DEREGISTERED" },
 | 
			
		||||
	{ GMM_COMMON_PROC_INIT, "COMMON PROCEDURE (INIT)" },
 | 
			
		||||
	{ GMM_REGISTERED_NORMAL, "REGISTERED (NORMAL)" },
 | 
			
		||||
	{ GMM_REGISTERED_SUSPENDED, "REGISTERED (SUSPENDED)" },
 | 
			
		||||
	{ GMM_DEREGISTERED_INIT, "DEREGISTERED (INIT)" },
 | 
			
		||||
	{ 0, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
char *sgsn_gtp_ntoa(struct ul16_t *ul)
 | 
			
		||||
{
 | 
			
		||||
	struct in_addr ia;
 | 
			
		||||
@@ -527,13 +523,31 @@ static void vty_dump_pdp(struct vty *vty, const char *pfx,
 | 
			
		||||
static void vty_dump_mmctx(struct vty *vty, const char *pfx,
 | 
			
		||||
			   struct sgsn_mm_ctx *mm, int pdp)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t id = 0;
 | 
			
		||||
	const char *mm_state_name = NULL;
 | 
			
		||||
 | 
			
		||||
	switch(mm->ran_type) {
 | 
			
		||||
	case MM_CTX_T_UTRAN_Iu:
 | 
			
		||||
#if BUILD_IU
 | 
			
		||||
		id = mm->iu.ue_ctx->conn_id;
 | 
			
		||||
		mm_state_name = osmo_fsm_inst_state_name(mm->iu.mm_state_fsm);
 | 
			
		||||
#endif
 | 
			
		||||
		break;
 | 
			
		||||
	case MM_CTX_T_GERAN_Gb:
 | 
			
		||||
		id = mm->gb.tlli;
 | 
			
		||||
		mm_state_name = osmo_fsm_inst_state_name(mm->gb.mm_state_fsm);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "%sMM Context for IMSI %s, IMEI %s, P-TMSI %08x%s",
 | 
			
		||||
		pfx, mm->imsi, mm->imei, mm->p_tmsi, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, "%s  MSISDN: %s, TLLI: %08x%s HLR: %s",
 | 
			
		||||
		pfx, mm->msisdn, mm->gb.tlli, mm->hlr, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, "%s  MM State: %s, Routeing Area: %s, Cell ID: %u%s",
 | 
			
		||||
		pfx, get_value_string(gprs_mm_st_strs, mm->gmm_state),
 | 
			
		||||
		pfx, mm->msisdn, id, mm->hlr, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, "%s  GMM State: %s, Routeing Area: %s, Cell ID: %u%s",
 | 
			
		||||
		pfx, osmo_fsm_inst_state_name(mm->gmm_fsm),
 | 
			
		||||
		osmo_rai_name(&mm->ra), mm->gb.cell_id, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, "%s  MM State: %s, RAN Type: %s%s", pfx, mm_state_name,
 | 
			
		||||
		get_value_string(sgsn_ran_type_names, mm->ran_type), VTY_NEWLINE);
 | 
			
		||||
 | 
			
		||||
	vty_out_rate_ctr_group(vty, "  ", mm->ctrg);
 | 
			
		||||
 | 
			
		||||
@@ -636,12 +650,15 @@ DEFUN(imsi_acl, cfg_imsi_acl_cmd,
 | 
			
		||||
	"Remove IMSI from ACL\n"
 | 
			
		||||
	"IMSI of subscriber\n")
 | 
			
		||||
{
 | 
			
		||||
	char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1] = { '0' };
 | 
			
		||||
	char imsi_sanitized[GSM23003_IMSI_MAX_DIGITS + 1];
 | 
			
		||||
	const char *op = argv[0];
 | 
			
		||||
	const char *imsi = imsi_sanitized;
 | 
			
		||||
	size_t len = strnlen(argv[1], GSM23003_IMSI_MAX_DIGITS + 1);
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	memset(imsi_sanitized, '0', GSM23003_IMSI_MAX_DIGITS);
 | 
			
		||||
	imsi_sanitized[GSM23003_IMSI_MAX_DIGITS] = '\0';
 | 
			
		||||
 | 
			
		||||
	/* Sanitize IMSI */
 | 
			
		||||
	if (len > GSM23003_IMSI_MAX_DIGITS) {
 | 
			
		||||
		vty_out(vty, "%% IMSI (%s) too long (max %u digits) -- ignored!%s",
 | 
			
		||||
@@ -690,6 +707,27 @@ DEFUN(cfg_encrypt, cfg_encrypt_cmd,
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN(cfg_authentication, cfg_authentication_cmd,
 | 
			
		||||
      "authentication (optional|required)",
 | 
			
		||||
      "Whether to enforce MS authentication in GERAN (only with auth-policy remote)\n"
 | 
			
		||||
      "Allow MS to attach via GERAN without authentication (default and only possible value for non-remote auth-policy)\n"
 | 
			
		||||
      "Always require authentication (only available for auth-policy remote, default with that auth-policy)\n")
 | 
			
		||||
{
 | 
			
		||||
	int required = (argv[0][0] == 'r');
 | 
			
		||||
 | 
			
		||||
	if (vty->type != VTY_FILE) {
 | 
			
		||||
		if (g_cfg->auth_policy != SGSN_AUTH_POLICY_REMOTE && required) {
 | 
			
		||||
			vty_out(vty, "%% Authentication is not possible without HLR, "
 | 
			
		||||
				     "consider setting 'auth-policy' to 'remote'%s",
 | 
			
		||||
				     VTY_NEWLINE);
 | 
			
		||||
			return CMD_WARNING;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_cfg->require_authentication = required;
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
 | 
			
		||||
	"auth-policy (accept-all|closed|acl-only|remote)",
 | 
			
		||||
	"Configure the Authorization policy of the SGSN. This setting determines which subscribers are"
 | 
			
		||||
@@ -702,7 +740,6 @@ DEFUN(cfg_auth_policy, cfg_auth_policy_cmd,
 | 
			
		||||
	int val = get_string_value(sgsn_auth_pol_strs, argv[0]);
 | 
			
		||||
	OSMO_ASSERT(val >= SGSN_AUTH_POLICY_OPEN && val <= SGSN_AUTH_POLICY_REMOTE);
 | 
			
		||||
	g_cfg->auth_policy = val;
 | 
			
		||||
	g_cfg->require_authentication = (val == SGSN_AUTH_POLICY_REMOTE);
 | 
			
		||||
	g_cfg->require_update_location = (val == SGSN_AUTH_POLICY_REMOTE);
 | 
			
		||||
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
@@ -1284,7 +1321,7 @@ DEFUN(cfg_no_comp_rfc1144, cfg_no_comp_rfc1144_cmd,
 | 
			
		||||
DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
 | 
			
		||||
      "compression rfc1144 active slots <1-256>",
 | 
			
		||||
      COMPRESSION_STR
 | 
			
		||||
      "RFC1144 Header compresion scheme\n"
 | 
			
		||||
      "RFC1144 Header compression scheme\n"
 | 
			
		||||
      "Compression is actively proposed\n"
 | 
			
		||||
      "Number of compression state slots\n"
 | 
			
		||||
      "Number of compression state slots\n")
 | 
			
		||||
@@ -1298,7 +1335,7 @@ DEFUN(cfg_comp_rfc1144, cfg_comp_rfc1144_cmd,
 | 
			
		||||
DEFUN(cfg_comp_rfc1144p, cfg_comp_rfc1144p_cmd,
 | 
			
		||||
      "compression rfc1144 passive",
 | 
			
		||||
      COMPRESSION_STR
 | 
			
		||||
      "RFC1144 Header compresion scheme\n"
 | 
			
		||||
      "RFC1144 Header compression scheme\n"
 | 
			
		||||
      "Compression is available on request\n")
 | 
			
		||||
{
 | 
			
		||||
	g_cfg->pcomp_rfc1144.active = 0;
 | 
			
		||||
@@ -1318,7 +1355,7 @@ DEFUN(cfg_no_comp_v42bis, cfg_no_comp_v42bis_cmd,
 | 
			
		||||
DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
 | 
			
		||||
      "compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>",
 | 
			
		||||
      COMPRESSION_STR
 | 
			
		||||
      "V.42bis data compresion scheme\n"
 | 
			
		||||
      "V.42bis data compression scheme\n"
 | 
			
		||||
      "Compression is actively proposed\n"
 | 
			
		||||
      "Direction in which the compression shall be active (p0)\n"
 | 
			
		||||
      "Compress ms->sgsn direction only\n"
 | 
			
		||||
@@ -1351,7 +1388,7 @@ DEFUN(cfg_comp_v42bis, cfg_comp_v42bis_cmd,
 | 
			
		||||
DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
 | 
			
		||||
      "compression v42bis passive",
 | 
			
		||||
      COMPRESSION_STR
 | 
			
		||||
      "V.42bis data compresion scheme\n"
 | 
			
		||||
      "V.42bis data compression scheme\n"
 | 
			
		||||
      "Compression is available on request\n")
 | 
			
		||||
{
 | 
			
		||||
	g_cfg->dcomp_v42bis.active = 0;
 | 
			
		||||
@@ -1359,16 +1396,31 @@ DEFUN(cfg_comp_v42bisp, cfg_comp_v42bisp_cmd,
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if BUILD_IU
 | 
			
		||||
DEFUN(cfg_sgsn_cs7_instance_iu,
 | 
			
		||||
      cfg_sgsn_cs7_instance_iu_cmd,
 | 
			
		||||
      "cs7-instance-iu <0-15>",
 | 
			
		||||
      "Set SS7 to be used by the Iu-Interface.\n" "SS7 instance reference number (default: 0)\n")
 | 
			
		||||
{
 | 
			
		||||
	g_cfg->iu.cs7_instance = atoi(argv[0]);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int sgsn_vty_init(struct sgsn_config *cfg)
 | 
			
		||||
{
 | 
			
		||||
	g_cfg = cfg;
 | 
			
		||||
 | 
			
		||||
	g_cfg->T_defs = sgsn_T_defs;
 | 
			
		||||
	osmo_tdefs_reset(g_cfg->T_defs);
 | 
			
		||||
 | 
			
		||||
	install_element_ve(&show_sgsn_cmd);
 | 
			
		||||
	//install_element_ve(&show_mmctx_tlli_cmd);
 | 
			
		||||
	install_element_ve(&show_mmctx_imsi_cmd);
 | 
			
		||||
	install_element_ve(&show_mmctx_all_cmd);
 | 
			
		||||
	install_element_ve(&show_pdpctx_all_cmd);
 | 
			
		||||
	install_element_ve(&show_subscr_cache_cmd);
 | 
			
		||||
	install_element_ve(&show_timer_cmd);
 | 
			
		||||
 | 
			
		||||
	install_element(ENABLE_NODE, &update_subscr_insert_auth_triplet_cmd);
 | 
			
		||||
	install_element(ENABLE_NODE, &update_subscr_create_cmd);
 | 
			
		||||
@@ -1388,6 +1440,7 @@ int sgsn_vty_init(struct sgsn_config *cfg)
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_ggsn_no_echo_interval_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_imsi_acl_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_auth_policy_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_authentication_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_encrypt_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_gsup_ipa_name_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd);
 | 
			
		||||
@@ -1407,18 +1460,7 @@ int sgsn_vty_init(struct sgsn_config *cfg)
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_ggsn_dynamic_lookup_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_grx_ggsn_cmd);
 | 
			
		||||
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3312_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3322_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3350_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3360_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3370_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3313_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3314_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3316_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3385_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3386_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3395_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_T3397_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_timer_cmd);
 | 
			
		||||
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_no_comp_rfc1144_cmd);
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_comp_rfc1144_cmd);
 | 
			
		||||
@@ -1428,6 +1470,7 @@ int sgsn_vty_init(struct sgsn_config *cfg)
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_comp_v42bisp_cmd);
 | 
			
		||||
 | 
			
		||||
#ifdef BUILD_IU
 | 
			
		||||
	install_element(SGSN_NODE, &cfg_sgsn_cs7_instance_iu_cmd);
 | 
			
		||||
	ranap_iu_vty_init(SGSN_NODE, &g_cfg->iu.rab_assign_addr_enc);
 | 
			
		||||
#endif
 | 
			
		||||
	return 0;
 | 
			
		||||
@@ -1440,19 +1483,6 @@ int sgsn_parse_config(const char *config_file)
 | 
			
		||||
	/* make sure sgsn_vty_init() was called before this */
 | 
			
		||||
	OSMO_ASSERT(g_cfg);
 | 
			
		||||
 | 
			
		||||
	g_cfg->timers.T3312 = GSM0408_T3312_SECS;
 | 
			
		||||
	g_cfg->timers.T3322 = GSM0408_T3322_SECS;
 | 
			
		||||
	g_cfg->timers.T3350 = GSM0408_T3350_SECS;
 | 
			
		||||
	g_cfg->timers.T3360 = GSM0408_T3360_SECS;
 | 
			
		||||
	g_cfg->timers.T3370 = GSM0408_T3370_SECS;
 | 
			
		||||
	g_cfg->timers.T3313 = GSM0408_T3313_SECS;
 | 
			
		||||
	g_cfg->timers.T3314 = GSM0408_T3314_SECS;
 | 
			
		||||
	g_cfg->timers.T3316 = GSM0408_T3316_SECS;
 | 
			
		||||
	g_cfg->timers.T3385 = GSM0408_T3385_SECS;
 | 
			
		||||
	g_cfg->timers.T3386 = GSM0408_T3386_SECS;
 | 
			
		||||
	g_cfg->timers.T3395 = GSM0408_T3395_SECS;
 | 
			
		||||
	g_cfg->timers.T3397 = GSM0408_T3397_SECS;
 | 
			
		||||
 | 
			
		||||
	rc = vty_read_config_file(config_file, NULL);
 | 
			
		||||
	if (rc < 0) {
 | 
			
		||||
		fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
 | 
			
		||||
@@ -33,6 +33,7 @@ EXTRA_DIST = \
 | 
			
		||||
	$(TESTSUITE) \
 | 
			
		||||
	vty_test_runner.py \
 | 
			
		||||
	ctrl_test_runner.py \
 | 
			
		||||
	test_nodes.vty \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
TESTSUITE = $(srcdir)/testsuite
 | 
			
		||||
@@ -43,16 +44,38 @@ DISTCLEANFILES = \
 | 
			
		||||
 | 
			
		||||
if ENABLE_EXT_TESTS
 | 
			
		||||
python-tests: $(BUILT_SOURCES)
 | 
			
		||||
	osmotestvty.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
 | 
			
		||||
	osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
 | 
			
		||||
	$(srcdir)/vty_test_runner.py -w $(abs_top_builddir) -v
 | 
			
		||||
	$(srcdir)/ctrl_test_runner.py -w $(abs_top_builddir) -v
 | 
			
		||||
	rm -f $(top_builddir)/sms.db $(top_builddir)/gsn_restart $(top_builddir)/gtphub_restart_count
 | 
			
		||||
	$(MAKE) vty-test
 | 
			
		||||
	$(MAKE) ctrl-python-test
 | 
			
		||||
else
 | 
			
		||||
python-tests: $(BUILT_SOURCES)
 | 
			
		||||
	echo "Not running python-based tests (determined at configure-time)"
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
vty-python-test: $(BUILT_SOURCES)
 | 
			
		||||
	osmotestvty.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
 | 
			
		||||
	osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v
 | 
			
		||||
	$(srcdir)/vty_test_runner.py -w $(abs_top_builddir) -v
 | 
			
		||||
	rm -f $(top_builddir)/sms.db $(top_builddir)/gsn_restart $(top_builddir)/gtphub_restart_count
 | 
			
		||||
 | 
			
		||||
# To update the VTY script from current application behavior,
 | 
			
		||||
# pass -u to vty_script_runner.py by doing:
 | 
			
		||||
#   make vty-transcript-test U=-u
 | 
			
		||||
vty-transcript-test:
 | 
			
		||||
	osmo_verify_transcript_vty.py -v \
 | 
			
		||||
		-n OsmoSGSN -p 4245 \
 | 
			
		||||
		-r "$(top_builddir)/src/sgsn/osmo-sgsn -c $(top_srcdir)/doc/examples/osmo-sgsn/osmo-sgsn.cfg" \
 | 
			
		||||
		$(U) $${T:-$(srcdir)/*.vty}
 | 
			
		||||
	rm -f $(builddir)/sms.db $(builddir)/gsn_restart
 | 
			
		||||
 | 
			
		||||
# don't run multiple tests concurrently so that the ports don't conflict
 | 
			
		||||
vty-test:
 | 
			
		||||
	$(MAKE) vty-python-test
 | 
			
		||||
	$(MAKE) vty-transcript-test
 | 
			
		||||
 | 
			
		||||
ctrl-python-test: $(BUILT_SOURCES)
 | 
			
		||||
	$(srcdir)/ctrl_test_runner.py -w $(abs_top_builddir) -v
 | 
			
		||||
	rm -f $(top_builddir)/sms.db $(top_builddir)/gsn_restart $(top_builddir)/gtphub_restart_count
 | 
			
		||||
 | 
			
		||||
check-local: atconfig $(TESTSUITE)
 | 
			
		||||
	$(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS)
 | 
			
		||||
	$(MAKE) $(AM_MAKEFLAGS) python-tests
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
#!/usr/bin/env python2
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
# (C) 2013 by Jacob Erlbeck <jerlbeck@sysmocom.de>
 | 
			
		||||
# (C) 2014 by Holger Hans Peter Freyther
 | 
			
		||||
@@ -53,8 +53,8 @@ class TestCtrlBase(unittest.TestCase):
 | 
			
		||||
        try:
 | 
			
		||||
            self.proc = osmoutil.popen_devnull(osmo_ctrl_cmd)
 | 
			
		||||
        except OSError:
 | 
			
		||||
            print >> sys.stderr, "Current directory: %s" % os.getcwd()
 | 
			
		||||
            print >> sys.stderr, "Consider setting -b"
 | 
			
		||||
            print("Current directory: %s" % os.getcwd(), file=sys.stderr)
 | 
			
		||||
            print("Consider setting -b", file=sys.stderr)
 | 
			
		||||
        time.sleep(2)
 | 
			
		||||
 | 
			
		||||
        appstring = self.ctrl_app()[2]
 | 
			
		||||
@@ -72,7 +72,7 @@ class TestCtrlBase(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def connect(self, host, port):
 | 
			
		||||
        if verbose:
 | 
			
		||||
            print "Connecting to host %s:%i" % (host, port)
 | 
			
		||||
            print("Connecting to host %s:%i" % (host, port))
 | 
			
		||||
 | 
			
		||||
        retries = 30
 | 
			
		||||
        while True:
 | 
			
		||||
@@ -92,7 +92,7 @@ class TestCtrlBase(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def send(self, data):
 | 
			
		||||
        if verbose:
 | 
			
		||||
            print "Sending \"%s\"" %(data)
 | 
			
		||||
            print("Sending \"%s\"" %(data))
 | 
			
		||||
        data = Ctrl().add_header(data)
 | 
			
		||||
        return self.sock.send(data) == len(data)
 | 
			
		||||
 | 
			
		||||
@@ -121,9 +121,9 @@ class TestCtrlBase(unittest.TestCase):
 | 
			
		||||
        data = self.sock.recv(4096)
 | 
			
		||||
        while (len(data)>0):
 | 
			
		||||
            (head, data) = IPA().split_combined(data)
 | 
			
		||||
            answer = Ctrl().rem_header(head)
 | 
			
		||||
            answer = Ctrl().rem_header(head).decode()
 | 
			
		||||
            if verbose:
 | 
			
		||||
                print "Got message:", answer
 | 
			
		||||
                print("Got message:", answer)
 | 
			
		||||
            (mtype, id, msg) = answer.split(None, 2)
 | 
			
		||||
            id = int(id)
 | 
			
		||||
            rsp = {'mtype': mtype, 'id': id}
 | 
			
		||||
@@ -139,27 +139,27 @@ class TestCtrlBase(unittest.TestCase):
 | 
			
		||||
            responses[id] = rsp
 | 
			
		||||
 | 
			
		||||
        if verbose:
 | 
			
		||||
            print "Decoded replies: ", responses
 | 
			
		||||
            print("Decoded replies: ", responses)
 | 
			
		||||
 | 
			
		||||
        return responses
 | 
			
		||||
 | 
			
		||||
class TestCtrlSGSN(TestCtrlBase):
 | 
			
		||||
    def ctrl_command(self):
 | 
			
		||||
        return ["./src/gprs/osmo-sgsn", "-c",
 | 
			
		||||
        return ["./src/sgsn/osmo-sgsn", "-c",
 | 
			
		||||
                "doc/examples/osmo-sgsn/osmo-sgsn.cfg"]
 | 
			
		||||
 | 
			
		||||
    def ctrl_app(self):
 | 
			
		||||
        return (4251, "./src/gprs/osmo-sgsn", "OsmoSGSN", "sgsn")
 | 
			
		||||
        return (4251, "./src/sgsn/osmo-sgsn", "OsmoSGSN", "sgsn")
 | 
			
		||||
 | 
			
		||||
    def testListSubscribers(self):
 | 
			
		||||
        # TODO. Add command to mark a subscriber as active
 | 
			
		||||
        r = self.do_get('subscriber-list-active-v1')
 | 
			
		||||
        self.assertEquals(r['mtype'], 'GET_REPLY')
 | 
			
		||||
        self.assertEquals(r['var'], 'subscriber-list-active-v1')
 | 
			
		||||
        self.assertEquals(r['value'], None)
 | 
			
		||||
        self.assertEqual(r['mtype'], 'GET_REPLY')
 | 
			
		||||
        self.assertEqual(r['var'], 'subscriber-list-active-v1')
 | 
			
		||||
        self.assertEqual(r['value'], None)
 | 
			
		||||
 | 
			
		||||
def add_sgsn_test(suite, workdir):
 | 
			
		||||
    if not os.path.isfile(os.path.join(workdir, "src/gprs/osmo-sgsn")):
 | 
			
		||||
    if not os.path.isfile(os.path.join(workdir, "src/sgsn/osmo-sgsn")):
 | 
			
		||||
        print("Skipping the SGSN test")
 | 
			
		||||
        return
 | 
			
		||||
    test = unittest.TestLoader().loadTestsFromTestCase(TestCtrlSGSN)
 | 
			
		||||
@@ -191,9 +191,9 @@ if __name__ == '__main__':
 | 
			
		||||
    if args.p:
 | 
			
		||||
        confpath = args.p
 | 
			
		||||
 | 
			
		||||
    print "confpath %s, workdir %s" % (confpath, workdir)
 | 
			
		||||
    print("confpath %s, workdir %s" % (confpath, workdir))
 | 
			
		||||
    os.chdir(workdir)
 | 
			
		||||
    print "Running tests for specific control commands"
 | 
			
		||||
    print("Running tests for specific control commands")
 | 
			
		||||
    suite = unittest.TestSuite()
 | 
			
		||||
    add_sgsn_test(suite, workdir)
 | 
			
		||||
    res = unittest.TextTestRunner(verbosity=verbose_level).run(suite)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,10 +32,10 @@ gbproxy_test_LDFLAGS = \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
gbproxy_test_LDADD = \
 | 
			
		||||
	$(top_builddir)/src/gprs/gb_proxy.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gb_proxy_patch.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gb_proxy_peer.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gb_proxy_tlli.o \
 | 
			
		||||
	$(top_builddir)/src/gbproxy/gb_proxy.o \
 | 
			
		||||
	$(top_builddir)/src/gbproxy/gb_proxy_patch.o \
 | 
			
		||||
	$(top_builddir)/src/gbproxy/gb_proxy_peer.o \
 | 
			
		||||
	$(top_builddir)/src/gbproxy/gb_proxy_tlli.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_gb_parse.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_llc_parse.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/crc24.o \
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ gtphub_test_LDFLAGS = \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
gtphub_test_LDADD = \
 | 
			
		||||
	$(top_builddir)/src/gprs/gtphub.o \
 | 
			
		||||
	$(top_builddir)/src/gtphub/gtphub.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_utils.o \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS) \
 | 
			
		||||
	$(LIBOSMOGSM_LIBS) \
 | 
			
		||||
 
 | 
			
		||||
@@ -42,27 +42,31 @@ sgsn_test_LDFLAGS = \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
 | 
			
		||||
sgsn_test_LDADD = \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_llc_parse.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_llc.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/crc24.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_sndcp.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_gmm_attach.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_gmm.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_sgsn.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/sgsn_vty.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/sgsn_libgtp.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/sgsn_auth.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/sgsn_ares.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_llc.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_gb.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_sndcp.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_gmm_attach.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_gmm.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_gmm_fsm.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_mm_state_gb_fsm.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_sgsn.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/sgsn_vty.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/sgsn_libgtp.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/sgsn_auth.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_subscriber.o \
 | 
			
		||||
        $(top_builddir)/src/sgsn/gprs_llc_xid.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_sndcp_xid.o \
 | 
			
		||||
        $(top_builddir)/src/sgsn/slhc.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_sm.o \
 | 
			
		||||
        $(top_builddir)/src/sgsn/gprs_sndcp_comp.o \
 | 
			
		||||
        $(top_builddir)/src/sgsn/gprs_sndcp_pcomp.o \
 | 
			
		||||
        $(top_builddir)/src/sgsn/v42bis.o \
 | 
			
		||||
        $(top_builddir)/src/sgsn/gprs_sndcp_dcomp.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_utils.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_subscriber.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_llc_parse.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_gb_parse.o \
 | 
			
		||||
        $(top_builddir)/src/gprs/gprs_llc_xid.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_sndcp_xid.o \
 | 
			
		||||
        $(top_builddir)/src/gprs/slhc.o \
 | 
			
		||||
        $(top_builddir)/src/gprs/gprs_sndcp_comp.o \
 | 
			
		||||
        $(top_builddir)/src/gprs/gprs_sndcp_pcomp.o \
 | 
			
		||||
        $(top_builddir)/src/gprs/v42bis.o \
 | 
			
		||||
        $(top_builddir)/src/gprs/gprs_sndcp_dcomp.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/crc24.o \
 | 
			
		||||
	$(top_builddir)/src/gprs/sgsn_ares.o \
 | 
			
		||||
	$(LIBOSMOABIS_LIBS) \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS) \
 | 
			
		||||
	$(LIBOSMOGSM_LIBS) \
 | 
			
		||||
@@ -76,6 +80,8 @@ sgsn_test_LDADD = \
 | 
			
		||||
 | 
			
		||||
if BUILD_IU
 | 
			
		||||
sgsn_test_LDADD += \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_ranap.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_mm_state_iu_fsm.o \
 | 
			
		||||
	$(LIBOSMORANAP_LIBS) \
 | 
			
		||||
	$(LIBOSMOSIGTRAN_LIBS) \
 | 
			
		||||
	$(LIBASN1C_LIBS) \
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@
 | 
			
		||||
#include <osmocom/gsupclient/gsup_client.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_utils.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gb_parse.h>
 | 
			
		||||
#include <osmocom/sgsn/gprs_gmm_fsm.h>
 | 
			
		||||
 | 
			
		||||
#include <osmocom/gprs/gprs_bssgp.h>
 | 
			
		||||
 | 
			
		||||
@@ -37,6 +38,7 @@
 | 
			
		||||
#include <osmocom/core/msgb.h>
 | 
			
		||||
#include <osmocom/core/rate_ctr.h>
 | 
			
		||||
#include <osmocom/core/utils.h>
 | 
			
		||||
#include <osmocom/vty/vty.h>
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
@@ -191,7 +193,6 @@ static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
 | 
			
		||||
 | 
			
		||||
	lle = gprs_lle_get_or_create(tlli, 3);
 | 
			
		||||
	ctx = sgsn_mm_ctx_alloc_gb(tlli, raid);
 | 
			
		||||
	ctx->gmm_state = GMM_REGISTERED_NORMAL;
 | 
			
		||||
	ctx->gb.llme = lle->llme;
 | 
			
		||||
 | 
			
		||||
	ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
 | 
			
		||||
@@ -1285,7 +1286,7 @@ static void test_gmm_cancel(void)
 | 
			
		||||
 | 
			
		||||
	ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid);
 | 
			
		||||
	OSMO_ASSERT(ctx != NULL);
 | 
			
		||||
	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
 | 
			
		||||
	OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);
 | 
			
		||||
 | 
			
		||||
	/* we expect an identity request (IMEI) */
 | 
			
		||||
	OSMO_ASSERT(sgsn_tx_counter == 1);
 | 
			
		||||
@@ -1305,7 +1306,7 @@ static void test_gmm_cancel(void)
 | 
			
		||||
	 * authorization */
 | 
			
		||||
	OSMO_ASSERT(ctx == sgsn_mm_ctx_by_tlli(foreign_tlli, &raid));
 | 
			
		||||
 | 
			
		||||
	OSMO_ASSERT(ctx->gmm_state == GMM_COMMON_PROC_INIT);
 | 
			
		||||
	OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_COMMON_PROC_INIT);
 | 
			
		||||
 | 
			
		||||
	/* we expect an attach accept/reject */
 | 
			
		||||
	OSMO_ASSERT(sgsn_tx_counter == 1);
 | 
			
		||||
@@ -1319,7 +1320,7 @@ static void test_gmm_cancel(void)
 | 
			
		||||
	send_0408_message(ctx->gb.llme, foreign_tlli, &raid,
 | 
			
		||||
			  attach_compl, ARRAY_SIZE(attach_compl));
 | 
			
		||||
 | 
			
		||||
	OSMO_ASSERT(ctx->gmm_state == GMM_REGISTERED_NORMAL);
 | 
			
		||||
	OSMO_ASSERT(ctx->gmm_fsm->state == ST_GMM_REGISTERED_NORMAL);
 | 
			
		||||
 | 
			
		||||
	/* we don't expect a response */
 | 
			
		||||
	OSMO_ASSERT(sgsn_tx_counter == 0);
 | 
			
		||||
@@ -1575,6 +1576,22 @@ static void test_ggsn_selection(void)
 | 
			
		||||
	cleanup_test();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t pdp_status_len);
 | 
			
		||||
 | 
			
		||||
static void test_pdp_status_has_active_nsapis(void)
 | 
			
		||||
{
 | 
			
		||||
	const size_t pdp_status_len = 2;
 | 
			
		||||
	const uint8_t pdp_status1[] = { 0b00100000, 0b00000000 }; /* PDP NSAPI 5 active */
 | 
			
		||||
	const uint8_t pdp_status2[] = { 0b00000000, 0b00000000 }; /* no active PDP NSAPI */
 | 
			
		||||
	const uint8_t pdp_status3[] = { 0b00000000, 0b00000001 }; /* PDP NSAPI 8 active */
 | 
			
		||||
 | 
			
		||||
	printf("Testing pdp_status_has_active_nsapis\n");
 | 
			
		||||
 | 
			
		||||
	OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status1, pdp_status_len));
 | 
			
		||||
	OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status2, pdp_status_len));
 | 
			
		||||
	OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status3, pdp_status_len));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct log_info_cat gprs_categories[] = {
 | 
			
		||||
	[DMM] = {
 | 
			
		||||
		.name = "DMM",
 | 
			
		||||
@@ -1630,6 +1647,10 @@ static struct log_info info = {
 | 
			
		||||
	.num_cat = ARRAY_SIZE(gprs_categories),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct vty_app_info vty_info = {
 | 
			
		||||
	.name 		= "testSGSN",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	void *osmo_sgsn_ctx;
 | 
			
		||||
@@ -1643,6 +1664,8 @@ int main(int argc, char **argv)
 | 
			
		||||
	sgsn_rate_ctr_init();
 | 
			
		||||
	sgsn_auth_init(sgsn);
 | 
			
		||||
	gprs_subscr_init(sgsn);
 | 
			
		||||
	vty_init(&vty_info);
 | 
			
		||||
	sgsn_vty_init(&sgsn->cfg);
 | 
			
		||||
 | 
			
		||||
	test_llme();
 | 
			
		||||
	test_subscriber();
 | 
			
		||||
@@ -1657,6 +1680,7 @@ int main(int argc, char **argv)
 | 
			
		||||
	test_gmm_cancel();
 | 
			
		||||
	test_apn_matching();
 | 
			
		||||
	test_ggsn_selection();
 | 
			
		||||
	test_pdp_status_has_active_nsapis();
 | 
			
		||||
	printf("Done\n");
 | 
			
		||||
 | 
			
		||||
	talloc_report_full(osmo_sgsn_ctx, stderr);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,4 +24,5 @@ Testing GMM reject
 | 
			
		||||
Testing cancellation
 | 
			
		||||
Testing APN matching
 | 
			
		||||
Testing GGSN selection
 | 
			
		||||
Testing pdp_status_has_active_nsapis
 | 
			
		||||
Done
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ noinst_PROGRAMS = slhc_test
 | 
			
		||||
slhc_test_SOURCES = slhc_test.c
 | 
			
		||||
 | 
			
		||||
slhc_test_LDADD = \
 | 
			
		||||
	$(top_builddir)/src/gprs/slhc.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/slhc.o \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ noinst_PROGRAMS = sndcp_xid_test
 | 
			
		||||
sndcp_xid_test_SOURCES = sndcp_xid_test.c
 | 
			
		||||
 | 
			
		||||
sndcp_xid_test_LDADD = \
 | 
			
		||||
	$(top_builddir)/src/gprs/gprs_sndcp_xid.o \
 | 
			
		||||
	$(top_builddir)/src/sgsn/gprs_sndcp_xid.o \
 | 
			
		||||
	$(LIBOSMOABIS_LIBS) \
 | 
			
		||||
	$(LIBOSMOCORE_LIBS) \
 | 
			
		||||
	$(LIBOSMOGSM_LIBS) \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										63
									
								
								tests/test_nodes.vty
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								tests/test_nodes.vty
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
OsmoSGSN> enable
 | 
			
		||||
OsmoSGSN# show timer
 | 
			
		||||
T3312 = 600 s	Periodic RA Update timer (s) (default: 600 s)
 | 
			
		||||
T3313 = 30 s	Waiting for paging response timer (s) (default: 30 s)
 | 
			
		||||
T3314 = 44 s	READY timer. Force to STANDBY on expiry timer (s) (default: 44 s)
 | 
			
		||||
T3316 = 44 s	AA-Ready timer (s) (default: 44 s)
 | 
			
		||||
T3322 = 6 s	Detach request -> accept timer (s) (default: 6 s)
 | 
			
		||||
T3350 = 6 s	Waiting for ATT/RAU/TMSI_COMPL timer (s) (default: 6 s)
 | 
			
		||||
T3360 = 6 s	Waiting for AUTH/CIPH response timer (s) (default: 6 s)
 | 
			
		||||
T3370 = 6 s	Waiting for IDENTITY response timer (s) (default: 6 s)
 | 
			
		||||
T3385 = 8 s	Wait for ACT PDP CTX REQ timer (s) (default: 8 s)
 | 
			
		||||
T3386 = 8 s	Wait for MODIFY PDP CTX ACK timer (s) (default: 8 s)
 | 
			
		||||
T3395 = 8 s	Wait for DEACT PDP CTX ACK timer (s) (default: 8 s)
 | 
			
		||||
T3397 = 8 s	Wait for DEACT AA PDP CTX ACK timer (s) (default: 8 s)
 | 
			
		||||
X1001 = 5 s	RANAP Release timeout. Wait for RANAP Release Complete.On expiry release Iu connection (s) (default: 5 s)
 | 
			
		||||
X3314 = 44 s	Iu User inactivity timer. On expiry release Iu connection (s) (default: 44 s)
 | 
			
		||||
OsmoSGSN# configure terminal
 | 
			
		||||
OsmoSGSN(config)# list
 | 
			
		||||
...
 | 
			
		||||
  sgsn
 | 
			
		||||
  ctrl
 | 
			
		||||
...
 | 
			
		||||
  ns
 | 
			
		||||
  bssgp
 | 
			
		||||
...
 | 
			
		||||
 | 
			
		||||
OsmoSGSN(config)# sgsn
 | 
			
		||||
OsmoSGSN(config-sgsn)# list
 | 
			
		||||
...
 | 
			
		||||
  gtp local-ip A.B.C.D
 | 
			
		||||
  ggsn <0-255> remote-ip A.B.C.D
 | 
			
		||||
  ggsn <0-255> gtp-version (0|1)
 | 
			
		||||
  ggsn <0-255> echo-interval <1-36000>
 | 
			
		||||
  ggsn <0-255> no echo-interval
 | 
			
		||||
  imsi-acl (add|del) IMSI
 | 
			
		||||
  auth-policy (accept-all|closed|acl-only|remote)
 | 
			
		||||
  authentication (optional|required)
 | 
			
		||||
  encryption (GEA0|GEA1|GEA2|GEA3|GEA4)
 | 
			
		||||
  gsup ipa-name NAME
 | 
			
		||||
  gsup remote-ip A.B.C.D
 | 
			
		||||
  gsup remote-port <0-65535>
 | 
			
		||||
  gsup oap-id <0-65535>
 | 
			
		||||
  gsup oap-k K
 | 
			
		||||
  gsup oap-opc OPC
 | 
			
		||||
  apn APNAME ggsn <0-255>
 | 
			
		||||
  apn APNAME imsi-prefix IMSIPRE ggsn <0-255>
 | 
			
		||||
  access-point-name NAME
 | 
			
		||||
  no access-point-name NAME
 | 
			
		||||
  cdr filename NAME
 | 
			
		||||
  no cdr filename
 | 
			
		||||
  cdr trap
 | 
			
		||||
  no cdr trap
 | 
			
		||||
  cdr interval <1-2147483647>
 | 
			
		||||
  ggsn dynamic
 | 
			
		||||
  grx-dns-add A.B.C.D
 | 
			
		||||
  timer [TNNNN] [(<0-2147483647>|default)]
 | 
			
		||||
  no compression rfc1144
 | 
			
		||||
  compression rfc1144 active slots <1-256>
 | 
			
		||||
  compression rfc1144 passive
 | 
			
		||||
  no compression v42bis
 | 
			
		||||
  compression v42bis active direction (ms|sgsn|both) codewords <512-65535> strlen <6-250>
 | 
			
		||||
  compression v42bis passive
 | 
			
		||||
...
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user