From e91b57d963846fe1629c7fb12924f2c676964c92 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 4 Jan 2022 16:59:23 +0100 Subject: [PATCH] Drop osmo-hnbgw OsmoHNBGW is now available in its own repository osmo-hnbgw.git. Change-Id: I4e17c578b432f0c997ea4e13b1c468b112278854 --- Makefile.am | 2 +- README.md | 12 +- configure.ac | 4 - contrib/Makefile.am | 1 - contrib/osmo-iuh.spec.in | 13 - contrib/systemd/Makefile.am | 6 - contrib/systemd/osmo-hnbgw.service | 11 - debian/control | 24 - debian/osmo-hnbgw.install | 4 - debian/rules | 1 - doc/Makefile.am | 3 - doc/examples/Makefile.am | 27 - doc/examples/osmo-hnbgw.cfg | 25 - doc/manuals/Makefile.am | 25 - doc/manuals/chapters/overview.adoc | 56 -- doc/manuals/chapters/running.adoc | 119 ---- doc/manuals/osmohnbgw-usermanual-docinfo.xml | 51 -- doc/manuals/osmohnbgw-usermanual.adoc | 37 - doc/manuals/osmohnbgw-vty-reference.xml | 38 - doc/manuals/regen_doc.sh | 17 - doc/manuals/vty/hnbgw_vty_additions.xml | 2 - doc/protocols_around_hnbgw.txt | 60 -- include/osmocom/iuh/Makefile.am | 4 +- include/osmocom/iuh/context_map.h | 51 -- include/osmocom/iuh/hnbgw.h | 174 ----- include/osmocom/iuh/hnbgw_cn.h | 5 - include/osmocom/iuh/hnbgw_hnbap.h | 6 - include/osmocom/iuh/hnbgw_ranap.h | 6 - include/osmocom/iuh/hnbgw_rua.h | 13 - include/osmocom/iuh/vty.h | 11 - src/Makefile.am | 14 - src/context_map.c | 181 ----- src/hnbgw.c | 698 ------------------- src/hnbgw_cn.c | 559 --------------- src/hnbgw_hnbap.c | 632 ----------------- src/hnbgw_ranap.c | 210 ------ src/hnbgw_rua.c | 566 --------------- src/hnbgw_vty.c | 418 ----------- 38 files changed, 5 insertions(+), 4081 deletions(-) delete mode 100644 contrib/Makefile.am delete mode 100644 contrib/systemd/Makefile.am delete mode 100644 contrib/systemd/osmo-hnbgw.service delete mode 100644 debian/osmo-hnbgw.install delete mode 100644 doc/examples/Makefile.am delete mode 100644 doc/examples/osmo-hnbgw.cfg delete mode 100644 doc/manuals/Makefile.am delete mode 100644 doc/manuals/chapters/overview.adoc delete mode 100644 doc/manuals/chapters/running.adoc delete mode 100644 doc/manuals/osmohnbgw-usermanual-docinfo.xml delete mode 100644 doc/manuals/osmohnbgw-usermanual.adoc delete mode 100644 doc/manuals/osmohnbgw-vty-reference.xml delete mode 100755 doc/manuals/regen_doc.sh delete mode 100644 doc/manuals/vty/hnbgw_vty_additions.xml delete mode 100644 doc/protocols_around_hnbgw.txt delete mode 100644 include/osmocom/iuh/context_map.h delete mode 100644 include/osmocom/iuh/hnbgw.h delete mode 100644 include/osmocom/iuh/hnbgw_cn.h delete mode 100644 include/osmocom/iuh/hnbgw_hnbap.h delete mode 100644 include/osmocom/iuh/hnbgw_ranap.h delete mode 100644 include/osmocom/iuh/hnbgw_rua.h delete mode 100644 include/osmocom/iuh/vty.h delete mode 100644 src/context_map.c delete mode 100644 src/hnbgw.c delete mode 100644 src/hnbgw_cn.c delete mode 100644 src/hnbgw_hnbap.c delete mode 100644 src/hnbgw_ranap.c delete mode 100644 src/hnbgw_rua.c delete mode 100644 src/hnbgw_vty.c diff --git a/Makefile.am b/Makefile.am index f40cbd1a..c1359a13 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS = foreign dist-bzip2 -SUBDIRS = src include doc contrib +SUBDIRS = src include doc pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libosmo-hnbap.pc libosmo-ranap.pc libosmo-rua.pc libosmo-sabp.pc diff --git a/README.md b/README.md index 984ac857..c0d7baee 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ -osmo-iuh - Osmocom Iuh and HNB-GW implementation +osmo-iuh - Osmocom Iuh implementation ================================================ This repository contains a C-language implementation of the 3GPP Iuh -interface, together with a HNB-GW (Home NodeB Gateway). You can use it -to interface Iuh-speaking femtocells/small cells to Iu-speaking MSCs and -SGSNs. +interface. You can use it to interface Iuh-speaking femtocells/small cells to +Iu-speaking MSCs and SGSNs. It is part of the [Osmocom](https://osmocom.org/) Open Source Mobile Communications project. @@ -87,11 +86,6 @@ Using Note: osmo-iuh just left very active development (December 2015, January 2016), so your mileage may vary. -If you run the 'hnbgw' executable, it will open a listening SCTP socket -and wait for incoming Iuh connections. It will accept any -HNB-REGISTER-REQUEST, and it will establish Iu (over SUA) connections -towards the MSC and SGSN. - Regenerating C code from ASN.1 source ------------------------------------- diff --git a/configure.ac b/configure.ac index 5490348e..b16f3d28 100644 --- a/configure.ac +++ b/configure.ac @@ -169,9 +169,5 @@ AC_OUTPUT( include/osmocom/sabp/Makefile include/osmocom/iuh/Makefile doc/Makefile - doc/examples/Makefile - doc/manuals/Makefile - contrib/Makefile - contrib/systemd/Makefile contrib/osmo-iuh.spec ) diff --git a/contrib/Makefile.am b/contrib/Makefile.am deleted file mode 100644 index 3439c97b..00000000 --- a/contrib/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = systemd diff --git a/contrib/osmo-iuh.spec.in b/contrib/osmo-iuh.spec.in index 977d35c2..e542533d 100644 --- a/contrib/osmo-iuh.spec.in +++ b/contrib/osmo-iuh.spec.in @@ -138,22 +138,9 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +) %post -n libosmo-sabp1 -p /sbin/ldconfig %postun -n libosmo-sabp1 -p /sbin/ldconfig -%if 0%{?suse_version} -%pre %service_add_pre osmo-hnbgw.service -%post %service_add_post osmo-hnbgw.service -%preun %service_del_preun osmo-hnbgw.service -%postun %service_del_postun osmo-hnbgw.service -%endif - %files %license COPYING %doc README.md -%dir %{_docdir}/%{name}/examples -%{_docdir}/%{name}/examples/osmo-hnbgw.cfg -%{_bindir}/osmo-hnbgw -%dir %{_sysconfdir}/osmocom -%config %{_sysconfdir}/osmocom/osmo-hnbgw.cfg -%{_unitdir}/osmo-hnbgw.service %files -n libosmo-hnbap0 %{_libdir}/libosmo-hnbap.so.0* diff --git a/contrib/systemd/Makefile.am b/contrib/systemd/Makefile.am deleted file mode 100644 index 212601c0..00000000 --- a/contrib/systemd/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -EXTRA_DIST = osmo-hnbgw.service - -if HAVE_SYSTEMD -systemdsystemunit_DATA = \ - osmo-hnbgw.service -endif diff --git a/contrib/systemd/osmo-hnbgw.service b/contrib/systemd/osmo-hnbgw.service deleted file mode 100644 index 7aca29fd..00000000 --- a/contrib/systemd/osmo-hnbgw.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Osmocom Home Nodeb Gateway (OsmoHNBGW) - -[Service] -Type=simple -Restart=always -ExecStart=/usr/bin/osmo-hnbgw -c /etc/osmocom/osmo-hnbgw.cfg -RestartSec=2 - -[Install] -WantedBy=multi-user.target diff --git a/debian/control b/debian/control index cceef39d..c9d7cbbd 100644 --- a/debian/control +++ b/debian/control @@ -21,30 +21,6 @@ Vcs-Git: git://git.osmocom.org/osmo-iuh.git Vcs-Browser: https://git.osmocom.org/osmo-iuh/ Homepage: https://projects.osmocom.org/projects/osmohnbgw -Package: osmo-hnbgw -Section: net -Architecture: any -Multi-Arch: no -Pre-Depends: ${misc:Pre-Depends} -Depends: ${misc:Depends}, ${shlibs:Depends} -Description: osmocom Home Node B Gateway - -Package: osmo-hnbgw-dbg -Section: debug -Architecture: any -Multi-Arch: no -Pre-Depends: ${misc:Pre-Depends} -Depends: osmo-hnbgw (= ${binary:Version}), ${misc:Depends} -Description: osmocom Home Node B Gateway - -Package: osmo-hnbgw-doc -Section: doc -Architecture: all -Depends: ${misc:Depends} -Description: ${misc:Package} PDF documentation - Various manuals: user manual, VTY reference manual and/or - protocol/interface manuals. - Package: libosmo-hnbap0 Section: libs Architecture: any diff --git a/debian/osmo-hnbgw.install b/debian/osmo-hnbgw.install deleted file mode 100644 index f040f23f..00000000 --- a/debian/osmo-hnbgw.install +++ /dev/null @@ -1,4 +0,0 @@ -etc/osmocom/osmo-hnbgw.cfg -lib/systemd/system/osmo-hnbgw.service -usr/bin/osmo-hnbgw -usr/share/doc/osmo-iuh/examples/osmo-hnbgw.cfg diff --git a/debian/rules b/debian/rules index 9db7204b..d1b2ab62 100755 --- a/debian/rules +++ b/debian/rules @@ -18,7 +18,6 @@ override_dh_strip: dh_strip -plibosmo-ranap5 --dbg-package=libosmo-ranap-dbg dh_strip -plibosmo-rua0 --dbg-package=libosmo-rua-dbg dh_strip -plibosmo-sabp1 --dbg-package=libosmo-sabp-dbg - dh_strip -posmo-hnbgw --dbg-package=osmo-hnbgw-dbg # Print test results in case of a failure override_dh_auto_test: diff --git a/doc/Makefile.am b/doc/Makefile.am index eeed8752..e8a44b97 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,6 +1,4 @@ SUBDIRS = \ - examples \ - manuals \ $(NULL) EXTRA_DIST = \ @@ -11,5 +9,4 @@ EXTRA_DIST = \ hnb_cs_mt_sms.msc \ hnb_ps_lu.msc \ hnb_ps_pdp_act.msc \ - protocols_around_hnbgw.txt \ README diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am deleted file mode 100644 index 7441d483..00000000 --- a/doc/examples/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -osmoconfdir = $(sysconfdir)/osmocom -osmoconf_DATA = osmo-hnbgw.cfg - -EXTRA_DIST = osmo-hnbgw.cfg - -CFG_FILES = find $(srcdir) -name '*.cfg*' | sed -e 's,^$(srcdir),,' - -dist-hook: - for f in $$($(CFG_FILES)); do \ - j="$(distdir)/$$f" && \ - mkdir -p "$$(dirname $$j)" && \ - $(INSTALL_DATA) $(srcdir)/$$f $$j; \ - done - -install-data-hook: - for f in $$($(CFG_FILES)); do \ - j="$(DESTDIR)$(docdir)/examples/$$f" && \ - mkdir -p "$$(dirname $$j)" && \ - $(INSTALL_DATA) $(srcdir)/$$f $$j; \ - done - -uninstall-hook: - @$(PRE_UNINSTALL) - for f in $$($(CFG_FILES)); do \ - j="$(DESTDIR)$(docdir)/examples/$$f" && \ - $(RM) $$j; \ - done diff --git a/doc/examples/osmo-hnbgw.cfg b/doc/examples/osmo-hnbgw.cfg deleted file mode 100644 index 9286b2a0..00000000 --- a/doc/examples/osmo-hnbgw.cfg +++ /dev/null @@ -1,25 +0,0 @@ -! -! OsmoHNBGW (0) configuration saved from vty -!! -! -log stderr - logging filter all 1 - logging color 1 - logging print category 1 - logging timestamp 1 - logging print extended-timestamp 1 - logging level all debug - logging level lglobal notice - logging level llapd notice - logging level linp notice - logging level lmux notice - logging level lmi notice - logging level lmib notice - logging level lsms notice - logging level lctrl notice - logging level lgtp notice - logging level lstats notice -hnbgw - iuh - local-ip 0.0.0.0 - hnbap-allow-tmsi 1 diff --git a/doc/manuals/Makefile.am b/doc/manuals/Makefile.am deleted file mode 100644 index 595f1570..00000000 --- a/doc/manuals/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -EXTRA_DIST = \ - osmohnbgw-usermanual.adoc \ - osmohnbgw-usermanual-docinfo.xml \ - chapters \ - osmohnbgw-vty-reference.xml \ - regen_doc.sh \ - vty - -if BUILD_MANUALS - ASCIIDOC = osmohnbgw-usermanual.adoc - ASCIIDOC_DEPS = $(srcdir)/chapters/*.adoc - include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc - - VTY_REFERENCE = osmohnbgw-vty-reference.xml - - BUILT_REFERENCE_XML = $(builddir)/vty/hnbgw_vty_reference.xml - $(builddir)/vty/hnbgw_vty_reference.xml: $(top_builddir)/src/osmo-hnbgw - mkdir -p $(builddir)/vty - $(top_builddir)/src/osmo-hnbgw --vty-ref-xml > $@ - - include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc - - OSMO_REPOSITORY = osmo-hnbgw - include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc -endif diff --git a/doc/manuals/chapters/overview.adoc b/doc/manuals/chapters/overview.adoc deleted file mode 100644 index 2368b4ff..00000000 --- a/doc/manuals/chapters/overview.adoc +++ /dev/null @@ -1,56 +0,0 @@ -[[overview]] -== Overview - - -[[intro_overview]] -=== About OsmoHNBGW - -OsmoHNBGW implements the Home NodeB Gateway function in the 3G network architecture. It serves -as a gateway between the classic 3G core network (CN) domain with its IuCS and IuPS interface -and the femtocell based RAN. - -A typical 3G network consisting of Osmocom components will look as illustrated in the following -diagram: - -[[fig-3g]] -.Typical 3G network architecture used with OsmoHNBGW ----- - +------------+ +--------+ +----------+ +---------+ - UE <-->| hNodeB |<--Iuh---->| HNB-GW |<--IuCS-->| OsmoMSC |<--GSUP-->| OsmoHLR | - UE <-->| femto cell | ...-->| | ...-->| | | | - | | | | +----------+ +---------| - +------------+<--GTP-U | | - \ | | +------+ +------+ - | | |<--IuPS-->| SGSN |<--GTP-C-->| GGSN | - | +--------+ ...-->| | GTP-U-->| | - | +------+ / +------+ - \_______________________________/ ----- - -The HNB-GW performs a translation interface between the IuCS/IuPS interfaces on the one hand -side, and the Iuh interface on the or ther hand: - ----- - Iuh IuCS/IuPS - -NAS +----+----+ +----+----+ -Non-Access Stratum | CC | MM | | CC | MM | -- - - - - - - - - - - +----+----+-------+ +----+----+ - | RANAP | | H | RANAP | -Access Stratum +---------+ HNBAP | N +---------+ - - SCCP USER SAP - | RUA | | B | SUA | \ - +---------+-------+ - +---------+ | - | SCTP | G | SCTP | } SIGTRAN - +-----------------+ W +---------+ | - | IP | | IP | / - +-----------------+ +---------+ ----- - -On the femtocell (Home NodeB) side, OsmoHNBGW implements the Iuh interface as specified by 3GPP. - -=== The Iuh interface - -Iuh consists of the following sub-layers: - -- HNBAP (Home NodeB Application Part) -- RUA (RANAP User Adaptation, between RANAP and SCTP diff --git a/doc/manuals/chapters/running.adoc b/doc/manuals/chapters/running.adoc deleted file mode 100644 index f40027a6..00000000 --- a/doc/manuals/chapters/running.adoc +++ /dev/null @@ -1,119 +0,0 @@ -== Running OsmoHNBGW - -The OsmoHNBGW executable (`osmo-hnbgw`) offers the following command-line -arguments: - -=== SYNOPSIS - -*osmo-hnbgw* [-h|-V] [-d 'DBGMASK'] [-D] [-c 'CONFIGFILE'] [-s] [-T] [-e 'LOGLEVEL'] - -=== OPTIONS - -*-h, --help*:: - Print a short help message about the supported options -*-V, --version*:: - Print the compile-time version number of the OsmoHNBGW 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 <> 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-msc.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 <> - for more information. -*-T, --timestamp*:: - Enable time-stamping of log messages to stderr. This has mostly - been deprecated by VTY based logging configuration, see - <> 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 - <> for more information. - - -=== Multiple instances - -Running multiple instances of `osmo-hnbgw` on the same computer is possible if -all interfaces (VTY, CTRL, Iuh) are separated using the appropriate -configuration options. The IP based interfaces are binding to local host by -default. In order to separate the processes, the user has to bind those -services to specific but different IP addresses and/or ports. - -The VTY and the Control interface can be bound to IP addresses from the loopback -address range, for example: - ----- -line vty - bind 127.0.0.2 -ctrl - bind 127.0.0.2 ----- - -The Iuh interface can be bound to an individual port: - ----- -hnbgw - iuh - local-ip 0.0.0.0 - local-port 29169 ----- - -For the following links, OsmoHNBGW acts as a client and does not listen/bind to a -specific interface, and will hence not encounter conflicts for multiple instances -running on the same interface: - -- The SCCP/M3UA links are established by OsmoHNBGW contacting an STP. - -To run multiple OsmoHNBGW instances on the same SCCP routing, each HNBGW has to -configure a distinct point-code, see <>. - - -=== Configuring Primary Links - -[[configure_iucs_iups]] -==== Configure SCCP/M3UA to connect to an MSC's _IuCS_ and an SGSN's _IuPS_ interface - -OsmoHNBGW acts as client to contact an STP instance and establish an SCCP/M3UA -link. - -An example configuration of OsmoHNBGW's SCCP link: - ----- -cs7 instance 0 - point-code 0.23.5 - asp asp-clnt-OsmoHNBGW 2905 0 m3ua - remote-ip 127.0.0.1 - sctp-role client - sccp-address msc - routing-indicator PC - point-code 0.23.1 - sccp-address sgsn - routing-indicator PC - point-code 0.23.2 -hnbgw - iucs - remote-addr msc - iups - remote-addr sgsn ----- - -This configuration is explained in detail in <>. - -==== Configure RUA to accept Iuh connections from hNodeB - -OsmoHNBGW acts as server to accept Iuh connections from hNodeB devices. - -An example configuration for OsmoHNBGW's RUA server: - ----- -hnbgw - iuh - local-ip 10.9.8.7 - local-port 29169 ----- diff --git a/doc/manuals/osmohnbgw-usermanual-docinfo.xml b/doc/manuals/osmohnbgw-usermanual-docinfo.xml deleted file mode 100644 index 404d2a1e..00000000 --- a/doc/manuals/osmohnbgw-usermanual-docinfo.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - 1 - November 30th, 2019 - HW - - Initial version - - - - - - - Harald - Welte - hwelte@sysmocom.de - HW - - sysmocom - sysmocom - s.f.m.c. GmbH - Managing Director - - - - - - 2019 - sysmocom - s.f.m.c. GmbH - - - - - 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 the Invariant Sections being just 'Foreword', - 'Acknowledgements' and 'Preface', with no Front-Cover Texts, - and no Back-Cover Texts. A copy of the license is included in - the section entitled "GNU Free Documentation License". - - - The Asciidoc source code of this manual can be found at - - http://git.osmocom.org/osmo-hnbgw/ - - and of the common chapters at - - http://git.osmocom.org/osmo-gsm-manuals/ - - - diff --git a/doc/manuals/osmohnbgw-usermanual.adoc b/doc/manuals/osmohnbgw-usermanual.adoc deleted file mode 100644 index 21faed7b..00000000 --- a/doc/manuals/osmohnbgw-usermanual.adoc +++ /dev/null @@ -1,37 +0,0 @@ -:gfdl-enabled: -:program-name: OsmoHNBGW - -OsmoHNBGW User Manual -===================== -Harald Welte - - -include::./common/chapters/preface.adoc[] - -include::{srcdir}/chapters/overview.adoc[] - -include::{srcdir}/chapters/running.adoc[] - -// include::{srcdir}/chapters/control.adoc[] - -// include::./common/chapters/counters-overview.adoc[] - -// include::{srcdir}/chapters/counters.adoc[] - -include::./common/chapters/vty.adoc[] - -include::./common/chapters/logging.adoc[] - -include::./common/chapters/cs7-config.adoc[] - -// include::{srcdir}/chapters/net.adoc[] - -// include::./common/chapters/control_if.adoc[] - -include::./common/chapters/port_numbers.adoc[] - -include::./common/chapters/bibliography.adoc[] - -include::./common/chapters/glossary.adoc[] - -include::./common/chapters/gfdl.adoc[] diff --git a/doc/manuals/osmohnbgw-vty-reference.xml b/doc/manuals/osmohnbgw-vty-reference.xml deleted file mode 100644 index cd693333..00000000 --- a/doc/manuals/osmohnbgw-vty-reference.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - -]> - - - - - - v1 - 29th July 2019 - dw - Initial - - - - OsmoHNBGW VTY Reference - - - 2019 - - - - This work is copyright by sysmocom - s.f.m.c. GmbH. All rights reserved. - - - - - - &chapter-vty; - - diff --git a/doc/manuals/regen_doc.sh b/doc/manuals/regen_doc.sh deleted file mode 100755 index 39dd9eee..00000000 --- a/doc/manuals/regen_doc.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -x - -if [ -z "$DOCKER_PLAYGROUND" ]; then - echo "You need to set DOCKER_PLAYGROUND" - exit 1 -fi - -SCRIPT=$(realpath "$0") -MANUAL_DIR=$(dirname "$SCRIPT") - -COMMIT=${COMMIT:-$(git log -1 --format=format:%H)} - -cd "$DOCKER_PLAYGROUND/scripts" || exit 1 - -OSMO_SGSN_BRANCH=$COMMIT ./regen_doc.sh osmo-hnbgw 4261 \ - "$MANUAL_DIR/chapters/counters_generated.adoc" \ - "$MANUAL_DIR/vty/hnbgw_vty_reference.xml" diff --git a/doc/manuals/vty/hnbgw_vty_additions.xml b/doc/manuals/vty/hnbgw_vty_additions.xml deleted file mode 100644 index a4c675e8..00000000 --- a/doc/manuals/vty/hnbgw_vty_additions.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/doc/protocols_around_hnbgw.txt b/doc/protocols_around_hnbgw.txt deleted file mode 100644 index 3eef1557..00000000 --- a/doc/protocols_around_hnbgw.txt +++ /dev/null @@ -1,60 +0,0 @@ -Protocols Around the Home Node B Gateway -======================================== - - +--------+ - ,-->| Osmo | - / | MGCPGW | - | | |<--MGCP - | +--------+ \ - / | - +------------+<--RTP +--------+ `->+----------+ - UE <-->| hNodeB | | Osmo | | OsmoMSC | +------+ - UE <-->| femto cell |<--Iuh---->| HNB-GW |<--IuCS-->| | | Osmo | - | | | | | (VLR)|<-GSUP->| HLR | - | | | | +----------+ GSUP->+------+ - +------------+<--GTP-U | | / - \ | | +------+<---' +------+ - | | |<--IuPS-->| Osmo |<--GTP-C--->| Open | - | +--------+ | SGSN | GTP-U--->| GGSN | - | +------+ / +------+ - \_______________________________/ - - - - Iuh IuCS/IuPS - -NAS +----+----+ +----+----+ -Non-Access Stratum | CC | MM | | CC | MM | -- - - - - - - - - - - +----+----+-------+ +----+----+ - | RANAP | | H | RANAP | -Access Stratum +---------+ HNBAP | N +---------+ - - SCCP USER SAP - | RUA | | B | SUA | \ - +---------+-------+ - +---------+ | - | SCTP | G | SCTP | } SIGTRAN - +-----------------+ W +---------+ | - | IP | | IP | / - +-----------------+ +---------+ - - -Various SIGTRAN implementations: - - IuCS/IuPS - usual - | simplest - | | - v v - +------+------+------+-----+ - | SCCP | SCCP | | | - +------+------+ SCCP | | - | MTP3 | MTP3 | | | - +------+------+------+ SUA | - | MTP2 | | | | - +------+ M2UA | M3UA | | - | M2PA | | | | - +------+------+------+-----+ - | SCTP | - +--------------------------+ - | IP | - +--------------------------+ - -UE (User Endpoint) == MS (Mobile Subscriber) == mobile device diff --git a/include/osmocom/iuh/Makefile.am b/include/osmocom/iuh/Makefile.am index b2a667d2..e5dff0dc 100644 --- a/include/osmocom/iuh/Makefile.am +++ b/include/osmocom/iuh/Makefile.am @@ -1,4 +1,2 @@ noinst_HEADERS = \ - vty.h \ - context_map.h hnbgw.h hnbgw_cn.h \ - hnbgw_hnbap.h hnbgw_rua.h hnbgw_ranap.h + iu_common.h diff --git a/include/osmocom/iuh/context_map.h b/include/osmocom/iuh/context_map.h deleted file mode 100644 index 6279b91e..00000000 --- a/include/osmocom/iuh/context_map.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include -#include - -enum hnbgw_context_map_state { - MAP_S_NULL, - MAP_S_ACTIVE, /* currently active map */ - MAP_S_RESERVED1, /* just disconnected, still resrved */ - MAP_S_RESERVED2, /* still reserved */ - MAP_S_NUM_STATES /* Number of states, keep this at the end */ -}; - -extern const struct value_string hnbgw_context_map_state_names[]; -static inline const char *hnbgw_context_map_state_name(enum hnbgw_context_map_state val) -{ return get_value_string(hnbgw_context_map_state_names, val); } - -struct hnb_context; -struct hnbgw_cnlink; - -struct hnbgw_context_map { - /* entry in the per-CN list of mappings */ - struct llist_head cn_list; - /* entry in the per-HNB list of mappings */ - struct llist_head hnb_list; - /* pointer to HNB */ - struct hnb_context *hnb_ctx; - /* pointer to CN */ - struct hnbgw_cnlink *cn_link; - /* RUA contxt ID */ - uint32_t rua_ctx_id; - /* False for CS, true for PS */ - bool is_ps; - /* SCCP User SAP connection ID */ - uint32_t scu_conn_id; - - enum hnbgw_context_map_state state; -}; - - -struct hnbgw_context_map * -context_map_alloc_by_hnb(struct hnb_context *hnb, uint32_t rua_ctx_id, - bool is_ps, - struct hnbgw_cnlink *cn_if_new); - -struct hnbgw_context_map * -context_map_by_cn(struct hnbgw_cnlink *cn, uint32_t scu_conn_id); - -void context_map_deactivate(struct hnbgw_context_map *map); - -int context_map_init(struct hnb_gw *gw); diff --git a/include/osmocom/iuh/hnbgw.h b/include/osmocom/iuh/hnbgw.h deleted file mode 100644 index fc8298dc..00000000 --- a/include/osmocom/iuh/hnbgw.h +++ /dev/null @@ -1,174 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#define DEBUG -#include - - -enum { - DMAIN, - DHNBAP, - DRUA, - DRANAP, -}; - -#define LOGHNB(x, ss, lvl, fmt, args ...) \ - LOGP(ss, lvl, "%s " fmt, hnb_context_name(x), ## args) - -enum hnb_ctrl_node { - CTRL_NODE_HNB = _LAST_CTRL_NODE, - _LAST_CTRL_NODE_HNB -}; - -#define HNBGW_LOCAL_IP_DEFAULT "0.0.0.0" -/* TODO: CS and PS now both connect to OsmoSTP, i.e. that's always going to be the same address. Drop the - * duplicity. */ -#define HNBGW_IUCS_REMOTE_IP_DEFAULT "127.0.0.1" -#define HNBGW_IUPS_REMOTE_IP_DEFAULT "127.0.0.1" - -/* 25.467 Section 7.1 */ -#define IUH_DEFAULT_SCTP_PORT 29169 -#define RNA_DEFAULT_SCTP_PORT 25471 - -#define IUH_PPI_RUA 19 -#define IUH_PPI_HNBAP 20 -#define IUH_PPI_SABP 31 -#define IUH_PPI_RNA 42 -#define IUH_PPI_PUA 55 - -#define IUH_MSGB_SIZE 2048 - -struct umts_cell_id { - uint16_t mcc; /*!< Mobile Country Code */ - uint16_t mnc; /*!< Mobile Network Code */ - uint16_t lac; /*!< Locaton Area Code */ - uint16_t rac; /*!< Routing Area Code */ - uint16_t sac; /*!< Service Area Code */ - uint32_t cid; /*!< Cell ID */ -}; - -struct hnb_gw; - -enum hnbgw_cnlink_state { - /* we have just been initialized or were disconnected */ - CNLINK_S_NULL, - /* establishment of the SUA/SCCP link is pending */ - CNLINK_S_EST_PEND, - /* establishment of the SUA/SCCP link was confirmed */ - CNLINK_S_EST_CONF, - /* we have esnt the RANAP RESET and wait for the ACK */ - CNLINK_S_EST_RST_TX_WAIT_ACK, - /* we have received the RANAP RESET ACK and are active */ - CNLINK_S_EST_ACTIVE, -}; - -struct hnbgw_cnlink { - struct llist_head list; - enum hnbgw_cnlink_state state; - struct hnb_gw *gw; - /* timer for re-transmitting the RANAP Reset */ - struct osmo_timer_list T_RafC; - /* reference to the SCCP User SAP by which we communicate */ - struct osmo_sccp_instance *sccp; - struct osmo_sccp_user *sccp_user; - uint32_t next_conn_id; - - /* linked list of hnbgw_context_map */ - struct llist_head map_list; -}; - -struct hnb_context { - /*! Entry in HNB-global list of HNB */ - struct llist_head list; - /*! HNB-GW we are part of */ - struct hnb_gw *gw; - /*! SCTP socket + write queue for Iuh to this specific HNB */ - struct osmo_stream_srv *conn; - /*! copied from HNB-Identity-Info IE */ - char identity_info[256]; - /*! copied from Cell Identity IE */ - struct umts_cell_id id; - - /*! SCTP stream ID for HNBAP */ - uint16_t hnbap_stream; - /*! SCTP stream ID for RUA */ - uint16_t rua_stream; - - /*! True if a HNB-REGISTER-REQ from this HNB has been accepted. Note that - * this entire data structure is freed if the HNB sends HNB-DE-REGISTER-REQ. */ - bool hnb_registered; - - /* linked list of hnbgw_context_map */ - struct llist_head map_list; -}; - -struct ue_context { - /*! Entry in the HNB-global list of UE */ - struct llist_head list; - /*! Unique Context ID for this UE */ - uint32_t context_id; - char imsi[16+1]; - uint32_t tmsi; - /*! UE is serviced via this HNB */ - struct hnb_context *hnb; -}; - -struct hnb_gw { - struct { - const char *iuh_local_ip; - /*! SCTP port for Iuh listening */ - uint16_t iuh_local_port; - /*! The UDP port where we receive multiplexed CS user - * plane traffic from HNBs */ - uint16_t iuh_cs_mux_port; - const char *iucs_remote_addr_name; - const char *iups_remote_addr_name; - uint16_t rnc_id; - bool hnbap_allow_tmsi; - /*! print hnb-id (true) or MCC-MNC-LAC-RAC-SAC (false) in logs */ - bool log_prefix_hnb_id; - } config; - /*! SCTP listen socket for incoming connections */ - struct osmo_stream_srv_link *iuh; - /* list of struct hnb_context */ - struct llist_head hnb_list; - /* list of struct ue_context */ - struct llist_head ue_list; - /* next availble UE Context ID */ - uint32_t next_ue_ctx_id; - struct ctrl_handle *ctrl; - /* currently active CN links for CS and PS */ - struct { - struct osmo_sccp_instance *client; - struct hnbgw_cnlink *cnlink; - struct osmo_sccp_addr local_addr; - struct osmo_sccp_addr iucs_remote_addr; - struct osmo_sccp_addr iups_remote_addr; - } sccp; -}; - -extern void *talloc_asn1_ctx; - -struct hnb_context *hnb_context_by_id(struct hnb_gw *gw, uint32_t cid); -struct hnb_context *hnb_context_by_identity_info(struct hnb_gw *gw, const char *identity_info); -const char *hnb_context_name(struct hnb_context *ctx); -unsigned hnb_contexts(const struct hnb_gw *gw); - -struct ue_context *ue_context_by_id(struct hnb_gw *gw, uint32_t id); -struct ue_context *ue_context_by_imsi(struct hnb_gw *gw, const char *imsi); -struct ue_context *ue_context_by_tmsi(struct hnb_gw *gw, uint32_t tmsi); -struct ue_context *ue_context_alloc(struct hnb_context *hnb, const char *imsi, - uint32_t tmsi); -void ue_context_free(struct ue_context *ue); - -struct hnb_context *hnb_context_alloc(struct hnb_gw *gw, struct osmo_stream_srv_link *link, int new_fd); -void hnb_context_release(struct hnb_context *ctx); - -void hnbgw_vty_init(struct hnb_gw *gw, void *tall_ctx); -int hnbgw_vty_go_parent(struct vty *vty); diff --git a/include/osmocom/iuh/hnbgw_cn.h b/include/osmocom/iuh/hnbgw_cn.h deleted file mode 100644 index 2e61d829..00000000 --- a/include/osmocom/iuh/hnbgw_cn.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -int hnbgw_cnlink_init(struct hnb_gw *gw, const char *stp_host, uint16_t stp_port, const char *local_ip); diff --git a/include/osmocom/iuh/hnbgw_hnbap.h b/include/osmocom/iuh/hnbgw_hnbap.h deleted file mode 100644 index cca35506..00000000 --- a/include/osmocom/iuh/hnbgw_hnbap.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg); -int hnbgw_hnbap_init(void); diff --git a/include/osmocom/iuh/hnbgw_ranap.h b/include/osmocom/iuh/hnbgw_ranap.h deleted file mode 100644 index 2c559647..00000000 --- a/include/osmocom/iuh/hnbgw_ranap.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -int hnbgw_ranap_rx(struct msgb *msg, uint8_t *data, size_t len); -int hnbgw_ranap_init(void); diff --git a/include/osmocom/iuh/hnbgw_rua.h b/include/osmocom/iuh/hnbgw_rua.h deleted file mode 100644 index 6a890b79..00000000 --- a/include/osmocom/iuh/hnbgw_rua.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include - -int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg); -int hnbgw_rua_init(void); - -int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len); -int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id, - const uint8_t *data, unsigned int len); -int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id, - const RUA_Cause_t *cause, const uint8_t *data, unsigned int len); diff --git a/include/osmocom/iuh/vty.h b/include/osmocom/iuh/vty.h deleted file mode 100644 index 3d05da58..00000000 --- a/include/osmocom/iuh/vty.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -enum osmo_iuh_vty_node { - HNBGW_NODE = _LAST_OSMOVTY_NODE + 1, - IUH_NODE, - IUCS_NODE, - IUPS_NODE, -}; - diff --git a/src/Makefile.am b/src/Makefile.am index b69d65f2..6c10564e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,20 +88,6 @@ libosmo_sabp_la_LIBADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOVTY_LIBS) $(OSMO libosmo_sabp_la_SOURCES = sabp_common.c sabp_encoder.c sabp_decoder.c -# build the actual HomeNodeB gateway -# -bin_PROGRAMS = osmo-hnbgw - -osmo_hnbgw_SOURCES = hnbgw.c hnbgw_hnbap.c hnbgw_rua.c hnbgw_ranap.c \ - hnbgw_vty.c \ - context_map.c hnbgw_cn.c - -osmo_hnbgw_LDADD = $(OSMOCORE_LIBS) $(OSMOGSM_LIBS) $(OSMOVTY_LIBS) $(OSMOCTRL_LIBS) \ - $(ASN1C_LIBS) $(OSMOSIGTRAN_LIBS) \ - $(OSMONETIF_LIBS) \ - libosmo-hnbap.la libosmo-rua.la libosmo-ranap.la - - regen: regenerate-from-asn1-source regenerate-from-asn1-source: diff --git a/src/context_map.c b/src/context_map.c deleted file mode 100644 index f516efe4..00000000 --- a/src/context_map.c +++ /dev/null @@ -1,181 +0,0 @@ -/* Mapper between RUA ContextID (24 bit, per HNB) and the SUA/SCCP - * Connection ID (32bit, per signalling link) */ - -/* (C) 2015 by Harald Welte - * 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 . - * - */ - -/* an expired mapping is destroyed after 1..2 * EXPIRY_TIMER_SECS */ -#define EXPIRY_TIMER_SECS 23 - -#include - -#include -#include - -const struct value_string hnbgw_context_map_state_names[] = { - {MAP_S_NULL , "not-initialized"}, - {MAP_S_ACTIVE , "active"}, - {MAP_S_RESERVED1, "inactive-reserved"}, - {MAP_S_RESERVED2, "inactive-discard"}, - {0, NULL} -}; - -/* is a given SCCP USER SAP Connection ID in use for a given CN link? */ -static int cn_id_in_use(struct hnbgw_cnlink *cn, uint32_t id) -{ - struct hnbgw_context_map *map; - - llist_for_each_entry(map, &cn->map_list, cn_list) { - if (map->scu_conn_id == id) - return 1; - } - return 0; -} - -/* try to allocate a new SCCP User SAP Connection ID */ -static int alloc_cn_conn_id(struct hnbgw_cnlink *cn, uint32_t *id_out) -{ - uint32_t i; - uint32_t id; - - for (i = 0; i < 0xffffffff; i++) { - id = cn->next_conn_id++; - if (!cn_id_in_use(cn, id)) { - *id_out = id; - return 1; - } - } - return -1; -} - -/* Map from a HNB + ContextID to the SCCP-side Connection ID */ -struct hnbgw_context_map * -context_map_alloc_by_hnb(struct hnb_context *hnb, uint32_t rua_ctx_id, - bool is_ps, - struct hnbgw_cnlink *cn_if_new) -{ - struct hnbgw_context_map *map; - uint32_t new_scu_conn_id; - - llist_for_each_entry(map, &hnb->map_list, hnb_list) { - if (map->state != MAP_S_ACTIVE) - continue; - if (map->cn_link != cn_if_new) { - continue; - } - if (map->rua_ctx_id == rua_ctx_id - && map->is_ps == is_ps) { - return map; - } - } - - if (alloc_cn_conn_id(cn_if_new, &new_scu_conn_id) < 0) { - LOGHNB(hnb, DMAIN, LOGL_ERROR, "Unable to allocate CN connection ID\n"); - return NULL; - } - - LOGHNB(hnb, DMAIN, LOGL_INFO, "Creating new Mapping RUA CTX %p/%u <-> SCU Conn ID %p/%u\n", - hnb, rua_ctx_id, cn_if_new, new_scu_conn_id); - - /* alloate a new map entry */ - map = talloc_zero(hnb, struct hnbgw_context_map); - map->state = MAP_S_NULL; - map->cn_link = cn_if_new; - map->hnb_ctx = hnb; - map->rua_ctx_id = rua_ctx_id; - map->is_ps = is_ps; - map->scu_conn_id = new_scu_conn_id; - - /* put it into both lists */ - llist_add_tail(&map->hnb_list, &hnb->map_list); - llist_add_tail(&map->cn_list, &cn_if_new->map_list); - map->state = MAP_S_ACTIVE; - - return map; -} - -/* Map from a CN + Connection ID to HNB + Context ID */ -struct hnbgw_context_map * -context_map_by_cn(struct hnbgw_cnlink *cn, uint32_t scu_conn_id) -{ - struct hnbgw_context_map *map; - - llist_for_each_entry(map, &cn->map_list, cn_list) { - if (map->state != MAP_S_ACTIVE) - continue; - if (map->scu_conn_id == scu_conn_id) { - return map; - } - } - /* we don't allocate new mappings in the CN->HNB - * direction, as the RUA=SCCP=SUA connections are always - * established from HNB towards CN. */ - LOGP(DMAIN, LOGL_NOTICE, "Unable to resolve map for CN " "connection ID %p/%u\n", cn, scu_conn_id); - return NULL; -} - -void context_map_deactivate(struct hnbgw_context_map *map) -{ - /* set the state to reserved. We still show up in the list and - * avoid re-allocation of the context-id until we are cleaned up - * by the context_map garbage collector timer */ - - if (map->state != MAP_S_RESERVED2) - map->state = MAP_S_RESERVED1; -} - -static struct osmo_timer_list context_map_tmr; - -static void context_map_tmr_cb(void *data) -{ - struct hnb_gw *gw = data; - struct hnbgw_cnlink *cn = gw->sccp.cnlink; - struct hnbgw_context_map *map, *next_map; - - DEBUGP(DMAIN, "Running context mapper garbage collection\n"); - llist_for_each_entry_safe(map, next_map, &cn->map_list, cn_list) { - switch (map->state) { - case MAP_S_RESERVED1: - /* first time we see this reserved - * entry: mark it for stage 2 */ - map->state = MAP_S_RESERVED2; - break; - case MAP_S_RESERVED2: - /* second time we see this reserved - * entry: remove it */ - map->state = MAP_S_NULL; - llist_del(&map->cn_list); - llist_del(&map->hnb_list); - talloc_free(map); - break; - default: - break; - } - } - /* re-schedule this timer */ - osmo_timer_schedule(&context_map_tmr, EXPIRY_TIMER_SECS, 0); -} - -int context_map_init(struct hnb_gw *gw) -{ - context_map_tmr.cb = context_map_tmr_cb; - context_map_tmr.data = gw; - osmo_timer_schedule(&context_map_tmr, EXPIRY_TIMER_SECS, 0); - - return 0; -} diff --git a/src/hnbgw.c b/src/hnbgw.c deleted file mode 100644 index 9211a7e2..00000000 --- a/src/hnbgw.c +++ /dev/null @@ -1,698 +0,0 @@ -/* main application for hnb-gw part of osmo-iuh */ - -/* (C) 2015 by Harald Welte - * (C) 2016 by sysmocom s.f.m.c. GmbH - * 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 . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include - -static const char * const osmo_hnbgw_copyright = - "OsmoHNBGW - Osmocom Home Node B Gateway implementation\r\n" - "Copyright (C) 2016 by sysmocom s.f.m.c. GmbH \r\n" - "Contributions by Daniel Willmann, Harald Welte, Neels Hofmeyr\r\n" - "License AGPLv3+: GNU AGPL version 3 or later \r\n" - "This is free software: you are free to change and redistribute it.\r\n" - "There is NO WARRANTY, to the extent permitted by law.\r\n"; - -static void *tall_hnb_ctx; - -static struct hnb_gw *g_hnb_gw; - -static struct hnb_gw *hnb_gw_create(void *ctx) -{ - struct hnb_gw *gw = talloc_zero(ctx, struct hnb_gw); - - /* strdup so we can easily talloc_free in the VTY code */ - gw->config.iuh_local_ip = talloc_strdup(gw, HNBGW_LOCAL_IP_DEFAULT); - gw->config.iuh_local_port = IUH_DEFAULT_SCTP_PORT; - gw->config.log_prefix_hnb_id = true; - - gw->next_ue_ctx_id = 23; - INIT_LLIST_HEAD(&gw->hnb_list); - INIT_LLIST_HEAD(&gw->ue_list); - - context_map_init(gw); - - return gw; -} - -struct hnb_context *hnb_context_by_id(struct hnb_gw *gw, uint32_t cid) -{ - struct hnb_context *hnb; - - llist_for_each_entry(hnb, &gw->hnb_list, list) { - if (hnb->id.cid == cid) - return hnb; - } - - return NULL; -} - -struct hnb_context *hnb_context_by_identity_info(struct hnb_gw *gw, const char *identity_info) -{ - struct hnb_context *hnb; - - llist_for_each_entry(hnb, &gw->hnb_list, list) { - if (strcmp(identity_info, hnb->identity_info) == 0) - return hnb; - } - - return NULL; -} - - -unsigned hnb_contexts(const struct hnb_gw *gw) -{ - unsigned num_ctx = 0; - struct hnb_context *hnb; - - llist_for_each_entry(hnb, &gw->hnb_list, list) { - num_ctx++; - } - - return num_ctx; -} - -struct ue_context *ue_context_by_id(struct hnb_gw *gw, uint32_t id) -{ - struct ue_context *ue; - - llist_for_each_entry(ue, &gw->ue_list, list) { - if (ue->context_id == id) - return ue; - } - return NULL; - -} - -struct ue_context *ue_context_by_imsi(struct hnb_gw *gw, const char *imsi) -{ - struct ue_context *ue; - - llist_for_each_entry(ue, &gw->ue_list, list) { - if (!strcmp(ue->imsi, imsi)) - return ue; - } - return NULL; -} - -struct ue_context *ue_context_by_tmsi(struct hnb_gw *gw, uint32_t tmsi) -{ - struct ue_context *ue; - - llist_for_each_entry(ue, &gw->ue_list, list) { - if (ue->tmsi == tmsi) - return ue; - } - return NULL; -} - -void ue_context_free_by_hnb(struct hnb_gw *gw, const struct hnb_context *hnb) -{ - struct ue_context *ue, *tmp; - - llist_for_each_entry_safe(ue, tmp, &gw->ue_list, list) { - if (ue->hnb == hnb) - ue_context_free(ue); - } -} - -static uint32_t get_next_ue_ctx_id(struct hnb_gw *gw) -{ - uint32_t id; - - do { - id = gw->next_ue_ctx_id++; - } while (ue_context_by_id(gw, id)); - - return id; -} - -struct ue_context *ue_context_alloc(struct hnb_context *hnb, const char *imsi, - uint32_t tmsi) -{ - struct ue_context *ue; - - ue = talloc_zero(tall_hnb_ctx, struct ue_context); - if (!ue) - return NULL; - - ue->hnb = hnb; - if (imsi) - OSMO_STRLCPY_ARRAY(ue->imsi, imsi); - else - ue->imsi[0] = '\0'; - ue->tmsi = tmsi; - ue->context_id = get_next_ue_ctx_id(hnb->gw); - llist_add_tail(&ue->list, &hnb->gw->ue_list); - - LOGP(DHNBAP, LOGL_INFO, "created UE context: id 0x%x, imsi %s, tmsi 0x%x\n", - ue->context_id, imsi? imsi : "-", tmsi); - - return ue; -} - -void ue_context_free(struct ue_context *ue) -{ - llist_del(&ue->list); - talloc_free(ue); -} - -static int hnb_read_cb(struct osmo_stream_srv *conn) -{ - struct hnb_context *hnb = osmo_stream_srv_get_data(conn); - struct msgb *msg = msgb_alloc(IUH_MSGB_SIZE, "Iuh rx"); - int rc; - - if (!msg) - return -ENOMEM; - - /* we store a reference to the HomeNodeB in the msg->dest for the - * benefit of varoius downstream processing functions */ - msg->dst = hnb; - - rc = osmo_stream_srv_recv(conn, msg); - if (rc == -EAGAIN) { - /* Notification received */ - msgb_free(msg); - return 0; - } else if (rc < 0) { - LOGHNB(hnb, DMAIN, LOGL_ERROR, "Error during sctp_recvmsg()\n"); - /* FIXME: clean up after disappeared HNB */ - hnb_context_release(hnb); - goto out; - } else if (rc == 0) { - hnb_context_release(hnb); - rc = -1; - - goto out; - } else { - msgb_put(msg, rc); - } - - switch (msgb_sctp_ppid(msg)) { - case IUH_PPI_HNBAP: - hnb->hnbap_stream = msgb_sctp_stream(msg); - rc = hnbgw_hnbap_rx(hnb, msg); - break; - case IUH_PPI_RUA: - hnb->rua_stream = msgb_sctp_stream(msg); - rc = hnbgw_rua_rx(hnb, msg); - break; - case IUH_PPI_SABP: - case IUH_PPI_RNA: - case IUH_PPI_PUA: - LOGHNB(hnb, DMAIN, LOGL_ERROR, "Unimplemented SCTP PPID=%lu received\n", msgb_sctp_ppid(msg)); - rc = 0; - break; - default: - LOGHNB(hnb, DMAIN, LOGL_ERROR, "Unknown SCTP PPID=%lu received\n", msgb_sctp_ppid(msg)); - rc = 0; - break; - } - -out: - msgb_free(msg); - return rc; -} - -struct hnb_context *hnb_context_alloc(struct hnb_gw *gw, struct osmo_stream_srv_link *link, int new_fd) -{ - struct hnb_context *ctx; - - ctx = talloc_zero(tall_hnb_ctx, struct hnb_context); - if (!ctx) - return NULL; - INIT_LLIST_HEAD(&ctx->map_list); - - ctx->gw = gw; - ctx->conn = osmo_stream_srv_create(tall_hnb_ctx, link, new_fd, hnb_read_cb, NULL, ctx); - if (!ctx->conn) { - LOGP(DMAIN, LOGL_INFO, "error while creating connection\n"); - talloc_free(ctx); - return NULL; - } - - llist_add_tail(&ctx->list, &gw->hnb_list); - return ctx; -} - -static const char *umts_cell_id_name(const struct umts_cell_id *ucid) -{ - static __thread char buf[40]; - - snprintf(buf, sizeof(buf), "%u-%u-L%u-R%u-S%u", ucid->mcc, ucid->mnc, ucid->lac, ucid->rac, ucid->sac); - return buf; -} - -const char *hnb_context_name(struct hnb_context *ctx) -{ - if (!ctx) - return "NULL"; - - if (ctx->gw->config.log_prefix_hnb_id) - return ctx->identity_info; - else - return umts_cell_id_name(&ctx->id); -} - -void hnb_context_release(struct hnb_context *ctx) -{ - struct hnbgw_context_map *map, *map2; - - /* remove from the list of HNB contexts */ - llist_del(&ctx->list); - - /* deactivate all context maps */ - llist_for_each_entry_safe(map, map2, &ctx->map_list, hnb_list) { - /* remove it from list, as HNB context will soon be - * gone. Let's hope the second osmo_llist_del in the - * map garbage collector works fine? */ - llist_del(&map->hnb_list); - llist_del(&map->cn_list); - context_map_deactivate(map); - } - ue_context_free_by_hnb(ctx->gw, ctx); - - osmo_stream_srv_destroy(ctx->conn); - - talloc_free(ctx); -} - -/*! call-back when the listen FD has something to read */ -static int accept_cb(struct osmo_stream_srv_link *srv, int fd) -{ - struct hnb_gw *gw = osmo_stream_srv_link_get_data(srv); - struct hnb_context *ctx; - - ctx = hnb_context_alloc(gw, srv, fd); - if (!ctx) - return -ENOMEM; - - return 0; -} - -static const struct log_info_cat log_cat[] = { - [DMAIN] = { - .name = "DMAIN", .loglevel = LOGL_NOTICE, .enabled = 1, - .color = "", - .description = "Main program", - }, - [DHNBAP] = { - .name = "DHNBAP", .loglevel = LOGL_NOTICE, .enabled = 1, - .color = "", - .description = "Home Node B Application Part", - }, - [DRUA] = { - .name = "DRUA", .loglevel = LOGL_NOTICE, .enabled = 1, - .color = "", - .description = "RANAP User Adaptation", - }, - [DRANAP] = { - .name = "DRANAP", .loglevel = LOGL_NOTICE, .enabled = 1, - .color = "", - .description = "RAN Application Part", - }, -}; - -static const struct log_info hnbgw_log_info = { - .cat = log_cat, - .num_cat = ARRAY_SIZE(log_cat), -}; - -static struct vty_app_info vty_info = { - .name = "OsmoHNBGW", - .version = PACKAGE_VERSION, - .go_parent_cb = hnbgw_vty_go_parent, -}; - -static struct { - int daemonize; - const char *config_file; - bool log_disable_color; - bool log_enable_timestamp; - int log_level; - const char *log_category_mask; -} hnbgw_cmdline_config = { - 0, - "osmo-hnbgw.cfg", - false, - false, - 0, - NULL, -}; - -static void print_usage() -{ - printf("Usage: osmo-hnbgw\n"); -} - -static void print_help() -{ - printf(" -h --help This text.\n"); - printf(" -d option --debug=DHNBAP:DRUA:DRANAP:DMAIN Enable debugging.\n"); - printf(" -D --daemonize Fork the process into a background daemon.\n"); - printf(" -c --config-file filename The config file to use.\n"); - printf(" -s --disable-color\n"); - printf(" -T --timestamp Prefix every log line with a timestamp.\n"); - printf(" -V --version Print the version of OsmoHNBGW.\n"); - printf(" -e --log-level number Set a global loglevel.\n"); - - printf("\nVTY reference generation:\n"); - printf(" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n"); - printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n"); -} - -static void handle_long_options(const char *prog_name, const int long_option) -{ - static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT; - - switch (long_option) { - case 1: - vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg); - if (vty_ref_mode < 0) { - fprintf(stderr, "%s: Unknown VTY reference generation " - "mode '%s'\n", prog_name, optarg); - exit(2); - } - break; - case 2: - fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n", - get_value_string(vty_ref_gen_mode_names, vty_ref_mode), - get_value_string(vty_ref_gen_mode_desc, vty_ref_mode)); - vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode); - exit(0); - default: - fprintf(stderr, "%s: error parsing cmdline options\n", prog_name); - exit(2); - } -} - -static void handle_options(int argc, char **argv) -{ - while (1) { - int option_index = 0, c; - static int long_option = 0; - static struct option long_options[] = { - {"help", 0, 0, 'h'}, - {"debug", 1, 0, 'd'}, - {"daemonize", 0, 0, 'D'}, - {"config-file", 1, 0, 'c'}, - {"disable-color", 0, 0, 's'}, - {"timestamp", 0, 0, 'T'}, - {"version", 0, 0, 'V' }, - {"log-level", 1, 0, 'e'}, - {"vty-ref-mode", 1, &long_option, 1}, - {"vty-ref-xml", 0, &long_option, 2}, - {0, 0, 0, 0} - }; - - c = getopt_long(argc, argv, "hd:Dc:sTVe:", - long_options, &option_index); - if (c == -1) - break; - - switch (c) { - case 0: - handle_long_options(argv[0], long_option); - break; - case 'h': - print_usage(); - print_help(); - exit(0); - case 's': - hnbgw_cmdline_config.log_disable_color = true; - break; - case 'd': - hnbgw_cmdline_config.log_category_mask = optarg; - break; - case 'D': - hnbgw_cmdline_config.daemonize = 1; - break; - case 'c': - hnbgw_cmdline_config.config_file = optarg; - break; - case 'T': - hnbgw_cmdline_config.log_enable_timestamp = true; - break; - case 'e': - hnbgw_cmdline_config.log_level = atoi(optarg); - break; - case 'V': - print_version(1); - exit(0); - break; - default: - /* catch unknown options *as well as* missing arguments. */ - fprintf(stderr, "Error in command line options. Exiting.\n"); - exit(-1); - break; - } - } - - if (argc > optind) { - fprintf(stderr, "Unsupported positional arguments on command line\n"); - exit(2); - } -} - -CTRL_CMD_DEFINE_RO(hnb_info, "info"); -static int get_hnb_info(struct ctrl_cmd *cmd, void *data) -{ - struct hnb_context *hnb = data; - - cmd->reply = talloc_strdup(cmd, hnb->identity_info); - - return CTRL_CMD_REPLY; -} - -CTRL_CMD_DEFINE_RO(hnbs, "num-hnb"); -static int get_hnbs(struct ctrl_cmd *cmd, void *data) -{ - cmd->reply = talloc_asprintf(cmd, "%u", hnb_contexts(data)); - - return CTRL_CMD_REPLY; -} - -int hnb_ctrl_cmds_install() -{ - int rc = 0; - - rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_hnbs); - rc |= ctrl_cmd_install(CTRL_NODE_HNB, &cmd_hnb_info); - - return rc; -} - -static int hnb_ctrl_node_lookup(void *data, vector vline, int *node_type, void **node_data, int *i) -{ - const char *token = vector_slot(vline, *i); - struct hnb_context *hnb; - long num; - - switch (*node_type) { - case CTRL_NODE_ROOT: - if (strcmp(token, "hnb") != 0) - return 0; - - (*i)++; - - if (!ctrl_parse_get_num(vline, *i, &num)) - return -ERANGE; - - hnb = hnb_context_by_id(data, num); - if (!hnb) - return -ENODEV; - - *node_data = hnb; - *node_type = CTRL_NODE_HNB; - break; - default: - return 0; - } - - return 1; -} - -int main(int argc, char **argv) -{ - struct osmo_stream_srv_link *srv; - int rc; - - tall_hnb_ctx = talloc_named_const(NULL, 0, "hnb_context"); - talloc_asn1_ctx = talloc_named_const(NULL, 1, "asn1_context"); - msgb_talloc_ctx_init(tall_hnb_ctx, 0); - - g_hnb_gw = hnb_gw_create(tall_hnb_ctx); - g_hnb_gw->config.rnc_id = 23; - - rc = osmo_init_logging2(tall_hnb_ctx, &hnbgw_log_info); - if (rc < 0) - exit(1); - - rc = osmo_ss7_init(); - if (rc < 0) { - LOGP(DMAIN, LOGL_FATAL, "osmo_ss7_init() failed with rc=%d\n", rc); - exit(1); - } - - vty_info.copyright = osmo_hnbgw_copyright; - vty_init(&vty_info); - - osmo_ss7_vty_init_asp(tall_hnb_ctx); - osmo_sccp_vty_init(); - hnbgw_vty_init(g_hnb_gw, tall_hnb_ctx); - ctrl_vty_init(tall_hnb_ctx); - logging_vty_add_cmds(); - - /* Handle options after vty_init(), for --version */ - handle_options(argc, argv); - - rc = vty_read_config_file(hnbgw_cmdline_config.config_file, NULL); - if (rc < 0) { - LOGP(DMAIN, LOGL_FATAL, "Failed to parse the config file: '%s'\n", - hnbgw_cmdline_config.config_file); - return 1; - } - - /* - * cmdline options take precedence over config file, but if no options - * were passed we must not override the config file. - */ - if (hnbgw_cmdline_config.log_disable_color) - log_set_use_color(osmo_stderr_target, 0); - if (hnbgw_cmdline_config.log_category_mask) - log_parse_category_mask(osmo_stderr_target, - hnbgw_cmdline_config.log_category_mask); - if (hnbgw_cmdline_config.log_enable_timestamp) - log_set_print_timestamp(osmo_stderr_target, 1); - if (hnbgw_cmdline_config.log_level) - log_set_log_level(osmo_stderr_target, - hnbgw_cmdline_config.log_level); - - rc = telnet_init_dynif(tall_hnb_ctx, g_hnb_gw, vty_get_bind_addr(), OSMO_VTY_PORT_HNBGW); - if (rc < 0) { - perror("Error binding VTY port"); - exit(1); - } - - g_hnb_gw->ctrl = ctrl_interface_setup_dynip2(g_hnb_gw, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_HNBGW, - hnb_ctrl_node_lookup, _LAST_CTRL_NODE_HNB); - if (!g_hnb_gw->ctrl) { - LOGP(DMAIN, LOGL_ERROR, "Failed to create CTRL interface on %s:%u\n", - ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_HNBGW); - exit(1); - } else { - rc = hnb_ctrl_cmds_install(); - if (rc) { - LOGP(DMAIN, LOGL_ERROR, "Failed to install CTRL interface commands\n"); - return 2; - } - } - - ranap_set_log_area(DRANAP); - - rc = hnbgw_cnlink_init(g_hnb_gw, "localhost", M3UA_PORT, "localhost"); - if (rc < 0) { - LOGP(DMAIN, LOGL_ERROR, "Failed to initialize SCCP link to CN\n"); - exit(1); - } - - LOGP(DHNBAP, LOGL_NOTICE, "Using RNC-Id %u\n", g_hnb_gw->config.rnc_id); - - OSMO_ASSERT(g_hnb_gw->config.iuh_local_ip); - LOGP(DMAIN, LOGL_NOTICE, "Listening for Iuh at %s %d\n", - g_hnb_gw->config.iuh_local_ip, - g_hnb_gw->config.iuh_local_port); - srv = osmo_stream_srv_link_create(tall_hnb_ctx); - if (!srv) { - perror("cannot create server"); - exit(1); - } - osmo_stream_srv_link_set_data(srv, g_hnb_gw); - osmo_stream_srv_link_set_proto(srv, IPPROTO_SCTP); - osmo_stream_srv_link_set_nodelay(srv, true); - osmo_stream_srv_link_set_addr(srv, g_hnb_gw->config.iuh_local_ip); - osmo_stream_srv_link_set_port(srv, g_hnb_gw->config.iuh_local_port); - osmo_stream_srv_link_set_accept_cb(srv, accept_cb); - - if (osmo_stream_srv_link_open(srv) < 0) { - perror("Cannot open server"); - exit(1); - } - g_hnb_gw->iuh = srv; - - if (hnbgw_cmdline_config.daemonize) { - rc = osmo_daemonize(); - if (rc < 0) { - perror("Error during daemonize"); - exit(1); - } - } - - while (1) { - rc = osmo_select_main(0); - if (rc < 0) - exit(3); - } - - /* not reached */ - exit(0); -} diff --git a/src/hnbgw_cn.c b/src/hnbgw_cn.c deleted file mode 100644 index 7b3cb093..00000000 --- a/src/hnbgw_cn.c +++ /dev/null @@ -1,559 +0,0 @@ -/* IuCS/IuPS Core Network interface of HNB-GW */ - -/* (C) 2015 by Harald Welte - * 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 . - * - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -/*********************************************************************** - * Outbound RANAP RESET to CN - ***********************************************************************/ - -void hnbgw_cnlink_change_state(struct hnbgw_cnlink *cnlink, enum hnbgw_cnlink_state state); - -static int transmit_rst(struct hnb_gw *gw, RANAP_CN_DomainIndicator_t domain, - struct osmo_sccp_addr *remote_addr) -{ - struct msgb *msg; - RANAP_Cause_t cause = { - .present = RANAP_Cause_PR_transmissionNetwork, - .choice. transmissionNetwork = RANAP_CauseTransmissionNetwork_signalling_transport_resource_failure, - }; - - LOGP(DRANAP, LOGL_NOTICE, "Tx RESET to %s %s\n", - domain == RANAP_CN_DomainIndicator_cs_domain ? "IuCS" : "IuPS", - osmo_sccp_inst_addr_name(gw->sccp.cnlink->sccp, remote_addr)); - - msg = ranap_new_msg_reset(domain, &cause); - - return osmo_sccp_tx_unitdata_msg(gw->sccp.cnlink->sccp_user, - &gw->sccp.local_addr, - remote_addr, - msg); -} - -static int transmit_reset_ack(struct hnb_gw *gw, RANAP_CN_DomainIndicator_t domain, - const struct osmo_sccp_addr *remote_addr) -{ - struct msgb *msg; - - LOGP(DRANAP, LOGL_NOTICE, "Tx RESET ACK to %s %s\n", - domain == RANAP_CN_DomainIndicator_cs_domain ? "IuCS" : "IuPS", - osmo_sccp_inst_addr_name(gw->sccp.cnlink->sccp, remote_addr)); - - msg = ranap_new_msg_reset_ack(domain, NULL); - - return osmo_sccp_tx_unitdata_msg(gw->sccp.cnlink->sccp_user, - &gw->sccp.local_addr, - remote_addr, - msg); -} - -/* Timer callback once T_RafC expires */ -static void cnlink_trafc_cb(void *data) -{ - struct hnb_gw *gw = data; - - transmit_rst(gw, RANAP_CN_DomainIndicator_cs_domain, &gw->sccp.iucs_remote_addr); - transmit_rst(gw, RANAP_CN_DomainIndicator_ps_domain, &gw->sccp.iups_remote_addr); - hnbgw_cnlink_change_state(gw->sccp.cnlink, CNLINK_S_EST_RST_TX_WAIT_ACK); - /* The spec states that we should abandon after a configurable - * number of times. We decide to simply continue trying */ -} - -/* change the state of a CN Link */ -void hnbgw_cnlink_change_state(struct hnbgw_cnlink *cnlink, enum hnbgw_cnlink_state state) -{ - switch (state) { - case CNLINK_S_NULL: - case CNLINK_S_EST_PEND: - break; - case CNLINK_S_EST_CONF: - cnlink_trafc_cb(cnlink->gw); - break; - case CNLINK_S_EST_RST_TX_WAIT_ACK: - osmo_timer_schedule(&cnlink->T_RafC, 5, 0); - break; - case CNLINK_S_EST_ACTIVE: - osmo_timer_del(&cnlink->T_RafC); - break; - } -} - -/*********************************************************************** - * Incoming primitives from SCCP User SAP - ***********************************************************************/ - -static int cn_ranap_rx_reset_cmd(struct hnbgw_cnlink *cnlink, - const struct osmo_scu_unitdata_param *unitdata, - RANAP_InitiatingMessage_t *imsg) -{ - RANAP_CN_DomainIndicator_t domain; - RANAP_ResetIEs_t ies; - int rc; - - rc = ranap_decode_reseties(&ies, &imsg->value); - domain = ies.cN_DomainIndicator; - ranap_free_reseties(&ies); - - LOGP(DRANAP, LOGL_NOTICE, "Rx RESET from %s %s, returning ACK\n", - domain == RANAP_CN_DomainIndicator_cs_domain ? "IuCS" : "IuPS", - osmo_sccp_inst_addr_name(cnlink->sccp, &unitdata->calling_addr)); - - /* FIXME: actually reset connections, if any */ - - if (transmit_reset_ack(cnlink->gw, domain, &unitdata->calling_addr)) - LOGP(DRANAP, LOGL_ERROR, "Error: cannot send RESET ACK to %s %s\n", - domain == RANAP_CN_DomainIndicator_cs_domain ? "IuCS" : "IuPS", - osmo_sccp_inst_addr_name(cnlink->sccp, &unitdata->calling_addr)); - - return rc; -} - -static int cn_ranap_rx_reset_ack(struct hnbgw_cnlink *cnlink, - RANAP_SuccessfulOutcome_t *omsg) -{ - RANAP_ResetAcknowledgeIEs_t ies; - int rc; - - rc = ranap_decode_resetacknowledgeies(&ies, &omsg->value); - - hnbgw_cnlink_change_state(cnlink, CNLINK_S_EST_ACTIVE); - - ranap_free_resetacknowledgeies(&ies); - return rc; -} - -static int cn_ranap_rx_paging_cmd(struct hnbgw_cnlink *cnlink, - RANAP_InitiatingMessage_t *imsg, - const uint8_t *data, unsigned int len) -{ - struct hnb_gw *gw = cnlink->gw; - struct hnb_context *hnb; - RANAP_PagingIEs_t ies; - int rc; - - rc = ranap_decode_pagingies(&ies, &imsg->value); - if (rc < 0) - return rc; - - /* FIXME: determine which HNBs to send this Paging command, - * rather than broadcasting to all HNBs */ - llist_for_each_entry(hnb, &gw->hnb_list, list) { - rc = rua_tx_udt(hnb, data, len); - } - - ranap_free_pagingies(&ies); - return 0; -} - -static int cn_ranap_rx_initiating_msg(struct hnbgw_cnlink *cnlink, - const struct osmo_scu_unitdata_param *unitdata, - RANAP_InitiatingMessage_t *imsg, - const uint8_t *data, unsigned int len) -{ - switch (imsg->procedureCode) { - case RANAP_ProcedureCode_id_Reset: - return cn_ranap_rx_reset_cmd(cnlink, unitdata, imsg); - case RANAP_ProcedureCode_id_Paging: - return cn_ranap_rx_paging_cmd(cnlink, imsg, data, len); - case RANAP_ProcedureCode_id_OverloadControl: /* Overload ind */ - break; - case RANAP_ProcedureCode_id_ErrorIndication: /* Error ind */ - break; - case RANAP_ProcedureCode_id_ResetResource: /* request */ - case RANAP_ProcedureCode_id_InformationTransfer: - case RANAP_ProcedureCode_id_DirectInformationTransfer: - case RANAP_ProcedureCode_id_UplinkInformationExchange: - LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP " - "Procedure %ld from CN, ignoring\n", imsg->procedureCode); - break; - default: - LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " - "Procedure %ld from CN, ignoring\n", imsg->procedureCode); - break; - } - return 0; -} - -static int cn_ranap_rx_successful_msg(struct hnbgw_cnlink *cnlink, - RANAP_SuccessfulOutcome_t *omsg) -{ - switch (omsg->procedureCode) { - case RANAP_ProcedureCode_id_Reset: /* Reset acknowledge */ - return cn_ranap_rx_reset_ack(cnlink, omsg); - case RANAP_ProcedureCode_id_ResetResource: /* response */ - case RANAP_ProcedureCode_id_InformationTransfer: - case RANAP_ProcedureCode_id_DirectInformationTransfer: - case RANAP_ProcedureCode_id_UplinkInformationExchange: - LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP " - "Procedure %ld from CN, ignoring\n", omsg->procedureCode); - break; - default: - LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " - "Procedure %ld from CN, ignoring\n", omsg->procedureCode); - break; - } - return 0; -} - - -static int _cn_ranap_rx(struct hnbgw_cnlink *cnlink, - const struct osmo_scu_unitdata_param *unitdata, - RANAP_RANAP_PDU_t *pdu, const uint8_t *data, unsigned int len) -{ - int rc; - - switch (pdu->present) { - case RANAP_RANAP_PDU_PR_initiatingMessage: - rc = cn_ranap_rx_initiating_msg(cnlink, unitdata, &pdu->choice.initiatingMessage, - data, len); - break; - case RANAP_RANAP_PDU_PR_successfulOutcome: - rc = cn_ranap_rx_successful_msg(cnlink, &pdu->choice.successfulOutcome); - break; - case RANAP_RANAP_PDU_PR_unsuccessfulOutcome: - LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP " - "unsuccessful outcome procedure %ld from CN, ignoring\n", - pdu->choice.unsuccessfulOutcome.procedureCode); - rc = -ENOTSUP; - break; - default: - LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP " - "presence %u from CN, ignoring\n", pdu->present); - rc = -EINVAL; - break; - } - - return rc; -} - -static int handle_cn_ranap(struct hnbgw_cnlink *cnlink, const struct osmo_scu_unitdata_param *unitdata, - const uint8_t *data, unsigned int len) -{ - RANAP_RANAP_PDU_t _pdu, *pdu = &_pdu; - asn_dec_rval_t dec_ret; - int rc; - - memset(pdu, 0, sizeof(*pdu)); - dec_ret = aper_decode(NULL,&asn_DEF_RANAP_RANAP_PDU, (void **) &pdu, - data, len, 0, 0); - if (dec_ret.code != RC_OK) { - LOGP(DRANAP, LOGL_ERROR, "Error in RANAP ASN.1 decode\n"); - return -1; - } - - rc = _cn_ranap_rx(cnlink, unitdata, pdu, data, len); - - return rc; -} - -static bool pc_and_ssn_match(const struct osmo_sccp_addr *a, const struct osmo_sccp_addr *b) -{ - return (a == b) - || ((a->pc == b->pc) - && (a->ssn == b->ssn)); -} - -static int classify_cn_remote_addr(const struct hnb_gw *gw, - const struct osmo_sccp_addr *cn_remote_addr, - bool *is_ps) -{ - if (pc_and_ssn_match(cn_remote_addr, &gw->sccp.iucs_remote_addr)) { - if (is_ps) - *is_ps = false; - return 0; - } - if (pc_and_ssn_match(cn_remote_addr, &gw->sccp.iups_remote_addr)) { - if (is_ps) - *is_ps = true; - return 0; - } - LOGP(DMAIN, LOGL_ERROR, "Unexpected remote address, matches neither CS nor PS address: %s\n", - osmo_sccp_addr_dump(cn_remote_addr)); - return -1; -} - -static int handle_cn_unitdata(struct hnbgw_cnlink *cnlink, - const struct osmo_scu_unitdata_param *param, - struct osmo_prim_hdr *oph) -{ - if (param->called_addr.ssn != OSMO_SCCP_SSN_RANAP) { - LOGP(DMAIN, LOGL_NOTICE, "N-UNITDATA.ind for unknown SSN %u\n", - param->called_addr.ssn); - return -1; - } - - if (classify_cn_remote_addr(cnlink->gw, ¶m->calling_addr, NULL) < 0) - return -1; - - return handle_cn_ranap(cnlink, param, msgb_l2(oph->msg), msgb_l2len(oph->msg)); -} - -static int handle_cn_conn_conf(struct hnbgw_cnlink *cnlink, - const struct osmo_scu_connect_param *param, - struct osmo_prim_hdr *oph) -{ - /* we don't actually need to do anything, as RUA towards the HNB - * doesn't seem to know any confirmations to its CONNECT - * operation */ - - LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() conn_id=%d\n", - param->conn_id); - LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() called_addr=%s\n", - inet_ntoa(param->called_addr.ip.v4)); - LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() calling_addr=%s\n", - inet_ntoa(param->calling_addr.ip.v4)); - LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() responding_addr=%s\n", - inet_ntoa(param->responding_addr.ip.v4)); - - return 0; -} - -static int handle_cn_data_ind(struct hnbgw_cnlink *cnlink, - const struct osmo_scu_data_param *param, - struct osmo_prim_hdr *oph) -{ - struct hnbgw_context_map *map; - - /* connection-oriented data is always passed transparently - * towards the specific HNB, via a RUA connection identified by - * conn_id */ - - map = context_map_by_cn(cnlink, param->conn_id); - if (!map) { - /* FIXME: Return an error / released primitive */ - return 0; - } - - return rua_tx_dt(map->hnb_ctx, map->is_ps, map->rua_ctx_id, - msgb_l2(oph->msg), msgb_l2len(oph->msg)); -} - -static int handle_cn_disc_ind(struct hnbgw_cnlink *cnlink, - const struct osmo_scu_disconn_param *param, - struct osmo_prim_hdr *oph) -{ - struct hnbgw_context_map *map; - - LOGP(DMAIN, LOGL_DEBUG, "handle_cn_disc_ind() conn_id=%d originator=%d\n", - param->conn_id, param->originator); - LOGP(DMAIN, LOGL_DEBUG, "handle_cn_disc_ind() responding_addr=%s\n", - inet_ntoa(param->responding_addr.ip.v4)); - - RUA_Cause_t rua_cause = { - .present = RUA_Cause_PR_NOTHING, - /* FIXME: Convert incoming SCCP cause to RUA cause */ - }; - - /* we need to notify the HNB associated with this connection via - * a RUA DISCONNECT */ - - map = context_map_by_cn(cnlink, param->conn_id); - if (!map) { - /* FIXME: Return an error / released primitive */ - return 0; - } - - return rua_tx_disc(map->hnb_ctx, map->is_ps, map->rua_ctx_id, - &rua_cause, msgb_l2(oph->msg), msgb_l2len(oph->msg)); -} - -/* Entry point for primitives coming up from SCCP User SAP */ -static int sccp_sap_up(struct osmo_prim_hdr *oph, void *ctx) -{ - struct osmo_sccp_user *scu = ctx; - struct hnbgw_cnlink *cnlink; - struct osmo_scu_prim *prim = (struct osmo_scu_prim *) oph; - int rc = 0; - - LOGP(DMAIN, LOGL_DEBUG, "sccp_sap_up(%s)\n", osmo_scu_prim_name(oph)); - - if (!scu) { - LOGP(DMAIN, LOGL_ERROR, - "sccp_sap_up(): NULL osmo_sccp_user, cannot send prim (sap %u prim %u op %d)\n", - oph->sap, oph->primitive, oph->operation); - return -1; - } - - cnlink = osmo_sccp_user_get_priv(scu); - if (!cnlink) { - LOGP(DMAIN, LOGL_ERROR, - "sccp_sap_up(): NULL hnbgw_cnlink, cannot send prim (sap %u prim %u op %d)\n", - oph->sap, oph->primitive, oph->operation); - return -1; - } - - switch (OSMO_PRIM_HDR(oph)) { - case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION): - rc = handle_cn_unitdata(cnlink, &prim->u.unitdata, oph); - break; - case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_CONFIRM): - rc = handle_cn_conn_conf(cnlink, &prim->u.connect, oph); - break; - case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION): - rc = handle_cn_data_ind(cnlink, &prim->u.data, oph); - break; - case OSMO_PRIM(OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_INDICATION): - rc = handle_cn_disc_ind(cnlink, &prim->u.disconnect, oph); - break; - default: - LOGP(DMAIN, LOGL_ERROR, - "Received unknown prim %u from SCCP USER SAP\n", - OSMO_PRIM_HDR(oph)); - break; - } - - msgb_free(oph->msg); - - return rc; -} - -static bool addr_has_pc_and_ssn(const struct osmo_sccp_addr *addr) -{ - if (!(addr->presence & OSMO_SCCP_ADDR_T_SSN)) - return false; - if (!(addr->presence & OSMO_SCCP_ADDR_T_PC)) - return false; - return true; -} - -static int resolve_addr_name(struct osmo_sccp_addr *dest, struct osmo_ss7_instance **ss7, - const char *addr_name, const char *label, - uint32_t default_pc) -{ - struct osmo_ss7_instance *ss7_tmp; - - if (!addr_name) { - osmo_sccp_make_addr_pc_ssn(dest, default_pc, OSMO_SCCP_SSN_RANAP); - LOGP(DMAIN, LOGL_INFO, "%s remote addr not configured, using default: %s\n", label, - osmo_sccp_addr_name(*ss7, dest)); - return 0; - } - - ss7_tmp = osmo_sccp_addr_by_name(dest, addr_name); - if (!ss7_tmp) { - LOGP(DMAIN, LOGL_ERROR, "%s remote addr: no such SCCP address book entry: '%s'\n", - label, addr_name); - return -1; - } - - if (*ss7 && (*ss7 != ss7_tmp)) { - LOGP(DMAIN, LOGL_ERROR, "IuCS and IuPS cannot be served from separate CS7 instances," - " cs7 instance %d != %d\n", (*ss7)->cfg.id, ss7_tmp->cfg.id); - return -1; - } - - *ss7 = ss7_tmp; - - osmo_sccp_addr_set_ssn(dest, OSMO_SCCP_SSN_RANAP); - - if (!addr_has_pc_and_ssn(dest)) { - LOGP(DMAIN, LOGL_ERROR, "Invalid/incomplete %s remote-addr: %s\n", - label, osmo_sccp_addr_name(*ss7, dest)); - return -1; - } - - LOGP(DRANAP, LOGL_NOTICE, "Remote %s SCCP addr: %s\n", - label, osmo_sccp_addr_name(*ss7, dest)); - return 0; -} - -int hnbgw_cnlink_init(struct hnb_gw *gw, const char *stp_host, uint16_t stp_port, const char *local_ip) -{ - struct hnbgw_cnlink *cnlink; - struct osmo_ss7_instance *ss7; - uint32_t local_pc; - - OSMO_ASSERT(!gw->sccp.client); - OSMO_ASSERT(!gw->sccp.cnlink); - - ss7 = NULL; - if (resolve_addr_name(&gw->sccp.iucs_remote_addr, &ss7, - gw->config.iucs_remote_addr_name, "IuCS", (23 << 3) + 1)) - return -1; - if (resolve_addr_name(&gw->sccp.iups_remote_addr, &ss7, - gw->config.iups_remote_addr_name, "IuPS", (23 << 3) + 4)) - return -1; - - if (!ss7) { - LOGP(DRANAP, LOGL_NOTICE, "No cs7 instance configured for IuCS nor IuPS," - " creating default instance\n"); - ss7 = osmo_ss7_instance_find_or_create(gw, 0); - ss7->cfg.primary_pc = (23 << 3) + 5; - } - - if (!osmo_ss7_pc_is_valid(ss7->cfg.primary_pc)) { - LOGP(DMAIN, LOGL_ERROR, "IuCS/IuPS uplink cannot be setup: CS7 instance %d has no point-code set\n", - ss7->cfg.id); - return -1; - } - local_pc = ss7->cfg.primary_pc; - - osmo_sccp_make_addr_pc_ssn(&gw->sccp.local_addr, local_pc, OSMO_SCCP_SSN_RANAP); - LOGP(DRANAP, LOGL_NOTICE, "Local SCCP addr: %s\n", osmo_sccp_addr_name(ss7, &gw->sccp.local_addr)); - - gw->sccp.client = osmo_sccp_simple_client_on_ss7_id(gw, ss7->cfg.id, "OsmoHNBGW", - local_pc, OSMO_SS7_ASP_PROT_M3UA, - 0, local_ip, stp_port, stp_host); - if (!gw->sccp.client) { - LOGP(DMAIN, LOGL_ERROR, "Failed to init SCCP Client\n"); - return -1; - } - - cnlink = talloc_zero(gw, struct hnbgw_cnlink); - cnlink->gw = gw; - INIT_LLIST_HEAD(&cnlink->map_list); - cnlink->T_RafC.cb = cnlink_trafc_cb; - cnlink->T_RafC.data = gw; - cnlink->next_conn_id = 1000; - - cnlink->sccp_user = osmo_sccp_user_bind_pc(gw->sccp.client, "OsmoHNBGW", sccp_sap_up, - OSMO_SCCP_SSN_RANAP, gw->sccp.local_addr.pc); - if (!cnlink->sccp_user) { - LOGP(DMAIN, LOGL_ERROR, "Failed to init SCCP User\n"); - return -1; - } - - LOGP(DRANAP, LOGL_NOTICE, "Remote SCCP addr: IuCS: %s\n", - osmo_sccp_addr_name(ss7, &gw->sccp.iucs_remote_addr)); - LOGP(DRANAP, LOGL_NOTICE, "Remote SCCP addr: IuPS: %s\n", - osmo_sccp_addr_name(ss7, &gw->sccp.iups_remote_addr)); - - /* In sccp_sap_up() we expect the cnlink in the user's priv. */ - osmo_sccp_user_set_priv(cnlink->sccp_user, cnlink); - - gw->sccp.cnlink = cnlink; - - return 0; -} diff --git a/src/hnbgw_hnbap.c b/src/hnbgw_hnbap.c deleted file mode 100644 index f56cc9bb..00000000 --- a/src/hnbgw_hnbap.c +++ /dev/null @@ -1,632 +0,0 @@ -/* hnb-gw specific code for HNBAP */ - -/* (C) 2015 by Harald Welte - * 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 . - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "asn1helpers.h" -#include -#include - -#include -#include - -#define IU_MSG_NUM_IES 32 -#define IU_MSG_NUM_EXT_IES 32 - -static int hnbgw_hnbap_tx(struct hnb_context *ctx, struct msgb *msg) -{ - if (!msg) - return -EINVAL; - - msgb_sctp_ppid(msg) = IUH_PPI_HNBAP; - osmo_stream_srv_send(ctx->conn, msg); - - return 0; -} - -static int hnbgw_tx_hnb_register_rej(struct hnb_context *ctx) -{ - HNBAP_HNBRegisterReject_t reject_out; - HNBAP_HNBRegisterRejectIEs_t reject; - struct msgb *msg; - int rc; - - reject.presenceMask = 0, - reject.cause.present = HNBAP_Cause_PR_radioNetwork; - reject.cause.choice.radioNetwork = HNBAP_CauseRadioNetwork_unspecified; - - /* encode the Information Elements */ - memset(&reject_out, 0, sizeof(reject_out)); - rc = hnbap_encode_hnbregisterrejecties(&reject_out, &reject); - if (rc < 0) { - LOGHNB(ctx, DHNBAP, LOGL_ERROR, "Failure to encode HNB-REGISTER-REJECT to %s: rc=%d\n", - ctx->identity_info, rc); - return rc; - } - - /* generate a successfull outcome PDU */ - msg = hnbap_generate_unsuccessful_outcome(HNBAP_ProcedureCode_id_HNBRegister, - HNBAP_Criticality_reject, - &asn_DEF_HNBAP_HNBRegisterReject, - &reject_out); - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_HNBRegisterReject, &reject_out); - - rc = hnbgw_hnbap_tx(ctx, msg); - if (rc == 0) { - /* Tell libosmo-netif to destroy this connection when it is done - * sending our HNB-REGISTER-REJECT response. */ - osmo_stream_srv_set_flush_and_destroy(ctx->conn); - } else { - /* The message was not queued. Destroy the connection right away. */ - hnb_context_release(ctx); - return rc; - } - - return 0; -} - -static int hnbgw_tx_hnb_register_acc(struct hnb_context *ctx) -{ - HNBAP_HNBRegisterAccept_t accept_out; - struct msgb *msg; - int rc; - - /* Single required response IE: RNC-ID */ - HNBAP_HNBRegisterAcceptIEs_t accept = { - .rnc_id = ctx->gw->config.rnc_id - }; - - /* encode the Information Elements */ - memset(&accept_out, 0, sizeof(accept_out)); - rc = hnbap_encode_hnbregisteraccepties(&accept_out, &accept); - if (rc < 0) { - LOGHNB(ctx, DHNBAP, LOGL_ERROR, "Failure to encode HNB-REGISTER-ACCEPT to %s: rc=%d\n", - ctx->identity_info, rc); - return rc; - } - - /* generate a successfull outcome PDU */ - msg = hnbap_generate_successful_outcome(HNBAP_ProcedureCode_id_HNBRegister, - HNBAP_Criticality_reject, - &asn_DEF_HNBAP_HNBRegisterAccept, - &accept_out); - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_HNBRegisterAccept, &accept_out); - - LOGHNB(ctx, DHNBAP, LOGL_NOTICE, "Accepting HNB-REGISTER-REQ from %s\n", ctx->identity_info); - - return hnbgw_hnbap_tx(ctx, msg); -} - - -static int hnbgw_tx_ue_register_acc(struct ue_context *ue) -{ - HNBAP_UERegisterAccept_t accept_out; - HNBAP_UERegisterAcceptIEs_t accept; - struct msgb *msg; - uint8_t encoded_imsi[10]; - uint32_t ctx_id; - size_t encoded_imsi_len; - int rc; - - encoded_imsi_len = ranap_imsi_encode(encoded_imsi, - sizeof(encoded_imsi), ue->imsi); - - memset(&accept, 0, sizeof(accept)); - accept.uE_Identity.present = HNBAP_UE_Identity_PR_iMSI; - OCTET_STRING_fromBuf(&accept.uE_Identity.choice.iMSI, - (const char *)encoded_imsi, encoded_imsi_len); - asn1_u24_to_bitstring(&accept.context_ID, &ctx_id, ue->context_id); - - memset(&accept_out, 0, sizeof(accept_out)); - rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept); - if (rc < 0) { - return rc; - } - - msg = hnbap_generate_successful_outcome(HNBAP_ProcedureCode_id_UERegister, - HNBAP_Criticality_reject, - &asn_DEF_HNBAP_UERegisterAccept, - &accept_out); - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, &accept.uE_Identity.choice.iMSI); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_UERegisterAccept, &accept_out); - - return hnbgw_hnbap_tx(ue->hnb, msg); -} - -static int hnbgw_tx_ue_register_rej_tmsi(struct hnb_context *hnb, HNBAP_UE_Identity_t *ue_id) -{ - HNBAP_UERegisterReject_t reject_out; - HNBAP_UERegisterRejectIEs_t reject; - struct msgb *msg; - int rc; - - memset(&reject, 0, sizeof(reject)); - reject.uE_Identity.present = ue_id->present; - - /* Copy the identity over to the reject message */ - switch (ue_id->present) { - case HNBAP_UE_Identity_PR_tMSILAI: - LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id tMSI %d %s\n", ue_id->choice.tMSILAI.tMSI.size, - osmo_hexdump(ue_id->choice.tMSILAI.tMSI.buf, ue_id->choice.tMSILAI.tMSI.size)); - - LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id pLMNID %d %s\n", ue_id->choice.tMSILAI.lAI.pLMNID.size, - osmo_hexdump(ue_id->choice.tMSILAI.lAI.pLMNID.buf, ue_id->choice.tMSILAI.lAI.pLMNID.size)); - - LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id lAC %d %s\n", ue_id->choice.tMSILAI.lAI.lAC.size, - osmo_hexdump(ue_id->choice.tMSILAI.lAI.lAC.buf, ue_id->choice.tMSILAI.lAI.lAC.size)); - - BIT_STRING_fromBuf(&reject.uE_Identity.choice.tMSILAI.tMSI, - ue_id->choice.tMSILAI.tMSI.buf, - ue_id->choice.tMSILAI.tMSI.size * 8 - - ue_id->choice.tMSILAI.tMSI.bits_unused); - OCTET_STRING_fromBuf(&reject.uE_Identity.choice.tMSILAI.lAI.pLMNID, - (const char *)ue_id->choice.tMSILAI.lAI.pLMNID.buf, - ue_id->choice.tMSILAI.lAI.pLMNID.size); - OCTET_STRING_fromBuf(&reject.uE_Identity.choice.tMSILAI.lAI.lAC, - (const char *)ue_id->choice.tMSILAI.lAI.lAC.buf, - ue_id->choice.tMSILAI.lAI.lAC.size); - break; - - case HNBAP_UE_Identity_PR_pTMSIRAI: - LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id pTMSI %d %s\n", ue_id->choice.pTMSIRAI.pTMSI.size, - osmo_hexdump(ue_id->choice.pTMSIRAI.pTMSI.buf, ue_id->choice.pTMSIRAI.pTMSI.size)); - - LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id pLMNID %d %s\n", ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size, - osmo_hexdump(ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.buf, ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size)); - - LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id lAC %d %s\n", ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size, - osmo_hexdump(ue_id->choice.pTMSIRAI.rAI.lAI.lAC.buf, ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size)); - - LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "REJ UE_Id rAC %d %s\n", ue_id->choice.pTMSIRAI.rAI.rAC.size, - osmo_hexdump(ue_id->choice.pTMSIRAI.rAI.rAC.buf, ue_id->choice.pTMSIRAI.rAI.rAC.size)); - - BIT_STRING_fromBuf(&reject.uE_Identity.choice.pTMSIRAI.pTMSI, - ue_id->choice.pTMSIRAI.pTMSI.buf, - ue_id->choice.pTMSIRAI.pTMSI.size * 8 - - ue_id->choice.pTMSIRAI.pTMSI.bits_unused); - OCTET_STRING_fromBuf(&reject.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID, - (const char *)ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.buf, - ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size); - OCTET_STRING_fromBuf(&reject.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC, - (const char *)ue_id->choice.pTMSIRAI.rAI.lAI.lAC.buf, - ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size); - OCTET_STRING_fromBuf(&reject.uE_Identity.choice.pTMSIRAI.rAI.rAC, - (const char *)ue_id->choice.pTMSIRAI.rAI.rAC.buf, - ue_id->choice.pTMSIRAI.rAI.rAC.size); - break; - - default: - LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Cannot compose UE Register Reject:" - " unsupported UE ID (present=%d)\n", ue_id->present); - return -1; - } - - LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Rejecting UE Register Request: TMSI identity registration is switched off\n"); - - reject.cause.present = HNBAP_Cause_PR_radioNetwork; - reject.cause.choice.radioNetwork = HNBAP_CauseRadioNetwork_invalid_UE_identity; - - memset(&reject_out, 0, sizeof(reject_out)); - rc = hnbap_encode_ueregisterrejecties(&reject_out, &reject); - if (rc < 0) - return rc; - - msg = hnbap_generate_unsuccessful_outcome(HNBAP_ProcedureCode_id_UERegister, - HNBAP_Criticality_reject, - &asn_DEF_HNBAP_UERegisterReject, - &reject_out); - - /* Free copied identity IEs */ - switch (ue_id->present) { - case HNBAP_UE_Identity_PR_tMSILAI: - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING, - &reject.uE_Identity.choice.tMSILAI.tMSI); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &reject.uE_Identity.choice.tMSILAI.lAI.pLMNID); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &reject.uE_Identity.choice.tMSILAI.lAI.lAC); - break; - - case HNBAP_UE_Identity_PR_pTMSIRAI: - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING, - &reject.uE_Identity.choice.pTMSIRAI.pTMSI); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &reject.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &reject.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &reject.uE_Identity.choice.pTMSIRAI.rAI.rAC); - break; - - default: - /* should never happen after above switch() */ - break; - } - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_UERegisterReject, &reject_out); - - return hnbgw_hnbap_tx(hnb, msg); -} - -static int hnbgw_tx_ue_register_acc_tmsi(struct hnb_context *hnb, HNBAP_UE_Identity_t *ue_id) -{ - HNBAP_UERegisterAccept_t accept_out; - HNBAP_UERegisterAcceptIEs_t accept; - struct msgb *msg; - uint32_t ctx_id; - uint32_t tmsi = 0; - struct ue_context *ue; - int rc; - - memset(&accept, 0, sizeof(accept)); - accept.uE_Identity.present = ue_id->present; - - switch (ue_id->present) { - case HNBAP_UE_Identity_PR_tMSILAI: - BIT_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.tMSI, - ue_id->choice.tMSILAI.tMSI.buf, - ue_id->choice.tMSILAI.tMSI.size * 8 - - ue_id->choice.tMSILAI.tMSI.bits_unused); - tmsi = *(uint32_t*)accept.uE_Identity.choice.tMSILAI.tMSI.buf; - OCTET_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.lAI.pLMNID, - (const char *)ue_id->choice.tMSILAI.lAI.pLMNID.buf, - ue_id->choice.tMSILAI.lAI.pLMNID.size); - OCTET_STRING_fromBuf(&accept.uE_Identity.choice.tMSILAI.lAI.lAC, - (const char *)ue_id->choice.tMSILAI.lAI.lAC.buf, - ue_id->choice.tMSILAI.lAI.lAC.size); - break; - - case HNBAP_UE_Identity_PR_pTMSIRAI: - BIT_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.pTMSI, - ue_id->choice.pTMSIRAI.pTMSI.buf, - ue_id->choice.pTMSIRAI.pTMSI.size * 8 - - ue_id->choice.pTMSIRAI.pTMSI.bits_unused); - tmsi = *(uint32_t*)accept.uE_Identity.choice.pTMSIRAI.pTMSI.buf; - OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID, - (const char *)ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.buf, - ue_id->choice.pTMSIRAI.rAI.lAI.pLMNID.size); - OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC, - (const char *)ue_id->choice.pTMSIRAI.rAI.lAI.lAC.buf, - ue_id->choice.pTMSIRAI.rAI.lAI.lAC.size); - OCTET_STRING_fromBuf(&accept.uE_Identity.choice.pTMSIRAI.rAI.rAC, - (const char *)ue_id->choice.pTMSIRAI.rAI.rAC.buf, - ue_id->choice.pTMSIRAI.rAI.rAC.size); - break; - - default: - LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Unsupportedccept UE ID (present=%d)\n", ue_id->present); - return -1; - } - - tmsi = ntohl(tmsi); - LOGHNB(hnb, DHNBAP, LOGL_DEBUG, "HNBAP register with TMSI %x\n", tmsi); - - ue = ue_context_by_tmsi(hnb->gw, tmsi); - if (!ue) - ue = ue_context_alloc(hnb, NULL, tmsi); - - asn1_u24_to_bitstring(&accept.context_ID, &ctx_id, ue->context_id); - - memset(&accept_out, 0, sizeof(accept_out)); - rc = hnbap_encode_ueregisteraccepties(&accept_out, &accept); - if (rc < 0) - return rc; - - msg = hnbap_generate_successful_outcome(HNBAP_ProcedureCode_id_UERegister, - HNBAP_Criticality_reject, - &asn_DEF_HNBAP_UERegisterAccept, - &accept_out); - - switch (ue_id->present) { - case HNBAP_UE_Identity_PR_tMSILAI: - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING, - &accept.uE_Identity.choice.tMSILAI.tMSI); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &accept.uE_Identity.choice.tMSILAI.lAI.pLMNID); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &accept.uE_Identity.choice.tMSILAI.lAI.lAC); - break; - - case HNBAP_UE_Identity_PR_pTMSIRAI: - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_BIT_STRING, - &accept.uE_Identity.choice.pTMSIRAI.pTMSI); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.pLMNID); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &accept.uE_Identity.choice.pTMSIRAI.rAI.lAI.lAC); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_OCTET_STRING, - &accept.uE_Identity.choice.pTMSIRAI.rAI.rAC); - break; - - default: - /* should never happen after above switch() */ - break; - } - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_UERegisterAccept, &accept_out); - - return hnbgw_hnbap_tx(hnb, msg); -} - -static int hnbgw_rx_hnb_deregister(struct hnb_context *ctx, ANY_t *in) -{ - HNBAP_HNBDe_RegisterIEs_t ies; - int rc; - - rc = hnbap_decode_hnbde_registeries(&ies, in); - if (rc < 0) - return rc; - - LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "HNB-DE-REGISTER cause=%s\n", hnbap_cause_str(&ies.cause)); - - hnbap_free_hnbde_registeries(&ies); - hnb_context_release(ctx); - - return 0; -} - -static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, ANY_t *in) -{ - struct hnb_context *hnb; - HNBAP_HNBRegisterRequestIEs_t ies; - int rc; - - rc = hnbap_decode_hnbregisterrequesties(&ies, in); - if (rc < 0) { - LOGHNB(ctx, DHNBAP, LOGL_ERROR, "Failure to decode HNB-REGISTER-REQ from %s: rc=%d\n", - ctx->identity_info, rc); - return rc; - } - - /* copy all identity parameters from the message to ctx */ - asn1_strncpy(ctx->identity_info, &ies.hnB_Identity.hNB_Identity_Info, - sizeof(ctx->identity_info)); - ctx->id.lac = asn1str_to_u16(&ies.lac); - ctx->id.sac = asn1str_to_u16(&ies.sac); - ctx->id.rac = asn1str_to_u8(&ies.rac); - ctx->id.cid = asn1bitstr_to_u28(&ies.cellIdentity); - gsm48_mcc_mnc_from_bcd(ies.plmNidentity.buf, &ctx->id.mcc, &ctx->id.mnc); - - llist_for_each_entry(hnb, &ctx->gw->hnb_list, list) { - if (hnb->hnb_registered && ctx != hnb && memcmp(&ctx->id, &hnb->id, sizeof(ctx->id)) == 0) { - struct osmo_fd *ofd = osmo_stream_srv_get_ofd(ctx->conn); - char *name = osmo_sock_get_name(ctx, ofd->fd); - LOGHNB(ctx, DHNBAP, LOGL_ERROR, "rejecting HNB-REGISTER-REQ with duplicate cell identity " - "MCC=%u,MNC=%u,LAC=%u,RAC=%u,SAC=%u,CID=%u from %s\n", - ctx->id.mcc, ctx->id.mnc, ctx->id.lac, ctx->id.rac, ctx->id.sac, ctx->id.cid, name); - talloc_free(name); - return hnbgw_tx_hnb_register_rej(ctx); - } - } - - ctx->hnb_registered = true; - - LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "HNB-REGISTER-REQ from %s\n", ctx->identity_info); - - /* Send HNBRegisterAccept */ - rc = hnbgw_tx_hnb_register_acc(ctx); - hnbap_free_hnbregisterrequesties(&ies); - return rc; -} - -static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, ANY_t *in) -{ - HNBAP_UERegisterRequestIEs_t ies; - struct ue_context *ue; - char imsi[16]; - int rc; - - rc = hnbap_decode_ueregisterrequesties(&ies, in); - if (rc < 0) - return rc; - - switch (ies.uE_Identity.present) { - case HNBAP_UE_Identity_PR_iMSI: - ranap_bcd_decode(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSI.buf, - ies.uE_Identity.choice.iMSI.size); - break; - case HNBAP_UE_Identity_PR_iMSIDS41: - ranap_bcd_decode(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIDS41.buf, - ies.uE_Identity.choice.iMSIDS41.size); - break; - case HNBAP_UE_Identity_PR_iMSIESN: - ranap_bcd_decode(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIESN.iMSIDS41.buf, - ies.uE_Identity.choice.iMSIESN.iMSIDS41.size); - break; - case HNBAP_UE_Identity_PR_tMSILAI: - case HNBAP_UE_Identity_PR_pTMSIRAI: - if (ctx->gw->config.hnbap_allow_tmsi) - rc = hnbgw_tx_ue_register_acc_tmsi(ctx, &ies.uE_Identity); - else - rc = hnbgw_tx_ue_register_rej_tmsi(ctx, &ies.uE_Identity); - /* all has been handled by TMSI, skip the IMSI code below */ - hnbap_free_ueregisterrequesties(&ies); - return rc; - default: - LOGHNB(ctx, DHNBAP, LOGL_NOTICE, "UE-REGISTER-REQ with unsupported UE Id type %d\n", - ies.uE_Identity.present); - hnbap_free_ueregisterrequesties(&ies); - return rc; - } - - LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "UE-REGISTER-REQ ID_type=%d imsi=%s cause=%ld\n", - ies.uE_Identity.present, imsi, ies.registration_Cause); - - ue = ue_context_by_imsi(ctx->gw, imsi); - if (!ue) - ue = ue_context_alloc(ctx, imsi, 0); - - hnbap_free_ueregisterrequesties(&ies); - /* Send UERegisterAccept */ - return hnbgw_tx_ue_register_acc(ue); -} - -static int hnbgw_rx_ue_deregister(struct hnb_context *ctx, ANY_t *in) -{ - HNBAP_UEDe_RegisterIEs_t ies; - struct ue_context *ue; - int rc; - uint32_t ctxid; - - rc = hnbap_decode_uede_registeries(&ies, in); - if (rc < 0) - return rc; - - ctxid = asn1bitstr_to_u24(&ies.context_ID); - - LOGHNB(ctx, DHNBAP, LOGL_DEBUG, "UE-DE-REGISTER context=%u cause=%s\n", ctxid, hnbap_cause_str(&ies.cause)); - - ue = ue_context_by_id(ctx->gw, ctxid); - if (ue) - ue_context_free(ue); - - hnbap_free_uede_registeries(&ies); - return 0; -} - -static int hnbgw_rx_err_ind(struct hnb_context *hnb, ANY_t *in) -{ - HNBAP_ErrorIndicationIEs_t ies; - int rc; - - rc = hnbap_decode_errorindicationies(&ies, in); - if (rc < 0) - return rc; - - LOGHNB(hnb, DHNBAP, LOGL_NOTICE, "HNBAP ERROR.ind, cause: %s\n", hnbap_cause_str(&ies.cause)); - - hnbap_free_errorindicationies(&ies); - return 0; -} - -static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, HNBAP_InitiatingMessage_t *imsg) -{ - int rc = 0; - - switch (imsg->procedureCode) { - case HNBAP_ProcedureCode_id_HNBRegister: /* 8.2 */ - rc = hnbgw_rx_hnb_register_req(hnb, &imsg->value); - break; - case HNBAP_ProcedureCode_id_HNBDe_Register: /* 8.3 */ - rc = hnbgw_rx_hnb_deregister(hnb, &imsg->value); - break; - case HNBAP_ProcedureCode_id_UERegister: /* 8.4 */ - rc = hnbgw_rx_ue_register_req(hnb, &imsg->value); - break; - case HNBAP_ProcedureCode_id_UEDe_Register: /* 8.5 */ - rc = hnbgw_rx_ue_deregister(hnb, &imsg->value); - break; - case HNBAP_ProcedureCode_id_ErrorIndication: /* 8.6 */ - rc = hnbgw_rx_err_ind(hnb, &imsg->value); - break; - case HNBAP_ProcedureCode_id_TNLUpdate: /* 8.9 */ - case HNBAP_ProcedureCode_id_HNBConfigTransfer: /* 8.10 */ - case HNBAP_ProcedureCode_id_RelocationComplete: /* 8.11 */ - case HNBAP_ProcedureCode_id_U_RNTIQuery: /* 8.12 */ - case HNBAP_ProcedureCode_id_privateMessage: - LOGHNB(hnb, DHNBAP, LOGL_NOTICE, "Unimplemented HNBAP Procedure %ld\n", imsg->procedureCode); - break; - default: - LOGHNB(hnb, DHNBAP, LOGL_NOTICE, "Unknown HNBAP Procedure %ld\n", imsg->procedureCode); - break; - } - - return rc; -} - -static int hnbgw_rx_successful_outcome_msg(struct hnb_context *hnb, HNBAP_SuccessfulOutcome_t *msg) -{ - /* We don't care much about HNBAP */ - return 0; -} - -static int hnbgw_rx_unsuccessful_outcome_msg(struct hnb_context *hnb, HNBAP_UnsuccessfulOutcome_t *msg) -{ - /* We don't care much about HNBAP */ - LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Received Unsuccessful Outcome, procedureCode %ld, criticality %ld," - " cell mcc %u mnc %u lac %u rac %u sac %u cid %u\n", msg->procedureCode, msg->criticality, - hnb->id.mcc, hnb->id.mnc, hnb->id.lac, hnb->id.rac, hnb->id.sac, hnb->id.cid); - return 0; -} - - -static int _hnbgw_hnbap_rx(struct hnb_context *hnb, HNBAP_HNBAP_PDU_t *pdu) -{ - int rc = 0; - - /* it's a bit odd that we can't dispatch on procedure code, but - * that's not possible */ - switch (pdu->present) { - case HNBAP_HNBAP_PDU_PR_initiatingMessage: - rc = hnbgw_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage); - break; - case HNBAP_HNBAP_PDU_PR_successfulOutcome: - rc = hnbgw_rx_successful_outcome_msg(hnb, &pdu->choice.successfulOutcome); - break; - case HNBAP_HNBAP_PDU_PR_unsuccessfulOutcome: - rc = hnbgw_rx_unsuccessful_outcome_msg(hnb, &pdu->choice.unsuccessfulOutcome); - break; - default: - LOGHNB(hnb, DHNBAP, LOGL_NOTICE, "Unknown HNBAP Presence %u\n", pdu->present); - rc = -1; - } - - return rc; -} - -int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg) -{ - HNBAP_HNBAP_PDU_t _pdu, *pdu = &_pdu; - asn_dec_rval_t dec_ret; - int rc; - - /* decode and handle to _hnbgw_hnbap_rx() */ - - memset(pdu, 0, sizeof(*pdu)); - dec_ret = aper_decode(NULL, &asn_DEF_HNBAP_HNBAP_PDU, (void **) &pdu, - msg->data, msgb_length(msg), 0, 0); - if (dec_ret.code != RC_OK) { - LOGHNB(hnb, DHNBAP, LOGL_ERROR, "Error in ASN.1 decode\n"); - return -1; - } - - rc = _hnbgw_hnbap_rx(hnb, pdu); - - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_HNBAP_HNBAP_PDU, pdu); - - return rc; -} - - -int hnbgw_hnbap_init(void) -{ - return 0; -} diff --git a/src/hnbgw_ranap.c b/src/hnbgw_ranap.c deleted file mode 100644 index 445d4630..00000000 --- a/src/hnbgw_ranap.c +++ /dev/null @@ -1,210 +0,0 @@ -/* hnb-gw specific code for RANAP */ - -/* (C) 2015 by Harald Welte - * 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 . - * - */ - - - -#include -#include - -#include -#include -#include - -#include "asn1helpers.h" - -#include -#include -#include -#include -#include - -static int ranap_tx_reset_ack(struct hnb_context *hnb, - RANAP_CN_DomainIndicator_t domain) -{ - struct msgb *msg; - int rc; - - msg = ranap_new_msg_reset_ack(domain, NULL); - if (!msg) - return -1; - - rc = rua_tx_udt(hnb, msg->data, msgb_length(msg)); - - msgb_free(msg); - - return rc; -} - -static int ranap_rx_init_reset(struct hnb_context *hnb, ANY_t *in) -{ - RANAP_ResetIEs_t ies; - int rc, is_ps = 0; - - rc = ranap_decode_reseties(&ies, in); - if (rc < 0) - return rc; - - if (ies.cN_DomainIndicator == RANAP_CN_DomainIndicator_ps_domain) - is_ps=1; - - LOGHNB(hnb, DRANAP, LOGL_INFO, "Rx RESET.req(%s,%s)\n", is_ps ? "ps" : "cs", - ranap_cause_str(&ies.cause)); - - /* FIXME: Actually we have to wait for some guard time? */ - /* FIXME: Reset all resources related to this HNB/RNC */ - ranap_tx_reset_ack(hnb, ies.cN_DomainIndicator); - - return 0; -} - -static int ranap_rx_error_ind(struct hnb_context *hnb, ANY_t *in) -{ - RANAP_ErrorIndicationIEs_t ies; - int rc; - - rc = ranap_decode_errorindicationies(&ies, in); - if (rc < 0) - return rc; - - if (ies.presenceMask & ERRORINDICATIONIES_RANAP_CAUSE_PRESENT) { - LOGHNB(hnb, DRANAP, LOGL_ERROR, "Rx ERROR.ind(%s)\n", ranap_cause_str(&ies.cause)); - } else - LOGHNB(hnb, DRANAP, LOGL_ERROR, "Rx ERROR.ind\n"); - - return 0; -} - -static int ranap_rx_initiating_msg(struct hnb_context *hnb, RANAP_InitiatingMessage_t *imsg) -{ - int rc = 0; - - /* according tot the spec, we can primarily receive Overload, - * Reset, Reset ACK, Error Indication, reset Resource, Reset - * Resurce Acknowledge as connecitonless RANAP. There are some - * more messages regarding Information Transfer, Direct - * Information Transfer and Uplink Information Trnansfer that we - * can ignore. In either case, it is RANAP that we need to - * decode... */ - switch (imsg->procedureCode) { - case RANAP_ProcedureCode_id_Reset: - /* Reset request */ - rc = ranap_rx_init_reset(hnb, &imsg->value); - break; - case RANAP_ProcedureCode_id_OverloadControl: /* Overload ind */ - break; - case RANAP_ProcedureCode_id_ErrorIndication: /* Error ind */ - rc = ranap_rx_error_ind(hnb, &imsg->value); - break; - case RANAP_ProcedureCode_id_ResetResource: /* request */ - case RANAP_ProcedureCode_id_InformationTransfer: - case RANAP_ProcedureCode_id_DirectInformationTransfer: - case RANAP_ProcedureCode_id_UplinkInformationExchange: - LOGHNB(hnb, DRANAP, LOGL_NOTICE, "Received unsupported RANAP " - "Procedure %lu from HNB, ignoring\n", imsg->procedureCode); - break; - default: - LOGHNB(hnb, DRANAP, LOGL_NOTICE, "Received suspicious RANAP " - "Procedure %lu from HNB, ignoring\n", imsg->procedureCode); - break; - } - - return rc; -} - -static int ranap_rx_successful_msg(struct hnb_context *hnb, RANAP_SuccessfulOutcome_t *imsg) -{ - /* according tot the spec, we can primarily receive Overload, - * Reset, Reset ACK, Error Indication, reset Resource, Reset - * Resurce Acknowledge as connecitonless RANAP. There are some - * more messages regarding Information Transfer, Direct - * Information Transfer and Uplink Information Trnansfer that we - * can ignore. In either case, it is RANAP that we need to - * decode... */ - switch (imsg->procedureCode) { - case RANAP_ProcedureCode_id_Reset: /* Reset acknowledge */ - break; - case RANAP_ProcedureCode_id_ResetResource: /* response */ - case RANAP_ProcedureCode_id_InformationTransfer: - case RANAP_ProcedureCode_id_DirectInformationTransfer: - case RANAP_ProcedureCode_id_UplinkInformationExchange: - LOGHNB(hnb, DRANAP, LOGL_NOTICE, "Received unsupported RANAP " - "Procedure %lu from HNB, ignoring\n", imsg->procedureCode); - break; - default: - LOGHNB(hnb, DRANAP, LOGL_NOTICE, "Received suspicious RANAP " - "Procedure %lu from HNB, ignoring\n", imsg->procedureCode); - break; - } - - return 0; -} - - - -static int _hnbgw_ranap_rx(struct hnb_context *hnb, RANAP_RANAP_PDU_t *pdu) -{ - int rc = 0; - - switch (pdu->present) { - case RANAP_RANAP_PDU_PR_initiatingMessage: - rc = ranap_rx_initiating_msg(hnb, &pdu->choice.initiatingMessage); - break; - case RANAP_RANAP_PDU_PR_successfulOutcome: - rc = ranap_rx_successful_msg(hnb, &pdu->choice.successfulOutcome); - break; - case RANAP_RANAP_PDU_PR_unsuccessfulOutcome: - LOGHNB(hnb, DRANAP, LOGL_NOTICE, "Received unsupported RANAP " - "unsuccessful outcome procedure %lu from HNB, ignoring\n", - pdu->choice.unsuccessfulOutcome.procedureCode); - break; - default: - LOGHNB(hnb, DRANAP, LOGL_NOTICE, "Received suspicious RANAP " - "presence %u from HNB, ignoring\n", pdu->present); - break; - } - - return rc; -} - - -int hnbgw_ranap_rx(struct msgb *msg, uint8_t *data, size_t len) -{ - RANAP_RANAP_PDU_t _pdu, *pdu = &_pdu; - struct hnb_context *hnb = msg->dst; - asn_dec_rval_t dec_ret; - int rc; - - memset(pdu, 0, sizeof(*pdu)); - dec_ret = aper_decode(NULL,&asn_DEF_RANAP_RANAP_PDU, (void **) &pdu, - data, len, 0, 0); - if (dec_ret.code != RC_OK) { - LOGHNB(hnb, DRANAP, LOGL_ERROR, "Error in RANAP ASN.1 decode\n"); - return -1; - } - - rc = _hnbgw_ranap_rx(hnb, pdu); - - return rc; -} - -int hnbgw_ranap_init(void) -{ - return 0; -} diff --git a/src/hnbgw_rua.c b/src/hnbgw_rua.c deleted file mode 100644 index c625bcf2..00000000 --- a/src/hnbgw_rua.c +++ /dev/null @@ -1,566 +0,0 @@ -/* hnb-gw specific code for RUA (Ranap User Adaption) */ - -/* (C) 2015 by Harald Welte - * 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 . - * - */ - - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "asn1helpers.h" - -#include -#include -#include -#include -#include -#include - -static const char *cn_domain_indicator_to_str(RUA_CN_DomainIndicator_t cN_DomainIndicator) -{ - switch (cN_DomainIndicator) { - case RUA_CN_DomainIndicator_cs_domain: - return "IuCS"; - case RUA_CN_DomainIndicator_ps_domain: - return "IuPS"; - default: - return "(unknown-domain)"; - } -} - -static int hnbgw_rua_tx(struct hnb_context *ctx, struct msgb *msg) -{ - if (!msg) - return -EINVAL; - - msgb_sctp_ppid(msg) = IUH_PPI_RUA; - osmo_stream_srv_send(ctx->conn, msg); - - return 0; -} - -int rua_tx_udt(struct hnb_context *hnb, const uint8_t *data, unsigned int len) -{ - RUA_ConnectionlessTransfer_t out; - RUA_ConnectionlessTransferIEs_t ies; - struct msgb *msg; - int rc; - - memset(&ies, 0, sizeof(ies)); - ies.ranaP_Message.buf = (uint8_t *) data; - ies.ranaP_Message.size = len; - - /* FIXME: msgb_free(msg)? ownership not yet clear */ - - memset(&out, 0, sizeof(out)); - rc = rua_encode_connectionlesstransferies(&out, &ies); - if (rc < 0) - return rc; - - msg = rua_generate_initiating_message(RUA_ProcedureCode_id_ConnectionlessTransfer, - RUA_Criticality_reject, - &asn_DEF_RUA_ConnectionlessTransfer, - &out); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_ConnectionlessTransfer, &out); - - LOGHNB(hnb, DRUA, LOGL_DEBUG, "transmitting RUA payload of %u bytes\n", msgb_length(msg)); - - return hnbgw_rua_tx(hnb, msg); -} - -int rua_tx_dt(struct hnb_context *hnb, int is_ps, uint32_t context_id, - const uint8_t *data, unsigned int len) -{ - RUA_DirectTransfer_t out; - RUA_DirectTransferIEs_t ies; - uint32_t ctxidbuf; - struct msgb *msg; - int rc; - - memset(&ies, 0, sizeof(ies)); - if (is_ps) - ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain; - else - ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain; - asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id); - ies.ranaP_Message.buf = (uint8_t *) data; - ies.ranaP_Message.size = len; - - /* FIXME: msgb_free(msg)? ownership not yet clear */ - - memset(&out, 0, sizeof(out)); - rc = rua_encode_directtransferies(&out, &ies); - if (rc < 0) - return rc; - - msg = rua_generate_initiating_message(RUA_ProcedureCode_id_DirectTransfer, - RUA_Criticality_reject, - &asn_DEF_RUA_DirectTransfer, - &out); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_DirectTransfer, &out); - - LOGHNB(hnb, DRUA, LOGL_DEBUG, "transmitting RUA (cn=%s) payload of %u bytes\n", - is_ps ? "ps" : "cs", msgb_length(msg)); - - return hnbgw_rua_tx(hnb, msg); -} - -int rua_tx_disc(struct hnb_context *hnb, int is_ps, uint32_t context_id, - const RUA_Cause_t *cause, const uint8_t *data, unsigned int len) -{ - RUA_Disconnect_t out; - RUA_DisconnectIEs_t ies; - struct msgb *msg; - uint32_t ctxidbuf; - int rc; - - memset(&ies, 0, sizeof(ies)); - if (is_ps) - ies.cN_DomainIndicator = RUA_CN_DomainIndicator_ps_domain; - else - ies.cN_DomainIndicator = RUA_CN_DomainIndicator_cs_domain; - asn1_u24_to_bitstring(&ies.context_ID, &ctxidbuf, context_id); - memcpy(&ies.cause, cause, sizeof(ies.cause)); - if (data && len) { - ies.presenceMask |= DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT; - ies.ranaP_Message.buf = (uint8_t *) data; - ies.ranaP_Message.size = len; - } - - /* FIXME: msgb_free(msg)? ownership not yet clear */ - - memset(&out, 0, sizeof(out)); - rc = rua_encode_disconnecties(&out, &ies); - if (rc < 0) - return rc; - - msg = rua_generate_initiating_message(RUA_ProcedureCode_id_Disconnect, - RUA_Criticality_reject, - &asn_DEF_RUA_Disconnect, - &out); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RUA_Disconnect, &out); - - LOGHNB(hnb, DRUA, LOGL_DEBUG, "transmitting RUA (cn=%s) payload of %u bytes\n", - is_ps ? "ps" : "cs", msgb_length(msg)); - - - return hnbgw_rua_tx(hnb, msg); -} - - - -/* forward a RUA message to the SCCP User API to SCCP */ -static int rua_to_scu(struct hnb_context *hnb, - RUA_CN_DomainIndicator_t cN_DomainIndicator, - enum osmo_scu_prim_type type, - uint32_t context_id, uint32_t cause, - const uint8_t *data, unsigned int len) -{ - struct msgb *msg; - struct osmo_scu_prim *prim; - struct hnbgw_context_map *map = NULL; - struct hnbgw_cnlink *cn = hnb->gw->sccp.cnlink; - struct osmo_sccp_addr *remote_addr; - bool is_ps; - bool release_context_map = false; - int rc; - - switch (cN_DomainIndicator) { - case RUA_CN_DomainIndicator_cs_domain: - remote_addr = &hnb->gw->sccp.iucs_remote_addr; - is_ps = false; - break; - case RUA_CN_DomainIndicator_ps_domain: - remote_addr = &hnb->gw->sccp.iups_remote_addr; - is_ps = true; - break; - default: - LOGHNB(hnb, DRUA, LOGL_ERROR, "Unsupported Domain %ld\n", cN_DomainIndicator); - return -1; - } - - if (!cn) { - LOGHNB(hnb, DRUA, LOGL_NOTICE, "CN=NULL, discarding message\n"); - return 0; - } - - msg = msgb_alloc(1500, "rua_to_sccp"); - - prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim)); - osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg); - - switch (type) { - case OSMO_SCU_PRIM_N_UNITDATA: - LOGHNB(hnb, DRUA, LOGL_DEBUG, "rua_to_scu() %s to %s, rua_ctx_id %u (unitdata, no scu_conn_id)\n", - cn_domain_indicator_to_str(cN_DomainIndicator), osmo_sccp_addr_dump(remote_addr), context_id); - break; - default: - map = context_map_alloc_by_hnb(hnb, context_id, is_ps, cn); - OSMO_ASSERT(map); - LOGHNB(hnb, DRUA, LOGL_DEBUG, "rua_to_scu() %s to %s, rua_ctx_id %u scu_conn_id %u\n", - cn_domain_indicator_to_str(cN_DomainIndicator), osmo_sccp_addr_dump(remote_addr), - map->rua_ctx_id, map->scu_conn_id); - } - - /* add primitive header */ - switch (type) { - case OSMO_SCU_PRIM_N_CONNECT: - prim->u.connect.called_addr = *remote_addr; - prim->u.connect.calling_addr = cn->gw->sccp.local_addr; - prim->u.connect.sccp_class = 2; - prim->u.connect.conn_id = map->scu_conn_id; - /* Two separate logs because of osmo_sccp_addr_dump(). */ - LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA to SCCP N_CONNECT: called_addr:%s\n", - osmo_sccp_addr_dump(&prim->u.connect.called_addr)); - LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA to SCCP N_CONNECT: calling_addr:%s\n", - osmo_sccp_addr_dump(&prim->u.connect.calling_addr)); - break; - case OSMO_SCU_PRIM_N_DATA: - prim->u.data.conn_id = map->scu_conn_id; - break; - case OSMO_SCU_PRIM_N_DISCONNECT: - prim->u.disconnect.conn_id = map->scu_conn_id; - prim->u.disconnect.cause = cause; - release_context_map = true; - break; - case OSMO_SCU_PRIM_N_UNITDATA: - prim->u.unitdata.called_addr = *remote_addr; - prim->u.unitdata.calling_addr = cn->gw->sccp.local_addr; - /* Two separate logs because of osmo_sccp_addr_dump(). */ - LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA to SCCP N_UNITDATA: called_addr:%s\n", - osmo_sccp_addr_dump(&prim->u.unitdata.called_addr)); - LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA to SCCP N_UNITDATA: calling_addr:%s\n", - osmo_sccp_addr_dump(&prim->u.unitdata.calling_addr)); - break; - default: - return -EINVAL; - } - - /* add optional data section, if needed */ - if (data && len) { - msg->l2h = msgb_put(msg, len); - memcpy(msg->l2h, data, len); - } - - rc = osmo_sccp_user_sap_down(cn->sccp_user, &prim->oph); - - if (map && release_context_map) - context_map_deactivate(map); - - return rc; -} - -static uint32_t rua_to_scu_cause(RUA_Cause_t *in) -{ - /* FIXME: Implement this! */ -#if 0 - switch (in->present) { - case RUA_Cause_PR_NOTHING: - break; - case RUA_Cause_PR_radioNetwork: - switch (in->choice.radioNetwork) { - case RUA_CauseRadioNetwork_normal: - case RUA_CauseRadioNetwork_connect_failed: - case RUA_CauseRadioNetwork_network_release: - case RUA_CauseRadioNetwork_unspecified: - } - break; - case RUA_Cause_PR_transport: - switch (in->choice.transport) { - case RUA_CauseTransport_transport_resource_unavailable: - break; - case RUA_CauseTransport_unspecified: - break; - } - break; - case RUA_Cause_PR_protocol: - switch (in->choice.protocol) { - case RUA_CauseProtocol_transfer_syntax_error: - break; - case RUA_CauseProtocol_abstract_syntax_error_reject: - break; - case RUA_CauseProtocol_abstract_syntax_error_ignore_and_notify: - break; - case RUA_CauseProtocol_message_not_compatible_with_receiver_state: - break; - case RUA_CauseProtocol_semantic_error: - break; - case RUA_CauseProtocol_unspecified: - break; - case RUA_CauseProtocol_abstract_syntax_error_falsely_constructed_message: - break; - } - break; - case RUA_Cause_PR_misc: - switch (in->choice.misc) { - case RUA_CauseMisc_processing_overload: - break; - case RUA_CauseMisc_hardware_failure: - break; - case RUA_CauseMisc_o_and_m_intervention: - break; - case RUA_CauseMisc_unspecified: - break; - } - break; - default: - break; - } -#else - return 0; -#endif - -} - -static int rua_rx_init_connect(struct msgb *msg, ANY_t *in) -{ - RUA_ConnectIEs_t ies; - struct hnb_context *hnb = msg->dst; - uint32_t context_id; - int rc; - - rc = rua_decode_connecties(&ies, in); - if (rc < 0) - return rc; - - context_id = asn1bitstr_to_u24(&ies.context_ID); - - LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA %s Connect.req(ctx=0x%x, %s)\n", - cn_domain_indicator_to_str(ies.cN_DomainIndicator), context_id, - ies.establishment_Cause == RUA_Establishment_Cause_emergency_call ? "emergency" : "normal"); - - rc = rua_to_scu(hnb, ies.cN_DomainIndicator, OSMO_SCU_PRIM_N_CONNECT, - context_id, 0, ies.ranaP_Message.buf, - ies.ranaP_Message.size); - - rua_free_connecties(&ies); - - return rc; -} - -static int rua_rx_init_disconnect(struct msgb *msg, ANY_t *in) -{ - RUA_DisconnectIEs_t ies; - struct hnb_context *hnb = msg->dst; - uint32_t context_id; - uint32_t scu_cause; - uint8_t *ranap_data = NULL; - unsigned int ranap_len = 0; - int rc; - - rc = rua_decode_disconnecties(&ies, in); - if (rc < 0) - return rc; - - context_id = asn1bitstr_to_u24(&ies.context_ID); - scu_cause = rua_to_scu_cause(&ies.cause); - - LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA Disconnect.req(ctx=0x%x,cause=%s)\n", context_id, - rua_cause_str(&ies.cause)); - - if (ies.presenceMask & DISCONNECTIES_RUA_RANAP_MESSAGE_PRESENT) { - ranap_data = ies.ranaP_Message.buf; - ranap_len = ies.ranaP_Message.size; - } - - rc = rua_to_scu(hnb, ies.cN_DomainIndicator, - OSMO_SCU_PRIM_N_DISCONNECT, - context_id, scu_cause, ranap_data, ranap_len); - - rua_free_disconnecties(&ies); - - return rc; -} - -static int rua_rx_init_dt(struct msgb *msg, ANY_t *in) -{ - RUA_DirectTransferIEs_t ies; - struct hnb_context *hnb = msg->dst; - uint32_t context_id; - int rc; - - rc = rua_decode_directtransferies(&ies, in); - if (rc < 0) - return rc; - - context_id = asn1bitstr_to_u24(&ies.context_ID); - - LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA Data.req(ctx=0x%x)\n", context_id); - - rc = rua_to_scu(hnb, - ies.cN_DomainIndicator, - OSMO_SCU_PRIM_N_DATA, - context_id, 0, ies.ranaP_Message.buf, - ies.ranaP_Message.size); - - rua_free_directtransferies(&ies); - - return rc; -} - -static int rua_rx_init_udt(struct msgb *msg, ANY_t *in) -{ - RUA_ConnectionlessTransferIEs_t ies; - struct hnb_context *hnb = msg->dst; - int rc; - - rc = rua_decode_connectionlesstransferies(&ies, in); - if (rc < 0) - return rc; - - LOGHNB(hnb, DRUA, LOGL_DEBUG, "RUA UData.req()\n"); - - /* according tot the spec, we can primarily receive Overload, - * Reset, Reset ACK, Error Indication, reset Resource, Reset - * Resurce Acknowledge as connecitonless RANAP. There are some - * more messages regarding Information Transfer, Direct - * Information Transfer and Uplink Information Trnansfer that we - * can ignore. In either case, it is RANAP that we need to - * decode... */ - rc = hnbgw_ranap_rx(msg, ies.ranaP_Message.buf, ies.ranaP_Message.size); - rua_free_connectionlesstransferies(&ies); - - return rc; -} - - -static int rua_rx_init_err_ind(struct msgb *msg, ANY_t *in) -{ - RUA_ErrorIndicationIEs_t ies; - struct hnb_context *hnb = msg->dst; - int rc; - - rc = rua_decode_errorindicationies(&ies, in); - if (rc < 0) - return rc; - - LOGHNB(hnb, DRUA, LOGL_ERROR, "RUA UData.ErrorInd(%s)\n", rua_cause_str(&ies.cause)); - - rua_free_errorindicationies(&ies); - return rc; -} - -static int rua_rx_initiating_msg(struct msgb *msg, RUA_InitiatingMessage_t *imsg) -{ - struct hnb_context *hnb = msg->dst; - int rc; - - switch (imsg->procedureCode) { - case RUA_ProcedureCode_id_Connect: - rc = rua_rx_init_connect(msg, &imsg->value); - break; - case RUA_ProcedureCode_id_DirectTransfer: - rc = rua_rx_init_dt(msg, &imsg->value); - break; - case RUA_ProcedureCode_id_Disconnect: - rc = rua_rx_init_disconnect(msg, &imsg->value); - break; - case RUA_ProcedureCode_id_ConnectionlessTransfer: - rc = rua_rx_init_udt(msg, &imsg->value); - break; - case RUA_ProcedureCode_id_ErrorIndication: - rc = rua_rx_init_err_ind(msg, &imsg->value); - break; - case RUA_ProcedureCode_id_privateMessage: - LOGHNB(hnb, DRUA, LOGL_NOTICE, "Unhandled: RUA Initiating Msg: Private Msg\n"); - rc = 0; - break; - default: - LOGHNB(hnb, DRUA, LOGL_NOTICE, "Unknown RUA Procedure %lu\n", imsg->procedureCode); - rc = -1; - } - - return rc; -} - -static int rua_rx_successful_outcome_msg(struct msgb *msg, RUA_SuccessfulOutcome_t *in) -{ - struct hnb_context *hnb = msg->dst; - /* FIXME */ - LOGHNB(hnb, DRUA, LOGL_NOTICE, "Unexpected RUA Successful Outcome\n"); - return -1; -} - -static int rua_rx_unsuccessful_outcome_msg(struct msgb *msg, RUA_UnsuccessfulOutcome_t *in) -{ - struct hnb_context *hnb = msg->dst; - /* FIXME */ - LOGHNB(hnb, DRUA, LOGL_NOTICE, "Unexpected RUA Unsucessful Outcome\n"); - return -1; -} - - -static int _hnbgw_rua_rx(struct msgb *msg, RUA_RUA_PDU_t *pdu) -{ - struct hnb_context *hnb = msg->dst; - int rc; - - /* it's a bit odd that we can't dispatch on procedure code, but - * that's not possible */ - switch (pdu->present) { - case RUA_RUA_PDU_PR_initiatingMessage: - rc = rua_rx_initiating_msg(msg, &pdu->choice.initiatingMessage); - break; - case RUA_RUA_PDU_PR_successfulOutcome: - rc = rua_rx_successful_outcome_msg(msg, &pdu->choice.successfulOutcome); - break; - case RUA_RUA_PDU_PR_unsuccessfulOutcome: - rc = rua_rx_unsuccessful_outcome_msg(msg, &pdu->choice.unsuccessfulOutcome); - break; - default: - LOGHNB(hnb, DRUA, LOGL_NOTICE, "Unknown RUA presence %u\n", pdu->present); - rc = -1; - } - - return rc; -} - -int hnbgw_rua_rx(struct hnb_context *hnb, struct msgb *msg) -{ - RUA_RUA_PDU_t _pdu, *pdu = &_pdu; - asn_dec_rval_t dec_ret; - int rc; - - /* decode and handle to _hnbgw_hnbap_rx() */ - - memset(pdu, 0, sizeof(*pdu)); - dec_ret = aper_decode(NULL, &asn_DEF_RUA_RUA_PDU, (void **) &pdu, - msg->data, msgb_length(msg), 0, 0); - if (dec_ret.code != RC_OK) { - LOGHNB(hnb, DRUA, LOGL_ERROR, "Error in ASN.1 decode\n"); - return -1; - } - - rc = _hnbgw_rua_rx(msg, pdu); - - return rc; -} - - -int hnbgw_rua_init(void) -{ - return 0; -} diff --git a/src/hnbgw_vty.c b/src/hnbgw_vty.c deleted file mode 100644 index a826246f..00000000 --- a/src/hnbgw_vty.c +++ /dev/null @@ -1,418 +0,0 @@ -/* HNB-GW interface to quagga VTY */ - -/* (C) 2016 by sysmocom s.f.m.c. GmbH - * 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 . - * - */ - -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include - -static void *tall_hnb_ctx = NULL; -static struct hnb_gw *g_hnb_gw = NULL; - -static struct cmd_node hnbgw_node = { - HNBGW_NODE, - "%s(config-hnbgw)# ", - 1, -}; - -DEFUN(cfg_hnbgw, cfg_hnbgw_cmd, - "hnbgw", "Configure HNBGW options") -{ - vty->node = HNBGW_NODE; - return CMD_SUCCESS; -} - -static struct cmd_node iuh_node = { - IUH_NODE, - "%s(config-hnbgw-iuh)# ", - 1, -}; - -DEFUN(cfg_hnbgw_iuh, cfg_hnbgw_iuh_cmd, - "iuh", "Configure Iuh options") -{ - vty->node = IUH_NODE; - return CMD_SUCCESS; -} - -static struct cmd_node iucs_node = { - IUCS_NODE, - "%s(config-hnbgw-iucs)# ", - 1, -}; - -DEFUN(cfg_hnbgw_iucs, cfg_hnbgw_iucs_cmd, - "iucs", "Configure IuCS options") -{ - vty->node = IUCS_NODE; - return CMD_SUCCESS; -} - -static struct cmd_node iups_node = { - IUPS_NODE, - "%s(config-hnbgw-iups)# ", - 1, -}; - -DEFUN(cfg_hnbgw_iups, cfg_hnbgw_iups_cmd, - "iups", "Configure IuPS options") -{ - vty->node = IUPS_NODE; - return CMD_SUCCESS; -} - -int hnbgw_vty_go_parent(struct vty *vty) -{ - switch (vty->node) { - case IUH_NODE: - case IUCS_NODE: - case IUPS_NODE: - vty->node = HNBGW_NODE; - vty->index = NULL; - break; - case HNBGW_NODE: - vty->node = CONFIG_NODE; - vty->index = NULL; - break; - case CONFIG_NODE: - vty->node = ENABLE_NODE; - vty->index = NULL; - break; - default: - osmo_ss7_vty_go_parent(vty); - break; - } - - return vty->node; -} - -DEFUN(show_cnlink, show_cnlink_cmd, "show cnlink", - SHOW_STR "Display information on core network link\n") -{ - struct osmo_ss7_route *rt; - struct osmo_ss7_instance *ss7 = osmo_sccp_get_ss7(g_hnb_gw->sccp.client); -#define GUARD(STR) \ - STR ? STR : "", \ - STR ? ":" : "" - - vty_out(vty, "IuCS: %s <->", - osmo_sccp_user_name(g_hnb_gw->sccp.cnlink->sccp_user)); - vty_out(vty, " %s%s%s%s", - GUARD(g_hnb_gw->config.iucs_remote_addr_name), - osmo_sccp_inst_addr_name(g_hnb_gw->sccp.client, &g_hnb_gw->sccp.iucs_remote_addr), - VTY_NEWLINE); - - rt = osmo_ss7_route_lookup(ss7, g_hnb_gw->sccp.iucs_remote_addr.pc); - vty_out(vty, " SS7 route: %s%s", osmo_ss7_route_name(rt, true), VTY_NEWLINE); - - vty_out(vty, "IuPS: %s <->", - osmo_sccp_user_name(g_hnb_gw->sccp.cnlink->sccp_user)); - vty_out(vty, " %s%s%s%s", - GUARD(g_hnb_gw->config.iups_remote_addr_name), - osmo_sccp_inst_addr_name(g_hnb_gw->sccp.client, &g_hnb_gw->sccp.iups_remote_addr), - VTY_NEWLINE); - - rt = osmo_ss7_route_lookup(ss7, g_hnb_gw->sccp.iups_remote_addr.pc); - vty_out(vty, " SS7 route: %s%s", osmo_ss7_route_name(rt, true), VTY_NEWLINE); - -#undef GUARD - return CMD_SUCCESS; -} - -static void vty_out_ofd_addr(struct vty *vty, struct osmo_fd *ofd) -{ - char *name; - if (!ofd || ofd->fd < 0 - || !(name = osmo_sock_get_name(vty, ofd->fd))) { - vty_out(vty, "(no addr)"); - return; - } - vty_out(vty, "%s", name); - talloc_free(name); -} - -static void vty_dump_hnb_info__map_states(struct vty *vty, const char *name, unsigned int count, - unsigned int state_count[]) -{ - unsigned int i; - if (!count) - return; - vty_out(vty, " %s: %u contexts:", name, count); - for (i = 0; i <= MAP_S_NUM_STATES; i++) { - if (!state_count[i]) - continue; - vty_out(vty, " %s:%u", hnbgw_context_map_state_name(i), state_count[i]); - } - vty_out(vty, VTY_NEWLINE); -} - -static void vty_dump_hnb_info(struct vty *vty, struct hnb_context *hnb) -{ - struct hnbgw_context_map *map; - unsigned int map_count[2] = {}; - unsigned int state_count[2][MAP_S_NUM_STATES + 1] = {}; - - vty_out(vty, "HNB "); - vty_out_ofd_addr(vty, hnb->conn? osmo_stream_srv_get_ofd(hnb->conn) : NULL); - vty_out(vty, " \"%s\"%s", hnb->identity_info, VTY_NEWLINE); - vty_out(vty, " MCC %u MNC %u LAC %u RAC %u SAC %u CID %u SCTP-stream:HNBAP=%u,RUA=%u%s", - hnb->id.mcc, hnb->id.mnc, hnb->id.lac, hnb->id.rac, hnb->id.sac, hnb->id.cid, - hnb->hnbap_stream, hnb->rua_stream, VTY_NEWLINE); - - llist_for_each_entry(map, &hnb->map_list, hnb_list) { - map_count[map->is_ps? 1 : 0]++; - state_count[map->is_ps? 1 : 0] - [(map->state >= 0 && map->state < MAP_S_NUM_STATES)? - map->state : MAP_S_NUM_STATES]++; - } - vty_dump_hnb_info__map_states(vty, "IuCS", map_count[0], state_count[0]); - vty_dump_hnb_info__map_states(vty, "IuPS", map_count[1], state_count[1]); -} - -static void vty_dump_ue_info(struct vty *vty, struct ue_context *ue) -{ - vty_out(vty, "UE IMSI \"%s\" context ID %u%s", ue->imsi, ue->context_id, VTY_NEWLINE); -} - -DEFUN(show_hnb, show_hnb_cmd, "show hnb all", SHOW_STR "Display information about all HNB") -{ - struct hnb_context *hnb; - unsigned int count = 0; - - if (llist_empty(&g_hnb_gw->hnb_list)) { - vty_out(vty, "No HNB connected%s", VTY_NEWLINE); - return CMD_SUCCESS; - } - - llist_for_each_entry(hnb, &g_hnb_gw->hnb_list, list) { - vty_dump_hnb_info(vty, hnb); - count++; - } - - vty_out(vty, "%u HNB connected%s", count, VTY_NEWLINE); - - return CMD_SUCCESS; -} - -DEFUN(show_one_hnb, show_one_hnb_cmd, "show hnb NAME ", SHOW_STR "Display information about a HNB") -{ - struct hnb_context *hnb; - const char *identity_info = argv[0]; - - if (llist_empty(&g_hnb_gw->hnb_list)) { - vty_out(vty, "No HNB connected%s", VTY_NEWLINE); - return CMD_SUCCESS; - } - - hnb = hnb_context_by_identity_info(g_hnb_gw, identity_info); - if (hnb == NULL) { - vty_out(vty, "No HNB found with identity '%s'%s", identity_info, VTY_NEWLINE); - return CMD_SUCCESS; - } - - vty_dump_hnb_info(vty, hnb); - return CMD_SUCCESS; -} - -DEFUN(show_ue, show_ue_cmd, "show ue all", SHOW_STR "Display information about a UE") -{ - struct ue_context *ue; - - llist_for_each_entry(ue, &g_hnb_gw->ue_list, list) { - vty_dump_ue_info(vty, ue); - } - - return CMD_SUCCESS; -} - -DEFUN(show_talloc, show_talloc_cmd, "show talloc", SHOW_STR "Display talloc info") -{ - talloc_report_full(tall_hnb_ctx, stderr); - talloc_report_full(talloc_asn1_ctx, stderr); - - return CMD_SUCCESS; -} - -DEFUN(cfg_hnbgw_rnc_id, cfg_hnbgw_rnc_id_cmd, - "rnc-id <0-65535>", - "Configure the HNBGW's RNC Id, the common RNC Id used for all connected hNodeB. It is sent to" - " each hNodeB upon HNBAP HNB-Register-Accept, and the hNodeB will subsequently send this as" - " RANAP InitialUE Messages' GlobalRNC-ID IE. Takes effect as soon as the hNodeB re-registers.\n" - "RNC Id value\n") -{ - g_hnb_gw->config.rnc_id = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_hnbgw_iuh_local_ip, cfg_hnbgw_iuh_local_ip_cmd, "local-ip A.B.C.D", - "Accept Iuh connections on local interface\n" - "Local interface IP address (default: " HNBGW_LOCAL_IP_DEFAULT ")") -{ - talloc_free((void*)g_hnb_gw->config.iuh_local_ip); - g_hnb_gw->config.iuh_local_ip = talloc_strdup(tall_hnb_ctx, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_hnbgw_iuh_local_port, cfg_hnbgw_iuh_local_port_cmd, "local-port <1-65535>", - "Accept Iuh connections on local port\n" - "Local interface port (default: 29169)") -{ - g_hnb_gw->config.iuh_local_port = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_hnbgw_iuh_hnbap_allow_tmsi, cfg_hnbgw_iuh_hnbap_allow_tmsi_cmd, - "hnbap-allow-tmsi (0|1)", - "Allow HNBAP UE Register messages with TMSI or PTMSI identity\n" - "Only accept IMSI identity, reject TMSI or PTMSI\n" - "Accept IMSI, TMSI or PTMSI as UE identity\n") -{ - g_hnb_gw->config.hnbap_allow_tmsi = (*argv[0] == '1'); - return CMD_SUCCESS; -} - -DEFUN(cfg_hnbgw_log_prefix, cfg_hnbgw_log_prefix_cmd, - "log-prefix (hnb-id|umts-cell-id)", - "Configure the log message prefix\n" - "Use the hNB-ID as log message prefix\n" - "Use the UMTS Cell ID as log message prefix\n") -{ - if (!strcmp(argv[0], "hnb-id")) - g_hnb_gw->config.log_prefix_hnb_id = true; - else - g_hnb_gw->config.log_prefix_hnb_id = false; - return CMD_SUCCESS; -} - -DEFUN(cfg_hnbgw_iucs_remote_addr, - cfg_hnbgw_iucs_remote_addr_cmd, - "remote-addr NAME", - "SCCP address to send IuCS to (MSC)\n" - "SCCP address book entry name (see 'cs7-instance')\n") -{ - g_hnb_gw->config.iucs_remote_addr_name = talloc_strdup(g_hnb_gw, argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_hnbgw_iups_remote_addr, - cfg_hnbgw_iups_remote_addr_cmd, - "remote-addr NAME", - "SCCP address to send IuPS to (SGSN)\n" - "SCCP address book entry name (see 'cs7-instance')\n") -{ - g_hnb_gw->config.iups_remote_addr_name = talloc_strdup(g_hnb_gw, argv[0]); - return CMD_SUCCESS; -} - -static int config_write_hnbgw(struct vty *vty) -{ - vty_out(vty, "hnbgw%s", VTY_NEWLINE); - vty_out(vty, " log-prefix %s%s", g_hnb_gw->config.log_prefix_hnb_id ? "hnb-id" : "umts-cell-id", - VTY_NEWLINE); - return CMD_SUCCESS; -} - -static int config_write_hnbgw_iuh(struct vty *vty) -{ - const char *addr; - uint16_t port; - - vty_out(vty, " iuh%s", VTY_NEWLINE); - - addr = g_hnb_gw->config.iuh_local_ip; - if (addr && (strcmp(addr, HNBGW_LOCAL_IP_DEFAULT) != 0)) - vty_out(vty, " local-ip %s%s", addr, VTY_NEWLINE); - - port = g_hnb_gw->config.iuh_local_port; - if (port && port != IUH_DEFAULT_SCTP_PORT) - vty_out(vty, " local-port %u%s", port, VTY_NEWLINE); - - if (g_hnb_gw->config.hnbap_allow_tmsi) - vty_out(vty, " hnbap-allow-tmsi 1%s", VTY_NEWLINE); - - return CMD_SUCCESS; -} - -static int config_write_hnbgw_iucs(struct vty *vty) -{ - if (!g_hnb_gw->config.iucs_remote_addr_name) - return CMD_SUCCESS; - - vty_out(vty, " iucs%s", VTY_NEWLINE); - vty_out(vty, " remote-addr %s%s", g_hnb_gw->config.iucs_remote_addr_name, - VTY_NEWLINE); - - return CMD_SUCCESS; -} - -static int config_write_hnbgw_iups(struct vty *vty) -{ - if (!g_hnb_gw->config.iups_remote_addr_name) - return CMD_SUCCESS; - - vty_out(vty, " iups%s", VTY_NEWLINE); - vty_out(vty, " remote-addr %s%s", g_hnb_gw->config.iups_remote_addr_name, - VTY_NEWLINE); - - return CMD_SUCCESS; -} - -void hnbgw_vty_init(struct hnb_gw *gw, void *tall_ctx) -{ - g_hnb_gw = gw; - tall_hnb_ctx = tall_ctx; - - install_element(CONFIG_NODE, &cfg_hnbgw_cmd); - install_node(&hnbgw_node, config_write_hnbgw); - - install_element(HNBGW_NODE, &cfg_hnbgw_rnc_id_cmd); - install_element(HNBGW_NODE, &cfg_hnbgw_log_prefix_cmd); - - install_element(HNBGW_NODE, &cfg_hnbgw_iuh_cmd); - install_node(&iuh_node, config_write_hnbgw_iuh); - - install_element(IUH_NODE, &cfg_hnbgw_iuh_local_ip_cmd); - install_element(IUH_NODE, &cfg_hnbgw_iuh_local_port_cmd); - install_element(IUH_NODE, &cfg_hnbgw_iuh_hnbap_allow_tmsi_cmd); - - install_element(HNBGW_NODE, &cfg_hnbgw_iucs_cmd); - install_node(&iucs_node, config_write_hnbgw_iucs); - - install_element(IUCS_NODE, &cfg_hnbgw_iucs_remote_addr_cmd); - - install_element(HNBGW_NODE, &cfg_hnbgw_iups_cmd); - install_node(&iups_node, config_write_hnbgw_iups); - - install_element(IUPS_NODE, &cfg_hnbgw_iups_remote_addr_cmd); - - install_element_ve(&show_cnlink_cmd); - install_element_ve(&show_hnb_cmd); - install_element_ve(&show_one_hnb_cmd); - install_element_ve(&show_ue_cmd); - install_element_ve(&show_talloc_cmd); -}