Compare commits

..

5 Commits

Author SHA1 Message Date
Oliver Smith
a6e983b985 Bump version: 1.6.1.1-559f → 1.6.2
Change-Id: Ia04060e57019a2d1394f1f2bcd400d9a4ab5667f
2023-05-26 14:54:12 +02:00
Oliver Smith
559f4e8024 systemd: depend on networking-online.target
Related: SYS#6400
Change-Id: I29e547242b2ed1cfc4750c7d7e5f8636c2e8f3dc
2023-05-26 14:53:42 +02:00
Oliver Smith
c9b80363f4 Bump version: 1.6.0.2-42f8 → 1.6.1
Change-Id: I6a74dccada51f13c6c3a9f3fe08c1df2e9c2811b
2023-02-23 10:23:04 +01:00
Oliver Smith
42f82975f2 tests: adjust to XOR-3G rename in libosmocore
Fix forward compatibility to current master of libosmocore / future
versions where the value_string for OSMO_AUTH_ALG_XOR has been changed.
Adjust the tests so they pass with both the old and the new version.

Related: libosmocore I446e54d0ddf4a18c46ee022b1249af73552e3ce1
Change-Id: I391b1a9b52e1969172aba9d4a1cc5792fc077fe1
2023-02-23 10:22:30 +01:00
Oliver Smith
4af47bb3d8 Run struct_endianness.py
Ensure there is no diff to prepare to run this in CI.

Related: OS#5884
Change-Id: I4294a18871214b70cef267fcaaaaada42cb61bf9
(cherry picked from commit 62e5c1b2c7)
2023-02-23 10:22:25 +01:00
79 changed files with 640 additions and 2340 deletions

1
.github/FUNDING.yml vendored
View File

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

2
.gitignore vendored
View File

@@ -86,5 +86,3 @@ contrib/osmo-hlr.spec
/debian/osmo-mslookup-utils/ /debian/osmo-mslookup-utils/
/debian/*.log /debian/*.log
/debian/*.substvars /debian/*.substvars
include/osmocom/*/version.h

View File

@@ -11,9 +11,8 @@ SUBDIRS = \
EXTRA_DIST = \ EXTRA_DIST = \
.version \ .version \
README.md \ contrib/osmo-hlr.spec.in \
debian \ debian \
git-version-gen \
$(NULL) $(NULL)
AM_DISTCHECK_CONFIGURE_FLAGS = \ AM_DISTCHECK_CONFIGURE_FLAGS = \

View File

@@ -1,8 +1,8 @@
osmo-hlr - Osmocom HLR Implementation osmo-hlr - Osmocom HLR Implementation
===================================== =====================================
This repository contains a C-language implementation of a GSM *Home This repository contains a C-language implementation of a GSM Home
Location Register (HLR)*. It is part of the Location Register (HLR). It is part of the
[Osmocom](https://osmocom.org/) Open Source Mobile Communications [Osmocom](https://osmocom.org/) Open Source Mobile Communications
project. project.
@@ -10,14 +10,13 @@ Warning: While the HLR logical functionality is implemented, OsmoHLR
does not use the ETSI/3GPP TCAP/MAP protocol stack. Instead, a much does not use the ETSI/3GPP TCAP/MAP protocol stack. Instead, a much
simpler custom protocol (GSUP) is used. This means, OsmoHLR is of simpler custom protocol (GSUP) is used. This means, OsmoHLR is of
no use outside the context of an Osmocom core network. You can use no use outside the context of an Osmocom core network. You can use
it with [OsmoMSC](https://osmocom.org/projects/osmomsc/wiki), it with OsmoMSC, OsmoSGSN etc. - but not with third party components.
[OsmoSGSN](https://osmocom.org/projects/osmosgsn/wiki) etc. -
but not directly with third party components.
Homepage Homepage
-------- --------
The official homepage of the project is <https://osmocom.org/projects/osmo-hlr/wiki>. The official homepage of the project is
https://osmocom.org/projects/osmo-hlr/wiki
GIT Repository GIT Repository
-------------- --------------
@@ -34,18 +33,11 @@ Documentation
User Manuals and VTY reference manuals are [optionally] built in PDF form User Manuals and VTY reference manuals are [optionally] built in PDF form
as part of the build process. as part of the build process.
Pre-rendered PDF versions of the current `master` can be found at Pre-rendered PDF version of the current "master" can be found at
[User Manual](https://ftp.osmocom.org/docs/latest/osmohlr-usermanual.pdf)
* [User Manual](https://ftp.osmocom.org/docs/latest/osmohlr-usermanual.pdf) as well as the VTY reference manuals
* [VTY Reference Manual for osmo-hlr](https://ftp.osmocom.org/docs/latest/osmohlr-vty-reference.pdf) * [VTY Reference Manual for osmo-hlr](https://ftp.osmocom.org/docs/latest/osmohlr-vty-reference.pdf)
Forum
-----
We welcome any osmo-hlr related discussions in the
[Cellular Network Infrastructure -> 2G/3G Core Network](https://discourse.osmocom.org/c/cni/2g-3g-cn)
section of the osmocom discourse (web based Forum).
Mailing List Mailing List
------------ ------------
@@ -58,23 +50,16 @@ Please observe the [Osmocom Mailing List
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules) Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
when posting. when posting.
Issue Tracker
-------------
We use the [issue tracker of the osmo-hlr project on osmocom.org](https://osmocom.org/projects/osmo-hlr/issues) for
tracking the state of bug reports and feature requests. Feel free to submit any issues you may find, or help
us out by resolving existing issues.
Contributing Contributing
------------ ------------
Our coding standards are described at Our coding standards are described at
<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards> https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
We use a Gerrit based patch submission/review process for managing We us a gerrit based patch submission/review process for managing
contributions. Please see contributions. Please see
<https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for
more details more details
The current patch queue for osmo-hlr can be seen at The current patch queue for osmo-hlr can be seen at
<https://gerrit.osmocom.org/#/q/project:osmo-hlr+status:open> https://gerrit.osmocom.org/#/q/project:osmo-hlr+status:open

View File

@@ -1,9 +1,9 @@
# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install # When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release # according to https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info # In short:
# LIBVERSION=c:r:a # LIBVERSION=c:r:a
# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a. # If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a. # If any interfaces have been added, removed, or changed since the last update: c + 1:0:0.
# If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0. # If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line #library what description / commit summary line

View File

@@ -41,11 +41,11 @@ PKG_PROG_PKG_CONFIG([0.20])
PKG_CHECK_MODULES(TALLOC, [talloc >= 2.0.1]) PKG_CHECK_MODULES(TALLOC, [talloc >= 2.0.1])
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.11.0) PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.8.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.11.0) PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.8.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.11.0) PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.8.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.11.0) PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.8.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 2.0.0) PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.4.0)
PKG_CHECK_MODULES(SQLITE3, sqlite3) PKG_CHECK_MODULES(SQLITE3, sqlite3)
@@ -203,6 +203,7 @@ AC_OUTPUT(
contrib/Makefile contrib/Makefile
contrib/systemd/Makefile contrib/systemd/Makefile
contrib/dgsm/Makefile contrib/dgsm/Makefile
contrib/osmo-hlr.spec
tests/Makefile tests/Makefile
tests/auc/Makefile tests/auc/Makefile
tests/auc/gen_ts_55_205_test_sets/Makefile tests/auc/gen_ts_55_205_test_sets/Makefile

View File

@@ -29,8 +29,7 @@ export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
export LD_LIBRARY_PATH="$inst/lib" export LD_LIBRARY_PATH="$inst/lib"
export PATH="$inst/bin:$PATH" export PATH="$inst/bin:$PATH"
osmo-build-dep.sh libosmocore "" --disable-doxygen osmo-build-dep.sh libosmocore "" ac_cv_path_DOXYGEN=false
osmo-build-dep.sh libosmo-netif "" --disable-doxygen
osmo-build-dep.sh libosmo-abis osmo-build-dep.sh libosmo-abis
# Additional configure options and depends # Additional configure options and depends

195
contrib/osmo-hlr.spec.in Normal file
View File

@@ -0,0 +1,195 @@
#
# spec file for package osmo-hlr
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2016, Martin Hauke <mardnh@gmx.de>
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
Name: osmo-hlr
Version: @VERSION@
Release: 0
Summary: Osmocom Home Location Register for GSUP protocol towards OsmoSGSN and OsmoCSCN
License: AGPL-3.0-or-later AND GPL-2.0-or-later
Group: Productivity/Telephony/Servers
URL: https://osmocom.org/projects/osmo-hlr
Source: %{name}-%{version}.tar.xz
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libtool
BuildRequires: pkgconfig >= 0.20
BuildRequires: python3
%if 0%{?suse_version}
BuildRequires: systemd-rpm-macros
%endif
BuildRequires: pkgconfig(libosmoabis) >= 1.4.0
BuildRequires: pkgconfig(libosmocore) >= 1.8.0
BuildRequires: pkgconfig(libosmoctrl) >= 1.8.0
BuildRequires: pkgconfig(libosmogsm) >= 1.8.0
BuildRequires: pkgconfig(libosmovty) >= 1.8.0
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(talloc) >= 2.0.1
# only needed for populate_hlr_db.pl
Requires: libdbi-drivers-dbd-sqlite3
%{?systemd_requires}
%description
The GSUP HLR is a stand-alone HLR (Home Location Register) for SIM
and USIM based subscribers which exposes the GSUP protocol towards
its users. OsmoSGSN supports this protocol.
osmo-gsup-hlr is still very simplistic. It is a single-threaded
architecture and uses only sqlite3 tables as back-end. It is suitable
for installations of the scale that OsmoNITB was able to handle. It
also lacks various features like fine-grained control of subscribed
services (like supplementary services).
%package -n libosmo-gsup-client0
Summary: Osmocom GSUP (General Subscriber Update Protocol) client library
License: GPL-2.0-or-later
Group: System/Libraries
%description -n libosmo-gsup-client0
This is a shared library that can be used to implement client programs for
the GSUP protocol. The typical GSUP server is OsmoHLR, with OsmoMSC, OsmoSGSN
and External USSD Entities (EUSEs) using this library to implement clients.
%package -n libosmo-gsup-client-devel
Summary: Development files for the Osmocom GSUP client library
License: GPL-2.0-or-later
Group: Development/Libraries/C and C++
Requires: libosmo-gsup-client0 = %{version}
%description -n libosmo-gsup-client-devel
This is a shared library that can be used to implement client programs for
the GSUP protocol. The typical GSUP server is OsmoHLR, with OsmoMSC, OsmoSGSN
and External USSD Entities (EUSEs) using this library to implement clients.
This subpackage contains libraries and header files for developing
applications that want to make use of libosmo-gsup-client.
%package -n libosmo-mslookup1
Summary: Osmocom MS lookup library
License: GPL-2.0-or-later
Group: System/Libraries
%description -n libosmo-mslookup1
This shared library contains routines for looking up mobile subscribers.
%package -n libosmo-mslookup-devel
Summary: Development files for the Osmocom MS lookup library
License: GPL-2.0-or-later
Group: Development/Libraries/C and C++
Requires: libosmo-mslookup1 = %{version}
%description -n libosmo-mslookup-devel
This shared library contains routines for looking up mobile subscribers.
This subpackage contains libraries and header files for developing
applications that want to make use of libosmo-mslookup.
%package -n osmo-mslookup-client
Summary: Standalone program using libosmo-mslookup
License: GPL-2.0-or-later
Group: Development/Libraries/C and C++
%description -n osmo-mslookup-client
Standalone program using libosmo-mslookup to easily integrate with programs
that want to connect services (SIP, SMS,...) to the current location of a
subscriber.
%prep
%setup -q
%build
echo "%{version}" >.tarball-version
autoreconf -fi
%configure \
--docdir="%{_docdir}/%{name}" \
--with-systemdsystemunitdir=%{_unitdir} \
--enable-shared \
--disable-static
make V=1 %{?_smp_mflags}
%install
%make_install
install -d "%{buildroot}/%{_localstatedir}/lib/osmocom"
find %{buildroot} -type f -name "*.la" -delete -print
%check
make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%if 0%{?suse_version}
%preun
%service_del_preun %{name}.service
%postun
%service_del_postun %{name}.service
%pre
%service_add_pre %{name}.service
%endif
%post
%if 0%{?suse_version}
%service_add_post %{name}.service
%endif
/usr/share/osmocom/osmo-hlr-post-upgrade.sh
%post -n libosmo-gsup-client0 -p /sbin/ldconfig
%postun -n libosmo-gsup-client0 -p /sbin/ldconfig
%post -n libosmo-mslookup1 -p /sbin/ldconfig
%postun -n libosmo-mslookup1 -p /sbin/ldconfig
%files
%license COPYING
%dir %{_docdir}/%{name}
%dir %{_docdir}/%{name}/examples
%{_docdir}/%{name}/examples/osmo-hlr.cfg
%{_docdir}/%{name}/examples/osmo-hlr-dgsm.cfg
%dir %{_docdir}/%{name}/sql
%{_docdir}/%{name}/sql/hlr.sql
%{_docdir}/%{name}/sql//hlr_data.sql
%dir %{_sysconfdir}/osmocom
%dir %{_localstatedir}/lib/osmocom
%{_bindir}/osmo-hlr
%{_bindir}/osmo-hlr-db-tool
%dir %{_sysconfdir}/osmocom
%config %{_sysconfdir}/osmocom/osmo-hlr.cfg
%{_unitdir}/osmo-hlr.service
%dir %{_datadir}/osmocom
%{_datadir}/osmocom/osmo-hlr-post-upgrade.sh
%files -n libosmo-gsup-client0
%{_libdir}/libosmo-gsup-client.so.0*
%files -n libosmo-gsup-client-devel
%{_bindir}/osmo-euse-demo
%dir %{_includedir}/osmocom
%dir %{_includedir}/osmocom/gsupclient
%{_includedir}/osmocom/gsupclient/*.h
%{_libdir}/libosmo-gsup-client.so
%{_libdir}/pkgconfig/libosmo-gsup-client.pc
%files -n libosmo-mslookup1
%{_libdir}/libosmo-mslookup.so.1*
%files -n libosmo-mslookup-devel
%dir %{_includedir}/osmocom
%dir %{_includedir}/osmocom/mslookup
%{_includedir}/osmocom/mslookup/*.h
%{_libdir}/libosmo-mslookup.so
%{_libdir}/pkgconfig/libosmo-mslookup.pc
%files -n osmo-mslookup-client
%{_bindir}/osmo-mslookup-client
%changelog

View File

@@ -9,8 +9,6 @@ Type=simple
Restart=always Restart=always
StateDirectory=osmocom StateDirectory=osmocom
WorkingDirectory=%S/osmocom WorkingDirectory=%S/osmocom
User=osmocom
Group=osmocom
ExecStart=/usr/bin/osmo-hlr -c /etc/osmocom/osmo-hlr.cfg -l /var/lib/osmocom/hlr.db ExecStart=/usr/bin/osmo-hlr -c /etc/osmocom/osmo-hlr.cfg -l /var/lib/osmocom/hlr.db
RestartSec=2 RestartSec=2
ProtectHome=true ProtectHome=true

103
debian/changelog vendored
View File

@@ -1,106 +1,15 @@
osmo-hlr (1.9.1) unstable; urgency=medium osmo-hlr (1.6.2) unstable; urgency=medium
[ Pau Espin Pedrol ]
* Drop use of deprecated vty is_config_node() cb
[ Oliver Smith ]
* db: flush after changing schema version
-- Oliver Smith <osmith@sysmocom.de> Wed, 02 Apr 2025 15:12:35 +0200
osmo-hlr (1.9.0) unstable; urgency=medium
[ Vadim Yanitskiy ]
* subscriber-create-on-demand: rework configuration
* subscriber-create-on-demand: add mode for MSISDN=IMSI
[ Alexander Couzens ]
* gsupclient: Introduce gsup_client_mux
* gsupclient: add missing SPDX line
* debian/copyright: add gsup_client under GPLv2+
[ Pau Espin Pedrol ]
* gsup: Replace deprecated ipa_msg_push_header()
* jenkins.sh: libosmo-netif no longer depends on libosmo-abis
* Drop use of libosmo-abis osmocom/abis/ipaccess.h
* gsup_client: Add new APIs to avoid users accessing struct fields
* gsup_client: Avoid double memset 0
* Drop unneeded use of abis/ipa.h header
* jenkins.sh: Use --disable-doxygen configure param
[ Mychaela N. Falconia ]
* vty: always emit reject-cause lines in saved config
* change default reject cause to plmn-not-allowed
* change default no-proxy reject cause to net-fail
-- Oliver Smith <osmith@sysmocom.de> Wed, 12 Feb 2025 12:17:52 +0100
osmo-hlr (1.8.0) unstable; urgency=medium
[ Vadim Yanitskiy ]
* hlr_vty.c: drop redundant include of hlr_ussd.h
* build: include {README.md,git-version-gen} into the release tarball
* README.md: cosmetic: fix a typo
[ Mychaela N. Falconia ]
* SMS over GSUP: implement vty config of SMSC routing
* SMS over GSUP: implement forwarding of MO SMS
* SMS over GSUP: implement forwarding of MT SMS
* SMS over GSUP: handle READY-FOR-SM.req from MSCs
* ctrl: add subscriber.by-*.imsi GET-able variable
[ Andreas Eversberg ]
* Use uniform log format for default config files
[ Harald Welte ]
* Add funding link to github mirror
* README.md: Improve mark-down formatting
* README.md: Add Forum and Issue Tracker sections
[ Max ]
* .deb/.rpm: add osmocom user during package install
[ Oliver Smith ]
* .deb/.rpm: various fixes related to non-root
* contrib: remove rpm spec file
* debian/postinst: add checks, be verbose
* mslookup: don't ignore return value of write()
-- Oliver Smith <osmith@sysmocom.de> Wed, 24 Jul 2024 15:29:12 +0200
osmo-hlr (1.7.0) unstable; urgency=medium
[ Oliver Smith ]
* Run struct_endianness.py
* tests/db/db_test.err: adjust to XOR-3G rename
* debian: set compat level to 10
* systemd: depend on networking-online.target * systemd: depend on networking-online.target
[ Pau Espin Pedrol ] -- Oliver Smith <osmith@sysmocom.de> Fri, 26 May 2023 14:54:12 +0200
* mslookup: Call osmo_fd_unregister() before closing and changing bfd->fd
[ Vadim Yanitskiy ] osmo-hlr (1.6.1) unstable; urgency=medium
* tests/auc/Makefile.am: put object files to LDADD
* tests/*/Makefile.am: move -I to AM_CPPFLAGS
* lu_fsm: fix memleak in lu_fsm_wait_insert_data_result()
* ussd: fix GSUP memleaks in rx_proc_ss_{req,error}()
* gsup_server: fix msgb memleak in osmo_gsup_server_read_cb()
* USSD: fix handling of ussd-DataCodingScheme != 0x0f
[ Alexander Couzens ] * Run struct_endianness.py
* hlr: use talloc for memory allocation in osmo_gsup_create_insert_subscriber_data_msg * tests: adjust to XOR-3G rename in libosmocore
* Add support for multiple APN profiles for subscriber data
[ Harald Welte ] -- Oliver Smith <osmith@sysmocom.de> Thu, 23 Feb 2023 10:23:04 +0100
* Introduce support for XOR-2G algorithm
* cosmetic: gen_ts_55_205_test_sets/func_template.c: Use tab-indent
* cosmetic: gen_ts_55_205_test_sets/main_template tabs istead of spaces
* Port to new libosmogsm 'struct osmo_sub_auth_data2'
* src/db.c: Switch from "const char *statements" to "const char * const"
* db: extend database schema to support 256bit K and/or OP[c] values
* Add VTY support for TUAK algorithm
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 12 Sep 2023 14:41:33 +0200
osmo-hlr (1.6.0) unstable; urgency=medium osmo-hlr (1.6.0) unstable; urgency=medium

2
debian/compat vendored
View File

@@ -1 +1 @@
10 9

10
debian/control vendored
View File

@@ -2,17 +2,17 @@ Source: osmo-hlr
Section: net Section: net
Priority: optional Priority: optional
Maintainer: Osmocom team <openbsc@lists.osmocom.org> Maintainer: Osmocom team <openbsc@lists.osmocom.org>
Build-Depends: debhelper (>= 10), Build-Depends: debhelper (>= 9),
pkg-config, pkg-config,
dh-autoreconf, dh-autoreconf,
autotools-dev, autotools-dev,
python3-minimal, python3-minimal,
libosmocore-dev (>= 1.11.0), libosmocore-dev (>= 1.8.0),
libosmo-abis-dev (>= 2.0.0), libosmo-abis-dev (>= 1.4.0),
libosmo-netif-dev (>= 1.6.0), libosmo-netif-dev (>= 1.3.0),
libsqlite3-dev, libsqlite3-dev,
sqlite3, sqlite3,
osmo-gsm-manuals-dev (>= 1.6.0) osmo-gsm-manuals-dev (>= 1.4.0)
Standards-Version: 3.9.6 Standards-Version: 3.9.6
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr

18
debian/copyright vendored
View File

@@ -6,10 +6,6 @@ Files: *
Copyright: 2016-2022 Sysmocom s. f. m. c. GmbH <info@sysmocom.de> Copyright: 2016-2022 Sysmocom s. f. m. c. GmbH <info@sysmocom.de>
License: AGPL-3+ License: AGPL-3+
Files: src/gsupclient/*
Copyright: 2014-2016,2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
License: GPL-2+
License: AGPL-3+ License: AGPL-3+
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU Affero General Public License as published by
@@ -23,17 +19,3 @@ License: AGPL-3+
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
License: GPL-2+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

38
debian/postinst vendored
View File

@@ -3,41 +3,3 @@
# post-upgrade script in both cases, it won't do anything if there is nothing # post-upgrade script in both cases, it won't do anything if there is nothing
# to do. # to do.
/usr/share/osmocom/osmo-hlr-post-upgrade.sh /usr/share/osmocom/osmo-hlr-post-upgrade.sh
case "$1" in
configure)
# Create the osmocom group and user (if it doesn't exist yet)
if ! getent group osmocom >/dev/null; then
groupadd --system osmocom
fi
if ! getent passwd osmocom >/dev/null; then
useradd \
--system \
--gid osmocom \
--home-dir /var/lib/osmocom \
--shell /sbin/nologin \
--comment "Open Source Mobile Communications" \
osmocom
fi
# Fix permissions of previous (root-owned) install (OS#4107)
if dpkg --compare-versions "$2" le "1.8.0"; then
if [ -e /etc/osmocom/osmo-hlr.cfg ]; then
chown -v osmocom:osmocom /etc/osmocom/osmo-hlr.cfg
chmod -v 0660 /etc/osmocom/osmo-hlr.cfg
fi
if [ -d /etc/osmocom ]; then
chown -v root:osmocom /etc/osmocom
chmod -v 2775 /etc/osmocom
fi
mkdir -p /var/lib/osmocom
chown -R -v osmocom:osmocom /var/lib/osmocom
fi
;;
esac
# dh_installdeb(1) will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#

View File

@@ -1,12 +1,4 @@
# OsmoHLR example configuration for Distributed GSM (mslookup) # OsmoHLR example configuration for Distributed GSM (mslookup)
log stderr
logging color 1
logging print category-hex 0
logging print category 1
logging timestamp 0
logging print file basename last
logging print level 1
hlr hlr
gsup gsup
# For D-GSM roaming, osmo-hlr's GSUP must listen on a public IP: # For D-GSM roaming, osmo-hlr's GSUP must listen on a public IP:

View File

@@ -4,11 +4,11 @@
log stderr log stderr
logging filter all 1 logging filter all 1
logging color 1 logging color 1
logging print category-hex 0
logging print category 1 logging print category 1
logging timestamp 0 logging print category-hex 0
logging print file basename last
logging print level 1 logging print level 1
logging print file basename last
logging print extended-timestamp 1
logging level main notice logging level main notice
logging level db notice logging level db notice
logging level auc notice logging level auc notice
@@ -24,9 +24,3 @@ hlr
bind ip 127.0.0.1 bind ip 127.0.0.1
ussd route prefix *#100# internal own-msisdn ussd route prefix *#100# internal own-msisdn
ussd route prefix *#101# internal own-imsi ussd route prefix *#101# internal own-imsi
ps
pdp-profiles default
profile 1
apn internet
profile 2
apn *

View File

@@ -1,25 +1,13 @@
SUBDIRS = osmocom SUBDIRS = osmocom
osmocom/%/version.h: osmocom/%/version.h.tpl
$(AM_V_GEN)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)sed \
-e "s/{{VERSION}}/$$(echo '@VERSION@' | cut -d. -f1-3)/g" \
-e "s/{{VERSION_MAJOR}}/$$(echo '@VERSION@' | cut -d. -f1)/g" \
-e "s/{{VERSION_MINOR}}/$$(echo '@VERSION@' | cut -d. -f2)/g" \
-e "s/{{VERSION_PATCH}}/$$(echo '@VERSION@' | cut -d. -f3)/g" \
$< > $@
nobase_include_HEADERS = \ nobase_include_HEADERS = \
osmocom/gsupclient/cni_peer_id.h \ osmocom/gsupclient/cni_peer_id.h \
osmocom/gsupclient/gsup_client.h \ osmocom/gsupclient/gsup_client.h \
osmocom/gsupclient/gsup_client_mux.h \
osmocom/gsupclient/gsup_req.h \ osmocom/gsupclient/gsup_req.h \
osmocom/gsupclient/version.h \
osmocom/mslookup/mdns.h \ osmocom/mslookup/mdns.h \
osmocom/mslookup/mdns_sock.h \ osmocom/mslookup/mdns_sock.h \
osmocom/mslookup/mslookup_client_fake.h \ osmocom/mslookup/mslookup_client_fake.h \
osmocom/mslookup/mslookup_client.h \ osmocom/mslookup/mslookup_client.h \
osmocom/mslookup/mslookup_client_mdns.h \ osmocom/mslookup/mslookup_client_mdns.h \
osmocom/mslookup/mslookup.h \ osmocom/mslookup/mslookup.h \
osmocom/mslookup/version.h \
$(NULL) $(NULL)

View File

@@ -20,9 +20,6 @@
*/ */
#pragma once #pragma once
#include <stdint.h>
#include <stdbool.h>
#include <osmocom/core/timer.h> #include <osmocom/core/timer.h>
#include <osmocom/gsm/oap_client.h> #include <osmocom/gsm/oap_client.h>
#include <osmocom/gsm/ipa.h> #include <osmocom/gsm/ipa.h>
@@ -43,7 +40,6 @@ typedef int (*osmo_gsup_client_read_cb_t)(struct osmo_gsup_client *gsupc, struct
typedef bool (*osmo_gsup_client_up_down_cb_t)(struct osmo_gsup_client *gsupc, bool up); typedef bool (*osmo_gsup_client_up_down_cb_t)(struct osmo_gsup_client *gsupc, bool up);
/* NOTE: THIS STRUCT IS CONSIDERED PRIVATE, AVOID ACCESSING ITS FIELDS! */
struct osmo_gsup_client { struct osmo_gsup_client {
const char *unit_name; /* same as ipa_dev->unit_name, for backwards compat */ const char *unit_name; /* same as ipa_dev->unit_name, for backwards compat */
@@ -103,12 +99,3 @@ int osmo_gsup_client_enc_send(struct osmo_gsup_client *gsupc,
const struct osmo_gsup_message *gsup_msg); const struct osmo_gsup_message *gsup_msg);
struct msgb *osmo_gsup_client_msgb_alloc(void); struct msgb *osmo_gsup_client_msgb_alloc(void);
void *osmo_gsup_client_get_data(const struct osmo_gsup_client *gsupc);
void osmo_gsup_client_set_data(struct osmo_gsup_client *gsupc, void *data);
const char *osmo_gsup_client_get_rem_addr(const struct osmo_gsup_client *gsupc);
uint16_t osmo_gsup_client_get_rem_port(const struct osmo_gsup_client *gsupc);
bool osmo_gsup_client_is_connected(const struct osmo_gsup_client *gsupc);
const struct ipaccess_unit *osmo_gsup_client_get_ipaccess_unit(const struct osmo_gsup_client *gsupc);

View File

@@ -1,56 +0,0 @@
/*
* (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* Author: Neels Hofmeyr
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <osmocom/gsm/gsup.h>
struct gsup_client_mux;
struct ipaccess_unit;
struct gsup_client_mux_rx_cb {
int (*func)(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_message *gsup_msg);
void *data;
};
/* A GSUP client shared between code paths for various GSUP Message Classes.
* The main task is to dispatch GSUP messages to code paths corresponding to the respective Message Class, i.e.
* subscriber management, SMS, SS/USSD and inter-MSC messaging.
* If a GSUP Message Class IE is present in the message, the received message is dispatched directly to the rx_cb entry
* for that Message Class. Otherwise, the Message Class is determined by a switch() on the Message Type.*/
struct gsup_client_mux {
struct osmo_gsup_client *gsup_client;
/* Target clients by enum osmo_gsup_message_class */
struct gsup_client_mux_rx_cb rx_cb[OSMO_GSUP_MESSAGE_CLASS_ARRAYSIZE];
};
struct gsup_client_mux *gsup_client_mux_alloc(void *talloc_ctx);
int gsup_client_mux_start(struct gsup_client_mux *gcm, const char *gsup_server_addr_str, uint16_t gsup_server_port,
struct ipaccess_unit *ipa_dev);
int gsup_client_mux_tx(struct gsup_client_mux *gcm, const struct osmo_gsup_message *gsup_msg);
void gsup_client_mux_tx_set_source(const struct gsup_client_mux *gcm, struct osmo_gsup_message *gsup_msg);
void gsup_client_mux_tx_error_reply(struct gsup_client_mux *gcm, const struct osmo_gsup_message *gsup_orig,
enum gsm48_gmm_cause cause);
int gsup_client_mux_rx(struct osmo_gsup_client *gsup_client, struct msgb *msg);

View File

@@ -1,16 +0,0 @@
#pragma once
#define LIBOSMO_GSUP_CLIENT_VERSION {{VERSION}}
#define LIBOSMO_GSUP_CLIENT_VERSION_STR "{{VERSION}}"
#define LIBOSMO_GSUP_CLIENT_VERSION_MAJOR {{VERSION_MAJOR}}
#define LIBOSMO_GSUP_CLIENT_VERSION_MINOR {{VERSION_MINOR}}
#define LIBOSMO_GSUP_CLIENT_VERSION_PATCH {{VERSION_PATCH}}
#define LIBOSMO_GSUP_CLIENT_VERSION_GREATER_EQUAL(major, minor, patch) \
(LIBOSMO_GSUP_CLIENT_VERSION_MAJOR > (major) || \
(LIBOSMO_GSUP_CLIENT_VERSION_MAJOR == (major) && \
LIBOSMO_GSUP_CLIENT_VERSION_MINOR > (minor)) || \
(LIBOSMO_GSUP_CLIENT_VERSION_MAJOR == (major) && \
LIBOSMO_GSUP_CLIENT_VERSION_MINOR == (minor) && \
LIBOSMO_GSUP_CLIENT_VERSION_PATCH >= (patch)))

View File

@@ -6,7 +6,6 @@ noinst_HEADERS = \
gsup_router.h \ gsup_router.h \
gsup_server.h \ gsup_server.h \
hlr.h \ hlr.h \
hlr_sms.h \
hlr_ussd.h \ hlr_ussd.h \
hlr_vty.h \ hlr_vty.h \
hlr_vty_subscr.h \ hlr_vty_subscr.h \

View File

@@ -3,6 +3,6 @@
#include <osmocom/crypt/auth.h> #include <osmocom/crypt/auth.h>
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec, int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
struct osmo_sub_auth_data2 *aud2g, struct osmo_sub_auth_data *aud2g,
struct osmo_sub_auth_data2 *aud3g, struct osmo_sub_auth_data *aud3g,
const uint8_t *rand_auts, const uint8_t *auts); const uint8_t *rand_auts, const uint8_t *auts);

View File

@@ -40,8 +40,6 @@ enum stmt_idx {
DB_STMT_SET_LAST_LU_SEEN, DB_STMT_SET_LAST_LU_SEEN,
DB_STMT_SET_LAST_LU_SEEN_PS, DB_STMT_SET_LAST_LU_SEEN_PS,
DB_STMT_EXISTS_BY_IMSI, DB_STMT_EXISTS_BY_IMSI,
DB_STMT_EXISTS_AUTHORIZED_BY_IMSI,
DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI,
DB_STMT_EXISTS_BY_MSISDN, DB_STMT_EXISTS_BY_MSISDN,
DB_STMT_IND_ADD, DB_STMT_IND_ADD,
DB_STMT_IND_SELECT, DB_STMT_IND_SELECT,
@@ -72,8 +70,8 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite3_log
/* obtain the authentication data for a given imsi */ /* obtain the authentication data for a given imsi */
int db_get_auth_data(struct db_context *dbc, const char *imsi, int db_get_auth_data(struct db_context *dbc, const char *imsi,
struct osmo_sub_auth_data2 *aud2g, struct osmo_sub_auth_data *aud2g,
struct osmo_sub_auth_data2 *aud3g, struct osmo_sub_auth_data *aud3g,
int64_t *subscr_id); int64_t *subscr_id);
int db_update_sqn(struct db_context *dbc, int64_t id, int db_update_sqn(struct db_context *dbc, int64_t id,
@@ -123,7 +121,7 @@ struct hlr_subscriber {
* See https://sqlite.org/lang_datefunc.html, function datetime(). */ * See https://sqlite.org/lang_datefunc.html, function datetime(). */
#define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S" #define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S"
/* Like struct osmo_sub_auth_data2, but the keys are in hexdump representation. /* Like struct osmo_sub_auth_data, but the keys are in hexdump representation.
* This is useful because SQLite requires them in hexdump format, and callers * This is useful because SQLite requires them in hexdump format, and callers
* like the VTY and CTRL interface also have them available as hexdump to begin * like the VTY and CTRL interface also have them available as hexdump to begin
* with. In the binary format, a VTY command would first need to hexparse, * with. In the binary format, a VTY command would first need to hexparse,
@@ -159,8 +157,6 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
int db_subscr_update_imei_by_imsi(struct db_context *dbc, const char* imsi, const char *imei); int db_subscr_update_imei_by_imsi(struct db_context *dbc, const char* imsi, const char *imei);
int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi); int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi);
int db_subscr_authorized_by_imsi(struct db_context *dbc, const char *imsi);
int db_subscr_is_created_on_demand_by_imsi(struct db_context *dbc, const char *imsi, unsigned int msisdn_len);
int db_subscr_exists_by_msisdn(struct db_context *dbc, const char *msisdn); int db_subscr_exists_by_msisdn(struct db_context *dbc, const char *msisdn);
int db_subscrs_get(struct db_context *dbc, const char *filter_type, const char *filter, int db_subscrs_get(struct db_context *dbc, const char *filter_type, const char *filter,

View File

@@ -25,7 +25,6 @@
#include <osmocom/gsupclient/cni_peer_id.h> #include <osmocom/gsupclient/cni_peer_id.h>
#include <osmocom/gsupclient/gsup_req.h> #include <osmocom/gsupclient/gsup_req.h>
#define OSMO_DGSM_DEFAULT_LOCAL_ATTACH_MAX_AGE 60 * 60
#define OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS 2000 #define OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS 2000
#define LOG_DGSM(imsi, level, fmt, args...) \ #define LOG_DGSM(imsi, level, fmt, args...) \
LOGP(DDGSM, level, "(IMSI-%s) " fmt, imsi, ##args) LOGP(DDGSM, level, "(IMSI-%s) " fmt, imsi, ##args)

View File

@@ -2,9 +2,9 @@
#include <osmocom/core/linuxlist.h> #include <osmocom/core/linuxlist.h>
#include <osmocom/core/msgb.h> #include <osmocom/core/msgb.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/gsm/protocol/ipaccess.h>
#include <osmocom/abis/ipa.h> #include <osmocom/abis/ipa.h>
#include <osmocom/abis/ipaccess.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/gsupclient/cni_peer_id.h> #include <osmocom/gsupclient/cni_peer_id.h>
#include <osmocom/gsupclient/gsup_req.h> #include <osmocom/gsupclient/gsup_req.h>
@@ -69,6 +69,8 @@ void osmo_gsup_server_destroy(struct osmo_gsup_server *gsups);
int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup, int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup,
uint8_t *apn_buf, size_t apn_buf_size); uint8_t *apn_buf, size_t apn_buf_size);
int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn, int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
enum osmo_gsup_cn_domain cn_domain, void *talloc_ctx); uint8_t *msisdn_enc, size_t msisdn_enc_size,
uint8_t *apn_buf, size_t apn_buf_size,
enum osmo_gsup_cn_domain cn_domain);
int osmo_gsup_forward_to_local_peer(struct osmo_gsup_server *server, const struct osmo_cni_peer_id *to_peer, int osmo_gsup_forward_to_local_peer(struct osmo_gsup_server *server, const struct osmo_cni_peer_id *to_peer,
struct osmo_gsup_req *req, struct osmo_gsup_message *modified_gsup); struct osmo_gsup_req *req, struct osmo_gsup_message *modified_gsup);

View File

@@ -39,13 +39,6 @@ enum osmo_gsup_message_type;
extern struct osmo_tdef g_hlr_tdefs[]; extern struct osmo_tdef g_hlr_tdefs[];
enum subscr_create_on_demand_mode {
SUBSCR_COD_MODE_DISABLED = 0,
SUBSCR_COD_MODE_NO_MSISDN,
SUBSCR_COD_MODE_RAND_MSISDN,
SUBSCR_COD_MODE_MSISDN_FROM_IMSI,
};
struct hlr { struct hlr {
/* GSUP server pointer */ /* GSUP server pointer */
struct osmo_gsup_server *gs; struct osmo_gsup_server *gs;
@@ -63,24 +56,8 @@ struct hlr {
struct llist_head euse_list; struct llist_head euse_list;
struct hlr_euse *euse_default; struct hlr_euse *euse_default;
enum gsm48_gmm_cause reject_cause;
struct { enum gsm48_gmm_cause no_proxy_reject_cause;
enum gsm48_gmm_cause cs;
enum gsm48_gmm_cause ps;
} reject_cause;
struct {
enum gsm48_gmm_cause cs;
enum gsm48_gmm_cause ps;
} no_proxy_reject_cause;
/* PS: APN default configuration used by Subscription Data on ISR */
struct {
struct {
bool enabled;
struct osmo_gsup_pdp_info pdp_infos[OSMO_GSUP_MAX_NUM_PDP_INFO];
size_t num_pdp_infos;
} pdp_profile;
} ps;
/* NCSS (call independent) session guard timeout value */ /* NCSS (call independent) session guard timeout value */
int ncss_guard_timeout; int ncss_guard_timeout;
@@ -89,18 +66,12 @@ struct hlr {
struct llist_head ss_sessions; struct llist_head ss_sessions;
struct llist_head smsc_list;
struct llist_head smsc_routes;
struct hlr_smsc *smsc_default;
bool store_imei; bool store_imei;
struct { bool subscr_create_on_demand;
enum subscr_create_on_demand_mode mode;
unsigned int rand_msisdn_len;
/* Bitmask of DB_SUBSCR_FLAG_* */ /* Bitmask of DB_SUBSCR_FLAG_* */
uint8_t flags; uint8_t subscr_create_on_demand_flags;
} subscr_create_on_demand; unsigned int subscr_create_on_demand_rand_msisdn_len;
struct { struct {
bool allow_startup; bool allow_startup;
@@ -140,10 +111,7 @@ struct hlr {
char *domain_suffix; char *domain_suffix;
struct osmo_mslookup_client_method *running; struct osmo_mslookup_client_method *running;
} mdns; } mdns;
bool subscr_create_on_demand_fallback;
} client; } client;
bool auth_imsi_only;
bool ignore_created_on_demand;
} mslookup; } mslookup;
}; };
@@ -153,4 +121,3 @@ struct hlr_subscriber;
void osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr); void osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr);
int hlr_subscr_nam(struct hlr *hlr, struct hlr_subscriber *subscr, bool nam_val, bool is_ps); int hlr_subscr_nam(struct hlr *hlr, struct hlr_subscriber *subscr, bool nam_val, bool is_ps);
void dgsm_fallback_to_hlr();

View File

@@ -1,33 +0,0 @@
#pragma once
#include <osmocom/core/linuxlist.h>
struct hlr_smsc {
/* g_hlr->smsc_list */
struct llist_head list;
struct hlr *hlr;
/* name (must match the IPA ID tag) */
const char *name;
/* human-readable description */
const char *description;
};
struct hlr_smsc *smsc_find(struct hlr *hlr, const char *name);
struct hlr_smsc *smsc_alloc(struct hlr *hlr, const char *name);
void smsc_free(struct hlr_smsc *smsc);
struct hlr_smsc_route {
/* g_hlr->smsc_routes */
struct llist_head list;
const char *num_addr;
struct hlr_smsc *smsc;
};
struct hlr_smsc_route *smsc_route_find(struct hlr *hlr, const char *num_addr);
struct hlr_smsc_route *smsc_route_alloc(struct hlr *hlr, const char *num_addr,
struct hlr_smsc *smsc);
void smsc_route_free(struct hlr_smsc_route *rt);
void forward_mo_sms(struct osmo_gsup_req *req);
void forward_mt_sms(struct osmo_gsup_req *req);
void rx_ready_for_sm_req(struct osmo_gsup_req *req);

View File

@@ -31,23 +31,19 @@ enum hlr_vty_node {
HLR_NODE = _LAST_OSMOVTY_NODE + 1, HLR_NODE = _LAST_OSMOVTY_NODE + 1,
GSUP_NODE, GSUP_NODE,
EUSE_NODE, EUSE_NODE,
SMSC_NODE,
MSLOOKUP_NODE, MSLOOKUP_NODE,
MSLOOKUP_SERVER_NODE, MSLOOKUP_SERVER_NODE,
MSLOOKUP_SERVER_MSC_NODE, MSLOOKUP_SERVER_MSC_NODE,
MSLOOKUP_CLIENT_NODE, MSLOOKUP_CLIENT_NODE,
PS_NODE,
PS_PDP_PROFILES_NODE,
PS_PDP_PROFILES_PROFILE_NODE,
}; };
#define A38_XOR_MIN_KEY_LEN 12 #define A38_XOR_MIN_KEY_LEN 12
#define A38_XOR_MAX_KEY_LEN 16 #define A38_XOR_MAX_KEY_LEN 16
#define A38_XOR2G_KEY_LEN 16
#define A38_COMP128_KEY_LEN 16 #define A38_COMP128_KEY_LEN 16
#define MILENAGE_KEY_LEN 16 #define MILENAGE_KEY_LEN 16
int hlr_vty_is_config_node(struct vty *vty, int node);
int hlr_vty_go_parent(struct vty *vty); int hlr_vty_go_parent(struct vty *vty);
void hlr_vty_init(void *hlr_ctx); void hlr_vty_init(void *hlr_ctx);
void dgsm_vty_init(void); void dgsm_vty_init(void);

View File

@@ -71,8 +71,6 @@ void proxy_init(struct osmo_gsup_server *gsup_server_to_vlr);
void proxy_del(struct proxy *proxy); void proxy_del(struct proxy *proxy);
void proxy_set_gc_period(struct proxy *proxy, uint32_t gc_period); void proxy_set_gc_period(struct proxy *proxy, uint32_t gc_period);
struct osmo_gsup_req *proxy_deferred_gsup_req_get_by_imsi(struct proxy *proxy, const char *imsi);
/* The API to access / modify proxy entries keeps the implementation opaque, to make sure that we can easily move proxy /* The API to access / modify proxy entries keeps the implementation opaque, to make sure that we can easily move proxy
* storage to SQLite db. */ * storage to SQLite db. */
int proxy_subscr_get_by_imsi(struct proxy_subscr *dst, struct proxy *proxy, const char *imsi); int proxy_subscr_get_by_imsi(struct proxy_subscr *dst, struct proxy *proxy, const char *imsi);

View File

@@ -35,7 +35,6 @@ enum osmo_mslookup_id_type {
OSMO_MSLOOKUP_ID_NONE = 0, OSMO_MSLOOKUP_ID_NONE = 0,
OSMO_MSLOOKUP_ID_IMSI, OSMO_MSLOOKUP_ID_IMSI,
OSMO_MSLOOKUP_ID_MSISDN, OSMO_MSLOOKUP_ID_MSISDN,
OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED,
}; };
extern const struct value_string osmo_mslookup_id_type_names[]; extern const struct value_string osmo_mslookup_id_type_names[];

View File

@@ -37,8 +37,6 @@ typedef void (*osmo_mslookup_cb_t)(struct osmo_mslookup_client *client,
* This query handling info is not seen by the individual method implementations, to clarify that it is the * This query handling info is not seen by the individual method implementations, to clarify that it is the
* osmo_mslookup_client layer that takes care of these details. */ * osmo_mslookup_client layer that takes care of these details. */
struct osmo_mslookup_query_handling { struct osmo_mslookup_query_handling {
bool search_all;
/*! Wait at least this long before returning any results. /*! Wait at least this long before returning any results.
* *
* If nonzero, result_cb will be called as soon as this delay has elapsed, either with the so far youngest age * If nonzero, result_cb will be called as soon as this delay has elapsed, either with the so far youngest age

View File

@@ -1,16 +0,0 @@
#pragma once
#define LIBOSMO_MSLOOKUP_VERSION {{VERSION}}
#define LIBOSMO_MSLOOKUP_VERSION_STR "{{VERSION}}"
#define LIBOSMO_MSLOOKUP_VERSION_MAJOR {{VERSION_MAJOR}}
#define LIBOSMO_MSLOOKUP_VERSION_MINOR {{VERSION_MINOR}}
#define LIBOSMO_MSLOOKUP_VERSION_PATCH {{VERSION_PATCH}}
#define LIBOSMO_MSLOOKUP_VERSION_GREATER_EQUAL(major, minor, patch) \
(LIBOSMO_MSLOOKUP_VERSION_MAJOR > (major) || \
(LIBOSMO_MSLOOKUP_VERSION_MAJOR == (major) && \
LIBOSMO_MSLOOKUP_VERSION_MINOR > (minor)) || \
(LIBOSMO_MSLOOKUP_VERSION_MAJOR == (major) && \
LIBOSMO_MSLOOKUP_VERSION_MINOR == (minor) && \
LIBOSMO_MSLOOKUP_VERSION_PATCH >= (patch)))

View File

@@ -71,9 +71,9 @@ CREATE TABLE auc_2g (
CREATE TABLE auc_3g ( CREATE TABLE auc_3g (
subscriber_id INTEGER PRIMARY KEY, -- subscriber.id subscriber_id INTEGER PRIMARY KEY, -- subscriber.id
algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value
k VARCHAR(64) NOT NULL, -- hex string: subscriber's secret key (128/256bit) k VARCHAR(32) NOT NULL, -- hex string: subscriber's secret key (128bit)
op VARCHAR(64), -- hex string: operator's secret key (128/256bit) op VARCHAR(32), -- hex string: operator's secret key (128bit)
opc VARCHAR(64), -- hex string: derived from OP and K (128/256bit) opc VARCHAR(32), -- hex string: derived from OP and K (128bit)
sqn INTEGER NOT NULL DEFAULT 0, -- sequence number of key usage sqn INTEGER NOT NULL DEFAULT 0, -- sequence number of key usage
-- nr of index bits at lower SQN end -- nr of index bits at lower SQN end
ind_bitlen INTEGER NOT NULL DEFAULT 5 ind_bitlen INTEGER NOT NULL DEFAULT 5
@@ -91,4 +91,4 @@ CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi);
-- Set HLR database schema version number -- Set HLR database schema version number
-- Note: This constant is currently duplicated in src/db.c and must be kept in sync! -- Note: This constant is currently duplicated in src/db.c and must be kept in sync!
PRAGMA user_version = 7; PRAGMA user_version = 6;

View File

@@ -52,7 +52,6 @@ osmo_hlr_SOURCES = \
hlr_vty.c \ hlr_vty.c \
hlr_vty_subscr.c \ hlr_vty_subscr.c \
gsup_send.c \ gsup_send.c \
hlr_sms.c \
hlr_ussd.c \ hlr_ussd.c \
proxy.c \ proxy.c \
dgsm.c \ dgsm.c \
@@ -112,7 +111,7 @@ BOOTSTRAP_SQL = $(top_srcdir)/sql/hlr.sql
db_bootstrap.h: $(BOOTSTRAP_SQL) $(srcdir)/db_sql2c.sed db_bootstrap.h: $(BOOTSTRAP_SQL) $(srcdir)/db_sql2c.sed
echo "/* DO NOT EDIT THIS FILE. It is generated from files in osmo-hlr.git/sql/ */" > "$@" echo "/* DO NOT EDIT THIS FILE. It is generated from files in osmo-hlr.git/sql/ */" > "$@"
echo "#pragma once" >> "$@" echo "#pragma once" >> "$@"
echo "static const char * const stmt_bootstrap_sql[] = {" >> "$@" echo "static const char *stmt_bootstrap_sql[] = {" >> "$@"
cat "$(BOOTSTRAP_SQL)" \ cat "$(BOOTSTRAP_SQL)" \
| sed -f "$(srcdir)/db_sql2c.sed" \ | sed -f "$(srcdir)/db_sql2c.sed" \
>> "$@" >> "$@"

View File

@@ -1,4 +1,4 @@
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org> /* (C) 2015 by Harald Welte <laforge@gnumonks.org>
* *
* All Rights Reserved * All Rights Reserved
* *
@@ -32,8 +32,8 @@
/* compute given number of vectors using either aud2g or aud2g or a combination /* compute given number of vectors using either aud2g or aud2g or a combination
* of both. Handles re-synchronization if rand_auts and auts are set */ * of both. Handles re-synchronization if rand_auts and auts are set */
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec, int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
struct osmo_sub_auth_data2 *aud2g, struct osmo_sub_auth_data *aud2g,
struct osmo_sub_auth_data2 *aud3g, struct osmo_sub_auth_data *aud3g,
const uint8_t *rand_auts, const uint8_t *auts) const uint8_t *rand_auts, const uint8_t *auts)
{ {
unsigned int i; unsigned int i;
@@ -93,10 +93,10 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
: "2G only", : "2G only",
auts? ", with AUTS resync" : ""); auts? ", with AUTS resync" : "");
if (aud3g) { if (aud3g) {
DBGP("3G: k = %s\n", hex(aud3g->u.umts.k, aud3g->u.umts.k_len)); DBGP("3G: k = %s\n", hexb(aud3g->u.umts.k));
DBGP("3G: %s = %s\n", DBGP("3G: %s = %s\n",
aud3g->u.umts.opc_is_op? "OP" : "opc", aud3g->u.umts.opc_is_op? "OP" : "opc",
hex(aud3g->u.umts.opc, aud3g->u.umts.opc_len)); hexb(aud3g->u.umts.opc));
DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n", DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n",
aud3g->u.umts.ind, aud3g->u.umts.sqn); aud3g->u.umts.ind, aud3g->u.umts.sqn);
} }
@@ -115,9 +115,6 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
if (aud3g) { if (aud3g) {
/* 3G or 3G + 2G case */ /* 3G or 3G + 2G case */
/* backwards-compatibiliy: We assume all RES are 8 bytes long */
vec[i].res_len = 8;
/* Do AUTS only for the first vector or we would use /* Do AUTS only for the first vector or we would use
* the same SQN for each following key. */ * the same SQN for each following key. */
if ((i == 0) && auts) { if ((i == 0) && auts) {
@@ -126,10 +123,10 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
DBGP("vector [%u]: resync: rand_auts = %s\n", DBGP("vector [%u]: resync: rand_auts = %s\n",
i, hex(rand_auts, 16)); i, hex(rand_auts, 16));
rc = osmo_auth_gen_vec_auts2(vec+i, aud3g, auts, rc = osmo_auth_gen_vec_auts(vec+i, aud3g, auts,
rand_auts, rand); rand_auts, rand);
} else { } else {
rc = osmo_auth_gen_vec2(vec+i, aud3g, rand); rc = osmo_auth_gen_vec(vec+i, aud3g, rand);
} }
if (rc < 0) { if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 3G vector " LOGP(DAUC, LOGL_ERROR, "Error in 3G vector "
@@ -157,7 +154,7 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
DBGP("vector [%u]: calculating 2G separately\n", i); DBGP("vector [%u]: calculating 2G separately\n", i);
rc = osmo_auth_gen_vec2(&vtmp, aud2g, rand); rc = osmo_auth_gen_vec(&vtmp, aud2g, rand);
if (rc < 0) { if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector" LOGP(DAUC, LOGL_ERROR, "Error in 2G vector"
"generation: [%u]: rc = %d\n", i, rc); "generation: [%u]: rc = %d\n", i, rc);
@@ -168,7 +165,7 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
vec[i].auth_types |= OSMO_AUTH_TYPE_GSM; vec[i].auth_types |= OSMO_AUTH_TYPE_GSM;
} else { } else {
/* 2G only case */ /* 2G only case */
rc = osmo_auth_gen_vec2(vec+i, aud2g, rand); rc = osmo_auth_gen_vec(vec+i, aud2g, rand);
if (rc < 0) { if (rc < 0) {
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector " LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
"generation: [%u]: rc = %d\n", i, rc); "generation: [%u]: rc = %d\n", i, rc);

View File

@@ -1,6 +1,6 @@
/* OsmoHLR Control Interface implementation */ /* OsmoHLR Control Interface implementation */
/* (C) 2017-2023 sysmocom s.f.m.c. GmbH <info@sysmocom.de> /* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved * All Rights Reserved
* *
* Author: Max Suraev <msuraev@sysmocom.de> * Author: Max Suraev <msuraev@sysmocom.de>
@@ -39,7 +39,7 @@
#define SEL_BY_ID SEL_BY "id-" #define SEL_BY_ID SEL_BY "id-"
extern bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo, extern bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc); int *minlen, int *maxlen);
#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf)) #define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
@@ -166,7 +166,7 @@ static void print_subscr_info(struct ctrl_cmd *cmd,
); );
} }
static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *aud) static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
{ {
if (aud->algo == OSMO_AUTH_ALG_NONE) if (aud->algo == OSMO_AUTH_ALG_NONE)
return; return;
@@ -178,7 +178,7 @@ static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
hexdump_buf(aud->u.gsm.ki)); hexdump_buf(aud->u.gsm.ki));
} }
static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *aud) static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
{ {
if (aud->algo == OSMO_AUTH_ALG_NONE) if (aud->algo == OSMO_AUTH_ALG_NONE)
return; return;
@@ -187,7 +187,7 @@ static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
"\naud3g.k\t%s" "\naud3g.k\t%s"
, ,
osmo_auth_alg_name(aud->algo), osmo_auth_alg_name(aud->algo),
osmo_hexdump_nospc(aud->u.umts.k, aud->u.umts.k_len)); hexdump_buf(aud->u.umts.k));
/* hexdump uses a static string buffer, hence only one hexdump per /* hexdump uses a static string buffer, hence only one hexdump per
* printf(). */ * printf(). */
ctrl_cmd_reply_printf(cmd, ctrl_cmd_reply_printf(cmd,
@@ -196,7 +196,7 @@ static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
"\naud3g.sqn\t%" PRIu64 "\naud3g.sqn\t%" PRIu64
, ,
aud->u.umts.opc_is_op? "op" : "opc", aud->u.umts.opc_is_op? "op" : "opc",
osmo_hexdump_nospc(aud->u.umts.opc, aud->u.umts.opc_len), hexdump_buf(aud->u.umts.opc),
aud->u.umts.ind_bitlen, aud->u.umts.ind_bitlen,
aud->u.umts.sqn); aud->u.umts.sqn);
} }
@@ -291,8 +291,8 @@ CTRL_CMD_DEFINE_RO(subscr_info_aud, "info-aud");
static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data) static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
{ {
const char *imsi; const char *imsi;
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
int rc; int rc;
@@ -327,8 +327,8 @@ CTRL_CMD_DEFINE_RO(subscr_info_all, "info-all");
static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data) static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data)
{ {
struct hlr_subscriber subscr; struct hlr_subscriber subscr;
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
int rc; int rc;
@@ -426,20 +426,6 @@ static int set_subscr_cs_enabled(struct ctrl_cmd *cmd, void *data)
return set_subscr_cs_ps_enabled(cmd, data, false); return set_subscr_cs_ps_enabled(cmd, data, false);
} }
CTRL_CMD_DEFINE_RO(subscr_imsi, "imsi");
static int get_subscr_imsi(struct ctrl_cmd *cmd, void *data)
{
struct hlr_subscriber subscr;
struct hlr *hlr = data;
const char *by_selector = cmd->node;
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
return CTRL_CMD_ERROR;
cmd->reply = talloc_strdup(cmd, subscr.imsi);
return CTRL_CMD_REPLY;
}
CTRL_CMD_DEFINE(subscr_msisdn, "msisdn"); CTRL_CMD_DEFINE(subscr_msisdn, "msisdn");
static int verify_subscr_msisdn(struct ctrl_cmd *cmd, const char *value, void *data) static int verify_subscr_msisdn(struct ctrl_cmd *cmd, const char *value, void *data)
{ {
@@ -506,8 +492,8 @@ static int get_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
struct hlr_subscriber subscr; struct hlr_subscriber subscr;
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g_unused; struct osmo_sub_auth_data aud3g_unused;
int rc; int rc;
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd)) if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
@@ -564,7 +550,7 @@ static int set_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
} }
if (strcmp(tok, "none") == 0) { if (strcmp(tok, "none") == 0) {
aud2g.algo = OSMO_AUTH_ALG_NONE; aud2g.algo = OSMO_AUTH_ALG_NONE;
} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) { } else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen)) {
cmd->reply = "Unknown auth algorithm."; cmd->reply = "Unknown auth algorithm.";
return CTRL_CMD_ERROR; return CTRL_CMD_ERROR;
} }
@@ -606,8 +592,8 @@ static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
struct hlr_subscriber subscr; struct hlr_subscriber subscr;
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
struct osmo_sub_auth_data2 aud2g_unused; struct osmo_sub_auth_data aud2g_unused;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
int rc; int rc;
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd)) if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
@@ -632,9 +618,9 @@ static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
} }
cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", osmo_auth_alg_name(aud3g.algo), cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", osmo_auth_alg_name(aud3g.algo),
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, aud3g.u.umts.k_len), osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, sizeof(aud3g.u.umts.k)),
aud3g.u.umts.opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc_is_op ? "OP" : "OPC",
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, aud3g.u.umts.opc_len), osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc)),
aud3g.u.umts.ind_bitlen); aud3g.u.umts.ind_bitlen);
return CTRL_CMD_REPLY; return CTRL_CMD_REPLY;
} }
@@ -644,8 +630,8 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
struct hlr *hlr = data; struct hlr *hlr = data;
const char *by_selector = cmd->node; const char *by_selector = cmd->node;
char *tmp = NULL, *tok, *saveptr; char *tmp = NULL, *tok, *saveptr;
int minlen = 0, minlen_opc = 0; int minlen = 0;
int maxlen = 0, maxlen_opc = 0; int maxlen = 0;
struct sub_auth_data_str aud3g = { struct sub_auth_data_str aud3g = {
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.u.umts = { .u.umts = {
@@ -671,7 +657,7 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
} }
if (strcmp(tok, "none") == 0) { if (strcmp(tok, "none") == 0) {
aud3g.algo = OSMO_AUTH_ALG_NONE; aud3g.algo = OSMO_AUTH_ALG_NONE;
} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) { } else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen)) {
cmd->reply = "Unknown auth algorithm."; cmd->reply = "Unknown auth algorithm.";
return CTRL_CMD_ERROR; return CTRL_CMD_ERROR;
} }
@@ -713,7 +699,7 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
} }
aud3g.u.umts.opc = tok; aud3g.u.umts.opc = tok;
if (!osmo_is_hexstr(aud3g.u.umts.opc, minlen_opc * 2, maxlen_opc * 2, true)) { if (!osmo_is_hexstr(aud3g.u.umts.opc, MILENAGE_KEY_LEN * 2, MILENAGE_KEY_LEN * 2, true)) {
cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC."); cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC.");
return CTRL_CMD_ERROR; return CTRL_CMD_ERROR;
} }
@@ -775,7 +761,6 @@ static int hlr_ctrl_cmds_install(void)
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_all); rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_all);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_ps_enabled); rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_ps_enabled);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_cs_enabled); rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_cs_enabled);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_imsi);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_msisdn); rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_msisdn);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud2g); rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud2g);
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud3g); rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud3g);

View File

@@ -1,4 +1,4 @@
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org> /* (C) 2015 by Harald Welte <laforge@gnumonks.org>
* *
* All Rights Reserved * All Rights Reserved
* *
@@ -28,7 +28,7 @@
#include "db_bootstrap.h" #include "db_bootstrap.h"
/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */ /* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
#define CURRENT_SCHEMA_VERSION 7 #define CURRENT_SCHEMA_VERSION 6
#define SEL_COLUMNS \ #define SEL_COLUMNS \
"id," \ "id," \
@@ -53,7 +53,7 @@
static const char *stmt_sql[] = { static const char *stmt_sql[] = {
[DB_STMT_SEL_ALL] = "SELECT " SEL_COLUMNS " FROM subscriber;", [DB_STMT_SEL_ALL] = "SELECT " SEL_COLUMNS " FROM subscriber;",
[DB_STMT_SEL_ALL_ORDER_LAST_SEEN] = "SELECT " SEL_COLUMNS " FROM subscriber " [DB_STMT_SEL_ALL_ORDER_LAST_SEEN] = "SELECT " SEL_COLUMNS " FROM subscriber "
"WHERE last_lu_seen IS NOT NULL AND last_lu_seen > datetime('now','-1 month') ORDER BY last_lu_seen;", "WHERE last_lu_seen IS NOT NULL ORDER BY last_lu_seen;",
[DB_STMT_SEL_FILTER_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn LIKE $search ORDER BY msisdn", [DB_STMT_SEL_FILTER_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn LIKE $search ORDER BY msisdn",
[DB_STMT_SEL_FILTER_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi LIKE $search ORDER BY imsi", [DB_STMT_SEL_FILTER_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi LIKE $search ORDER BY imsi",
[DB_STMT_SEL_FILTER_IMEI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imei LIKE $search ORDER BY imei", [DB_STMT_SEL_FILTER_IMEI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imei LIKE $search ORDER BY imei",
@@ -92,10 +92,6 @@ static const char *stmt_sql[] = {
[DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch') WHERE id = $subscriber_id", [DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
[DB_STMT_SET_LAST_LU_SEEN_PS] = "UPDATE subscriber SET last_lu_seen_ps = datetime($val, 'unixepoch') WHERE id = $subscriber_id", [DB_STMT_SET_LAST_LU_SEEN_PS] = "UPDATE subscriber SET last_lu_seen_ps = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
[DB_STMT_EXISTS_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi", [DB_STMT_EXISTS_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi",
[DB_STMT_EXISTS_AUTHORIZED_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi AND (nam_cs = 1 OR nam_ps = 1)",
[DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI] =
"SELECT 1 FROM subscriber WHERE imsi = $imsi AND length(msisdn) = $msisdn_len"
" AND nam_cs = 0 AND nam_ps = 0 AND vlr_number IS NULL",
[DB_STMT_EXISTS_BY_MSISDN] = "SELECT 1 FROM subscriber WHERE msisdn = $msisdn", [DB_STMT_EXISTS_BY_MSISDN] = "SELECT 1 FROM subscriber WHERE msisdn = $msisdn",
[DB_STMT_IND_ADD] = "INSERT INTO ind (vlr) VALUES ($vlr)", [DB_STMT_IND_ADD] = "INSERT INTO ind (vlr) VALUES ($vlr)",
[DB_STMT_IND_SELECT] = "SELECT ind FROM ind WHERE vlr = $vlr", [DB_STMT_IND_SELECT] = "SELECT ind FROM ind WHERE vlr = $vlr",
@@ -239,7 +235,7 @@ void db_close(struct db_context *dbc)
talloc_free(dbc); talloc_free(dbc);
} }
static int db_run_statements(struct db_context *dbc, const char * const *statements, size_t statements_count) static int db_run_statements(struct db_context *dbc, const char **statements, size_t statements_count)
{ {
int rc = 0; int rc = 0;
int i; int i;
@@ -312,7 +308,7 @@ static int
db_upgrade_v1(struct db_context *dbc) db_upgrade_v1(struct db_context *dbc)
{ {
int rc; int rc;
const char * const statements[] = { const char *statements[] = {
"ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL", "ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL",
"PRAGMA user_version = 1", "PRAGMA user_version = 1",
}; };
@@ -328,7 +324,7 @@ db_upgrade_v1(struct db_context *dbc)
static int db_upgrade_v2(struct db_context *dbc) static int db_upgrade_v2(struct db_context *dbc)
{ {
int rc; int rc;
const char * const statements[] = { const char *statements[] = {
"ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14)", "ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14)",
"PRAGMA user_version = 2", "PRAGMA user_version = 2",
}; };
@@ -441,7 +437,7 @@ static int db_upgrade_v3(struct db_context *dbc)
"ms_purged_ps," \ "ms_purged_ps," \
"last_lu_seen" "last_lu_seen"
const char * const statements[] = { const char *statements[] = {
"BEGIN TRANSACTION", "BEGIN TRANSACTION",
"CREATE TEMPORARY TABLE subscriber_backup" SUBSCR_V3_CREATE, "CREATE TEMPORARY TABLE subscriber_backup" SUBSCR_V3_CREATE,
"INSERT INTO subscriber_backup SELECT " SUBSCR_V2_COLUMN_NAMES " FROM subscriber", "INSERT INTO subscriber_backup SELECT " SUBSCR_V2_COLUMN_NAMES " FROM subscriber",
@@ -464,7 +460,7 @@ static int db_upgrade_v3(struct db_context *dbc)
static int db_upgrade_v4(struct db_context *dbc) static int db_upgrade_v4(struct db_context *dbc)
{ {
int rc; int rc;
const char * const statements[] = { const char *statements[] = {
"ALTER TABLE subscriber ADD COLUMN last_lu_seen_ps TIMESTAMP default NULL", "ALTER TABLE subscriber ADD COLUMN last_lu_seen_ps TIMESTAMP default NULL",
"PRAGMA user_version = 4", "PRAGMA user_version = 4",
}; };
@@ -480,7 +476,7 @@ static int db_upgrade_v4(struct db_context *dbc)
static int db_upgrade_v5(struct db_context *dbc) static int db_upgrade_v5(struct db_context *dbc)
{ {
int rc; int rc;
const char * const statements[] = { const char *statements[] = {
"ALTER TABLE subscriber ADD COLUMN vlr_via_proxy VARCHAR", "ALTER TABLE subscriber ADD COLUMN vlr_via_proxy VARCHAR",
"ALTER TABLE subscriber ADD COLUMN sgsn_via_proxy VARCHAR", "ALTER TABLE subscriber ADD COLUMN sgsn_via_proxy VARCHAR",
"PRAGMA user_version = 5", "PRAGMA user_version = 5",
@@ -497,7 +493,7 @@ static int db_upgrade_v5(struct db_context *dbc)
static int db_upgrade_v6(struct db_context *dbc) static int db_upgrade_v6(struct db_context *dbc)
{ {
int rc; int rc;
const char * const statements[] = { const char *statements[] = {
"CREATE TABLE ind (\n" "CREATE TABLE ind (\n"
" -- 3G auth IND pool to be used for this VLR\n" " -- 3G auth IND pool to be used for this VLR\n"
" ind INTEGER PRIMARY KEY,\n" " ind INTEGER PRIMARY KEY,\n"
@@ -517,46 +513,6 @@ static int db_upgrade_v6(struct db_context *dbc)
return rc; return rc;
} }
static int db_upgrade_v7(struct db_context *dbc)
{
int rc;
/* SQLite doesn't allow us to change the column type in-place, so we
* first rename the old table, create a new table and then copy
* the data over before deleting the old table */
#define CREATE_AUC_3G_V7 \
"CREATE TABLE auc_3g (\n" \
" subscriber_id INTEGER PRIMARY KEY, -- subscriber.id\n" \
" algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value\n" \
" k VARCHAR(64) NOT NULL, -- hex string: subscriber's secret key (128/256bit)\n" \
" op VARCHAR(64), -- hex string: operator's secret key (128/256bit)\n" \
" opc VARCHAR(64), -- hex string: derived from OP and K (128/256bit)\n" \
" sqn INTEGER NOT NULL DEFAULT 0, -- sequence number of key usage\n" \
" -- nr of index bits at lower SQN end\n" \
" ind_bitlen INTEGER NOT NULL DEFAULT 5\n" \
");"
const char * const statements[] = {
"BEGIN TRANSACTION",
/* rename old table */
"ALTER TABLE auc_3g RENAME TO old_auc_3g",
/* create new table */
CREATE_AUC_3G_V7,
/* copy over old data */
"INSERT INTO auc_3g SELECT subscriber_id, algo_id_3g, k, op, opc,sqn, ind_bitlen FROM old_auc_3g",
/* delete old table */
"DROP TABLE old_auc_3g",
/* update user_version */
"PRAGMA user_version = 7",
"COMMIT",
};
rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
if (rc != SQLITE_DONE) {
LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 7\n");
return rc;
}
return rc;
}
typedef int (*db_upgrade_func_t)(struct db_context *dbc); typedef int (*db_upgrade_func_t)(struct db_context *dbc);
static db_upgrade_func_t db_upgrade_path[] = { static db_upgrade_func_t db_upgrade_path[] = {
db_upgrade_v1, db_upgrade_v1,
@@ -565,7 +521,6 @@ static db_upgrade_func_t db_upgrade_path[] = {
db_upgrade_v4, db_upgrade_v4,
db_upgrade_v5, db_upgrade_v5,
db_upgrade_v6, db_upgrade_v6,
db_upgrade_v7,
}; };
static int db_get_user_version(struct db_context *dbc) static int db_get_user_version(struct db_context *dbc)
@@ -599,7 +554,6 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logg
int rc; int rc;
bool has_sqlite_config_sqllog = false; bool has_sqlite_config_sqllog = false;
int version; int version;
bool version_changed = false;
LOGP(DDB, LOGL_NOTICE, "using database: %s\n", fname); LOGP(DDB, LOGL_NOTICE, "using database: %s\n", fname);
LOGP(DDB, LOGL_INFO, "Compiled against SQLite3 lib version %s\n", SQLITE_VERSION); LOGP(DDB, LOGL_INFO, "Compiled against SQLite3 lib version %s\n", SQLITE_VERSION);
@@ -677,7 +631,6 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logg
goto out_free; goto out_free;
} }
version = CURRENT_SCHEMA_VERSION; version = CURRENT_SCHEMA_VERSION;
version_changed = true;
} }
LOGP(DDB, LOGL_NOTICE, "Database '%s' has HLR DB schema version %d\n", dbc->fname, version); LOGP(DDB, LOGL_NOTICE, "Database '%s' has HLR DB schema version %d\n", dbc->fname, version);
@@ -692,7 +645,6 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logg
} }
LOGP(DDB, LOGL_NOTICE, "Database '%s' has been upgraded to HLR DB schema version %d\n", LOGP(DDB, LOGL_NOTICE, "Database '%s' has been upgraded to HLR DB schema version %d\n",
dbc->fname, version+1); dbc->fname, version+1);
version_changed = true;
} }
if (version != CURRENT_SCHEMA_VERSION) { if (version != CURRENT_SCHEMA_VERSION) {
@@ -709,12 +661,6 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logg
goto out_free; goto out_free;
} }
/* Flush the cache after changing the version, to make the scenario
* less likely that after an unclean shutdown the DB gets restored
* with the right table layout but wrong version (SYS#7394). */
if (version_changed)
sqlite3_db_cacheflush(dbc->db);
/* prepare all SQL statements */ /* prepare all SQL statements */
for (i = 0; i < ARRAY_SIZE(dbc->stmt); i++) { for (i = 0; i < ARRAY_SIZE(dbc->stmt); i++) {
rc = sqlite3_prepare_v2(dbc->db, stmt_sql[i], -1, rc = sqlite3_prepare_v2(dbc->db, stmt_sql[i], -1,

View File

@@ -1,4 +1,4 @@
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org> /* (C) 2015 by Harald Welte <laforge@gnumonks.org>
* *
* All Rights Reserved * All Rights Reserved
* *
@@ -74,9 +74,9 @@ out:
} }
/* hexparse a specific column of a sqlite prepared statement into dst (with length check) /* hexparse a specific column of a sqlite prepared statement into dst (with length check)
* returns byte length in case of success, -EIO on error */ * returns 0 for success, -EIO on error */
static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, sqlite3_stmt *stmt, static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int col, const char *col_name,
int col, const char *col_name, const char *imsi) const char *imsi)
{ {
const uint8_t *text; const uint8_t *text;
size_t col_len; size_t col_len;
@@ -84,15 +84,9 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, s
/* Bytes are stored as hex strings in database, hence divide length by two */ /* Bytes are stored as hex strings in database, hence divide length by two */
col_len = sqlite3_column_bytes(stmt, col) / 2; col_len = sqlite3_column_bytes(stmt, col) / 2;
if (col_len < dst_len_min) { if (col_len != dst_len) {
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected min length %lu but has length %lu\n", col_name, LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected length %lu but has length %lu\n", col_name,
dst_len_min, col_len); dst_len, col_len);
return -EIO;
}
if (col_len > dst_len_max) {
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected max length %lu but has length %lu\n", col_name,
dst_len_max, col_len);
return -EIO; return -EIO;
} }
@@ -102,10 +96,10 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, s
return -EIO; return -EIO;
} }
if (osmo_hexparse((void *)text, dst, dst_len_max) != col_len) if (osmo_hexparse((void *)text, dst, dst_len) != col_len)
return -EINVAL; return -EINVAL;
return col_len; return 0;
} }
/* obtain the authentication data for a given imsi /* obtain the authentication data for a given imsi
@@ -113,8 +107,8 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, s
* -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no auth data, * -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no auth data,
* -EIO on db failure */ * -EIO on db failure */
int db_get_auth_data(struct db_context *dbc, const char *imsi, int db_get_auth_data(struct db_context *dbc, const char *imsi,
struct osmo_sub_auth_data2 *aud2g, struct osmo_sub_auth_data *aud2g,
struct osmo_sub_auth_data2 *aud3g, struct osmo_sub_auth_data *aud3g,
int64_t *subscr_id) int64_t *subscr_id)
{ {
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI]; sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI];
@@ -148,8 +142,7 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
/* obtain result values using sqlite3_column_*() */ /* obtain result values using sqlite3_column_*() */
if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) { if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) {
/* we do have some 2G authentication data */ /* we do have some 2G authentication data */
if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), sizeof(aud2g->u.gsm.ki), if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), stmt, 2, "Ki", imsi))
stmt, 2, "Ki", imsi) < 0)
goto end_2g; goto end_2g;
aud2g->algo = sqlite3_column_int(stmt, 1); aud2g->algo = sqlite3_column_int(stmt, 1);
aud2g->type = OSMO_AUTH_TYPE_GSM; aud2g->type = OSMO_AUTH_TYPE_GSM;
@@ -158,30 +151,24 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
end_2g: end_2g:
if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) { if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
/* we do have some 3G authentication data */ /* we do have some 3G authentication data */
rc = hexparse_stmt(aud3g->u.umts.k, 16, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi); if (hexparse_stmt(aud3g->u.umts.k, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi)) {
if (rc < 0) {
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
aud3g->u.umts.k_len = rc;
aud3g->algo = sqlite3_column_int(stmt, 3); aud3g->algo = sqlite3_column_int(stmt, 3);
/* UMTS Subscribers can have either OP or OPC */ /* UMTS Subscribers can have either OP or OPC */
if (sqlite3_column_text(stmt, 5)) { if (sqlite3_column_text(stmt, 5)) {
rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi); if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi)) {
if (rc < 0) {
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
aud3g->u.umts.opc_len = rc;
aud3g->u.umts.opc_is_op = 1; aud3g->u.umts.opc_is_op = 1;
} else { } else {
rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi); if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi)) {
if (rc < 0) {
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
aud3g->u.umts.opc_len = rc;
aud3g->u.umts.opc_is_op = 0; aud3g->u.umts.opc_is_op = 0;
} }
aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7); aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7);
@@ -207,7 +194,7 @@ int db_get_auc(struct db_context *dbc, const char *imsi,
unsigned int num_vec, const uint8_t *rand_auts, unsigned int num_vec, const uint8_t *rand_auts,
const uint8_t *auts, bool separation_bit) const uint8_t *auts, bool separation_bit)
{ {
struct osmo_sub_auth_data2 aud2g, aud3g; struct osmo_sub_auth_data aud2g, aud3g;
int64_t subscr_id; int64_t subscr_id;
int ret = 0; int ret = 0;
int rc; int rc;

View File

@@ -1,4 +1,4 @@
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org> /* (C) 2015 by Harald Welte <laforge@gnumonks.org>
* *
* All Rights Reserved * All Rights Reserved
* *
@@ -238,9 +238,8 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
case OSMO_AUTH_ALG_COMP128v1: case OSMO_AUTH_ALG_COMP128v1:
case OSMO_AUTH_ALG_COMP128v2: case OSMO_AUTH_ALG_COMP128v2:
case OSMO_AUTH_ALG_COMP128v3: case OSMO_AUTH_ALG_COMP128v3:
case OSMO_AUTH_ALG_XOR_2G: case OSMO_AUTH_ALG_XOR:
break; break;
case OSMO_AUTH_ALG_XOR_3G:
case OSMO_AUTH_ALG_MILENAGE: case OSMO_AUTH_ALG_MILENAGE:
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:" LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
" auth algo not suited for 2G: %s\n", " auth algo not suited for 2G: %s\n",
@@ -268,12 +267,11 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
switch (aud->algo) { switch (aud->algo) {
case OSMO_AUTH_ALG_NONE: case OSMO_AUTH_ALG_NONE:
case OSMO_AUTH_ALG_MILENAGE: case OSMO_AUTH_ALG_MILENAGE:
case OSMO_AUTH_ALG_XOR_3G: case OSMO_AUTH_ALG_XOR:
break; break;
case OSMO_AUTH_ALG_COMP128v1: case OSMO_AUTH_ALG_COMP128v1:
case OSMO_AUTH_ALG_COMP128v2: case OSMO_AUTH_ALG_COMP128v2:
case OSMO_AUTH_ALG_COMP128v3: case OSMO_AUTH_ALG_COMP128v3:
case OSMO_AUTH_ALG_XOR_2G:
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:" LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
" auth algo not suited for 3G: %s\n", " auth algo not suited for 3G: %s\n",
osmo_auth_alg_name(aud->algo)); osmo_auth_alg_name(aud->algo));
@@ -286,12 +284,12 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
if (aud->algo == OSMO_AUTH_ALG_NONE) if (aud->algo == OSMO_AUTH_ALG_NONE)
break; break;
if (!osmo_is_hexstr(aud->u.umts.k, 32, 64, true)) { if (!osmo_is_hexstr(aud->u.umts.k, 32, 32, true)) {
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:" LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
" Invalid K: '%s'\n", aud->u.umts.k); " Invalid K: '%s'\n", aud->u.umts.k);
return -EINVAL; return -EINVAL;
} }
if (!osmo_is_hexstr(aud->u.umts.opc, 32, 64, true)) { if (!osmo_is_hexstr(aud->u.umts.opc, 32, 32, true)) {
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:" LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
" Invalid OP/OPC: '%s'\n", aud->u.umts.opc); " Invalid OP/OPC: '%s'\n", aud->u.umts.opc);
return -EINVAL; return -EINVAL;
@@ -555,59 +553,6 @@ int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi) {
return rc; return rc;
} }
/*! Check if a subscriber exists and has CS or PS service in the HLR database.
* \param[in, out] dbc database context.
* \param[in] imsi ASCII string of IMSI digits.
* \returns 0 if exists & authorized, -ENOENT if not, -EIO on database error.
*/
int db_subscr_authorized_by_imsi(struct db_context *dbc, const char *imsi) {
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_EXISTS_AUTHORIZED_BY_IMSI];
const char *err;
int rc;
if (!db_bind_text(stmt, NULL, imsi))
return -EIO;
rc = sqlite3_step(stmt);
db_remove_reset(stmt);
if (rc == SQLITE_ROW)
return 0; /* exists */
if (rc == SQLITE_DONE)
return -ENOENT; /* does not exist */
err = sqlite3_errmsg(dbc->db);
LOGP(DAUC, LOGL_ERROR, "Failed to check for authorized subscriber by IMSI='%s': %s\n", imsi, err);
return rc;
}
/*! Check if a subscriber exists and has ever been attached
* \param[in, out] dbc database context.
* \param[in] imsi ASCII string of IMSI digits.
* \returns 0 if has vlr_number, -ENOENT if not, -EIO on database error.
*/
int db_subscr_is_created_on_demand_by_imsi(struct db_context *dbc, const char *imsi, unsigned int msisdn_len) {
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_IS_CREATED_ON_DEMAND_BY_IMSI];
const char *err;
int rc;
if (!db_bind_text(stmt, "$imsi", imsi))
return -EIO;
if (!db_bind_int(stmt, "$msisdn_len", msisdn_len))
return -EIO;
rc = sqlite3_step(stmt);
db_remove_reset(stmt);
if (rc == SQLITE_ROW)
return 0; /* exists */
if (rc == SQLITE_DONE)
return -ENOENT; /* does not exist */
err = sqlite3_errmsg(dbc->db);
LOGP(DAUC, LOGL_ERROR, "Failed to check for on demand subscriber by IMSI='%s': %s\n", imsi, err);
return rc;
}
/*! Retrieve subscriber data from the HLR database. /*! Retrieve subscriber data from the HLR database.
* \param[in,out] dbc database context. * \param[in,out] dbc database context.
* \param[in] imsi ASCII string of IMSI digits. * \param[in] imsi ASCII string of IMSI digits.
@@ -753,12 +698,9 @@ int db_subscrs_get(struct db_context *dbc, const char *filter_type, const char *
copy_sqlite3_text_to_buf(subscr.imei, stmt, 3); copy_sqlite3_text_to_buf(subscr.imei, stmt, 3);
subscr.nam_cs = sqlite3_column_int(stmt, 9); subscr.nam_cs = sqlite3_column_int(stmt, 9);
subscr.nam_ps = sqlite3_column_int(stmt, 10); subscr.nam_ps = sqlite3_column_int(stmt, 10);
if (show_ls) { if (show_ls)
parse_last_lu_seen(&subscr.last_lu_seen, (const char *)sqlite3_column_text(stmt, 14), parse_last_lu_seen(&subscr.last_lu_seen, (const char *)sqlite3_column_text(stmt, 14),
subscr.imsi, "CS"); subscr.imsi, "CS");
copy_sqlite3_text_to_buf(subscr.vlr_number, stmt, 4);
}
get_cb(&subscr, data); get_cb(&subscr, data);
rc = sqlite3_step(stmt); rc = sqlite3_step(stmt);
(*count)++; (*count)++;

View File

@@ -58,12 +58,6 @@ static void resolve_hlr_result_cb(struct osmo_mslookup_client *client,
if (result->rc != OSMO_MSLOOKUP_RC_RESULT) { if (result->rc != OSMO_MSLOOKUP_RC_RESULT) {
LOG_DGSM(query->id.imsi, LOGL_ERROR, "Failed to resolve remote HLR: %s\n", LOG_DGSM(query->id.imsi, LOGL_ERROR, "Failed to resolve remote HLR: %s\n",
osmo_mslookup_result_name_c(OTC_SELECT, query, result)); osmo_mslookup_result_name_c(OTC_SELECT, query, result));
if (g_hlr->mslookup.client.subscr_create_on_demand_fallback &&
db_subscr_exists_by_imsi(g_hlr->dbc, query->id.imsi) != 0) {
struct osmo_gsup_req *req = proxy_deferred_gsup_req_get_by_imsi(proxy, query->id.imsi);
if (req && req->gsup.message_type == OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST)
dgsm_fallback_to_hlr(req);
}
proxy_subscr_del(proxy, query->id.imsi); proxy_subscr_del(proxy, query->id.imsi);
return; return;
} }
@@ -97,17 +91,8 @@ bool dgsm_check_forward_gsup_msg(struct osmo_gsup_req *req)
struct osmo_mslookup_query_handling handling; struct osmo_mslookup_query_handling handling;
uint32_t request_handle; uint32_t request_handle;
/* If the IMSI is authorized in the local HLR, then we won't proxy */ /* If the IMSI is known in the local HLR, then we won't proxy. */
if (db_subscr_authorized_by_imsi(g_hlr->dbc, req->gsup.imsi) == 0) if (db_subscr_exists_by_imsi(g_hlr->dbc, req->gsup.imsi) == 0)
return false;
/* unless configuration tells us to do otherwise. */
if (!g_hlr->mslookup.ignore_created_on_demand && !g_hlr->mslookup.auth_imsi_only &&
db_subscr_exists_by_imsi(g_hlr->dbc, req->gsup.imsi) == 0)
return false;
if (!g_hlr->mslookup.auth_imsi_only && !(g_hlr->mslookup.ignore_created_on_demand &&
db_subscr_is_created_on_demand_by_imsi(g_hlr->dbc, req->gsup.imsi,
g_hlr->subscr_create_on_demand.rand_msisdn_len) == 0))
return false; return false;
/* Are we already forwarding this IMSI to a remote HLR? */ /* Are we already forwarding this IMSI to a remote HLR? */
@@ -183,7 +168,7 @@ void dgsm_init(void *ctx)
dgsm_ctx = talloc_named_const(ctx, 0, "dgsm"); dgsm_ctx = talloc_named_const(ctx, 0, "dgsm");
INIT_LLIST_HEAD(&g_hlr->mslookup.server.local_site_services); INIT_LLIST_HEAD(&g_hlr->mslookup.server.local_site_services);
g_hlr->mslookup.server.local_attach_max_age = OSMO_DGSM_DEFAULT_LOCAL_ATTACH_MAX_AGE; g_hlr->mslookup.server.local_attach_max_age = 60 * 60;
g_hlr->mslookup.client.result_timeout_milliseconds = OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS; g_hlr->mslookup.client.result_timeout_milliseconds = OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS;

View File

@@ -22,11 +22,9 @@
#include <osmocom/mslookup/mslookup_client_mdns.h> #include <osmocom/mslookup/mslookup_client_mdns.h>
#include <osmocom/mslookup/mdns.h> #include <osmocom/mslookup/mdns.h>
#include <osmocom/hlr/hlr_vty.h> #include <osmocom/hlr/hlr_vty.h>
#include <osmocom/hlr/proxy.h>
#include <osmocom/hlr/mslookup_server.h> #include <osmocom/hlr/mslookup_server.h>
#include <osmocom/hlr/mslookup_server_mdns.h> #include <osmocom/hlr/mslookup_server_mdns.h>
#include <osmocom/gsupclient/cni_peer_id.h> #include <osmocom/gsupclient/cni_peer_id.h>
#include <osmocom/gsm/gsm23003.h>
struct cmd_node mslookup_node = { struct cmd_node mslookup_node = {
MSLOOKUP_NODE, MSLOOKUP_NODE,
@@ -190,53 +188,6 @@ DEFUN(cfg_mslookup_server_no_mdns_bind,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_mslookup_server_max_age,
cfg_mslookup_server_max_age_cmd,
"max-age <1-21600>",
"How old can the Last Location Update be for the mslookup server to respond\n"
"max age in seconds\n")
{
uint32_t val = atol(argv[0]);
g_hlr->mslookup.server.local_attach_max_age = val;
return CMD_SUCCESS;
}
DEFUN(cfg_mslookup_auth_imsi_only,
cfg_mslookup_auth_imsi_only_cmd,
"authorized-imsi-only",
"On local GSUP, use mslookup ignoring local HLR + don't answer queries for IMSIs without PS or CS network access mode")
{
g_hlr->mslookup.auth_imsi_only = true;
return CMD_SUCCESS;
}
DEFUN(cfg_mslookup_no_auth_imsi_only,
cfg_mslookup_no_auth_imsi_only_cmd,
"no authorized-imsi-only",
NO_STR "Answer Local GSUP/mDNS queries for any IMSI in the local HLR database")
{
g_hlr->mslookup.auth_imsi_only = false;
return CMD_SUCCESS;
}
DEFUN(cfg_mslookup_cod,
cfg_mslookup_cod_cmd,
"ignore-created-on-demand",
"Ignore IMSIs that were created-on-demand")
{
g_hlr->mslookup.ignore_created_on_demand = true;
return CMD_SUCCESS;
}
DEFUN(cfg_mslookup_no_cod,
cfg_mslookup_no_cod_cmd,
"no ignore-created-on-demand",
NO_STR "Answer mslookup and local GSUP for created on demand IMSIs")
{
g_hlr->mslookup.ignore_created_on_demand = false;
return CMD_SUCCESS;
}
struct cmd_node mslookup_server_msc_node = { struct cmd_node mslookup_server_msc_node = {
MSLOOKUP_SERVER_MSC_NODE, MSLOOKUP_SERVER_MSC_NODE,
"%s(config-mslookup-server-msc)# ", "%s(config-mslookup-server-msc)# ",
@@ -399,24 +350,6 @@ DEFUN(cfg_mslookup_no_client,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_mslookup_client_subscr_cod_fallback,
cfg_mslookup_client_subscr_cod_fallback_cmd,
"create-on-demand-fallback",
"If the msclient does not get a response from mDNS, proceed according to this HLR subscriber-create-on-demand config")
{
g_hlr->mslookup.client.subscr_create_on_demand_fallback = true;
return CMD_SUCCESS;
}
DEFUN(cfg_mslookup_client_no_subscr_cod_fallback,
cfg_mslookup_client_no_subscr_cod_fallback_cmd,
"no create-on-demand-fallback",
NO_STR "Return IMSI UNKNOWN if the mslookup client does not receive a response from mDNS")
{
g_hlr->mslookup.client.subscr_create_on_demand_fallback = false;
return CMD_SUCCESS;
}
DEFUN(cfg_mslookup_client_timeout, DEFUN(cfg_mslookup_client_timeout,
cfg_mslookup_client_timeout_cmd, cfg_mslookup_client_timeout_cmd,
"timeout <1-100000>", "timeout <1-100000>",
@@ -488,11 +421,6 @@ int config_write_mslookup(struct vty *vty)
vty_out(vty, "mslookup%s", VTY_NEWLINE); vty_out(vty, "mslookup%s", VTY_NEWLINE);
if (g_hlr->mslookup.auth_imsi_only)
vty_out(vty, " authorized-imsi-only%s", VTY_NEWLINE);
if (g_hlr->mslookup.ignore_created_on_demand)
vty_out(vty, " ignore-created-on-demand%s", VTY_NEWLINE);
if (g_hlr->mslookup.server.enable || !llist_empty(&g_hlr->mslookup.server.local_site_services)) { if (g_hlr->mslookup.server.enable || !llist_empty(&g_hlr->mslookup.server.local_site_services)) {
struct mslookup_server_msc_cfg *msc; struct mslookup_server_msc_cfg *msc;
@@ -522,9 +450,6 @@ int config_write_mslookup(struct vty *vty)
vty_out(vty, " msc ipa-name %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE); vty_out(vty, " msc ipa-name %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE);
config_write_msc_services(vty, " ", msc); config_write_msc_services(vty, " ", msc);
} }
if (g_hlr->mslookup.server.local_attach_max_age != OSMO_DGSM_DEFAULT_LOCAL_ATTACH_MAX_AGE)
vty_out(vty, " max-age %u%s",
g_hlr->mslookup.server.local_attach_max_age, VTY_NEWLINE);
/* If the server is disabled, still output the above to not lose the service config. */ /* If the server is disabled, still output the above to not lose the service config. */
if (!g_hlr->mslookup.server.enable) if (!g_hlr->mslookup.server.enable)
@@ -554,8 +479,6 @@ int config_write_mslookup(struct vty *vty)
vty_out(vty, " timeout %u%s", vty_out(vty, " timeout %u%s",
g_hlr->mslookup.client.result_timeout_milliseconds, g_hlr->mslookup.client.result_timeout_milliseconds,
VTY_NEWLINE); VTY_NEWLINE);
if (g_hlr->mslookup.client.subscr_create_on_demand_fallback)
vty_out(vty, " create-on-demand-fallback%s", VTY_NEWLINE);
} }
return CMD_SUCCESS; return CMD_SUCCESS;
@@ -622,110 +545,11 @@ DEFUN(do_mslookup_show_services,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
struct proxy_subscr_listentry {
struct llist_head entry;
timestamp_t last_update;
struct proxy_subscr data;
};
struct proxy_pending_gsup_req {
struct llist_head entry;
struct osmo_gsup_req *req;
timestamp_t received_at;
};
static void write_one_proxy(struct vty *vty, struct proxy_subscr_listentry *e)
{
struct proxy_subscr p = e->data;
uint32_t age;
vty_out(vty, "%-12s %-16s %-12s:%-4u ",
strlen(p.msisdn) == 0 ? "Unknown" : p.msisdn,
strlen(p.imsi) == 0 ? "Unknown" : p.imsi,
p.remote_hlr_addr.ip ? p.remote_hlr_addr.ip : "Unknown",
p.remote_hlr_addr.port);
if (!timestamp_age(&e->last_update, &age)) {
vty_out(vty, "Invalid%s", VTY_NEWLINE);
return;
}
#define UNIT_AGO(UNITNAME, UNITVAL) \
if (age >= (UNITVAL)) { \
vty_out(vty, "%u%s", age / (UNITVAL), UNITNAME); \
age = age % (UNITVAL); \
}
UNIT_AGO("d", 60*60*24);
UNIT_AGO("h", 60*60);
UNIT_AGO("m", 60);
UNIT_AGO("s", 1);
vty_out(vty, "%s", VTY_NEWLINE);
#undef UNIT_AGO
}
static void write_one_proxy_request(struct vty *vty, struct osmo_gsup_req *r)
{
vty_out(vty, "IMSI: %s TYPE: %s%s",
r->gsup.imsi,
osmo_gsup_message_type_name(r->gsup.message_type),
VTY_NEWLINE);
}
DEFUN(do_proxy_del_sub,
do_proxy_del_sub_cmd,
"proxy subscriber-delete [IMSI]",
"Subscriber Proxy \n"
"Delete by IMSI\n"
"IMSI of subscriber to delete from the Proxy"
)
{
const char *imsi = argv[0];
if (!osmo_imsi_str_valid(imsi)) {
vty_out(vty, "%% Not a valid IMSI: %s%s", imsi, VTY_NEWLINE);
return CMD_WARNING;
}
if (proxy_subscr_del(g_hlr->gs->proxy, imsi) == 0)
return CMD_SUCCESS;
vty_out(vty, "%% Unable to delete a Proxy for: %s%s", imsi, VTY_NEWLINE);
return CMD_WARNING;
}
DEFUN(do_proxy_show,
do_proxy_show_cmd,
"show proxy",
SHOW_STR "Proxy Entries\n")
{
struct proxy_subscr_listentry *e;
struct proxy_pending_gsup_req *p;
unsigned int count = 0;
vty_out(vty, "MSISDN IMSI HLR AGE%s", VTY_NEWLINE);
vty_out(vty, "------------ ---------------- -------------------- ------%s", VTY_NEWLINE);
llist_for_each_entry(e, &g_hlr->gs->proxy->subscr_list, entry) {
count++;
write_one_proxy(vty, e);
}
vty_out(vty, "%s%s",
(count == 0) ? "% No proxy subscribers" : "", VTY_NEWLINE);
if (!llist_count(&g_hlr->gs->proxy->pending_gsup_reqs))
return CMD_SUCCESS;
vty_out(vty, "In-flight Proxy Subscribers Requests:%s", VTY_NEWLINE);
llist_for_each_entry(p, &g_hlr->gs->proxy->pending_gsup_reqs, entry) {
write_one_proxy_request(vty, p->req);
}
return CMD_SUCCESS;
}
void dgsm_vty_init(void) void dgsm_vty_init(void)
{ {
install_element(CONFIG_NODE, &cfg_mslookup_cmd); install_element(CONFIG_NODE, &cfg_mslookup_cmd);
install_node(&mslookup_node, config_write_mslookup); install_node(&mslookup_node, config_write_mslookup);
install_element(MSLOOKUP_NODE, &cfg_mslookup_auth_imsi_only_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_auth_imsi_only_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_cod_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_cod_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_mdns_cmd); install_element(MSLOOKUP_NODE, &cfg_mslookup_mdns_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_mdns_domain_suffix_cmd); install_element(MSLOOKUP_NODE, &cfg_mslookup_mdns_domain_suffix_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_mdns_cmd); install_element(MSLOOKUP_NODE, &cfg_mslookup_no_mdns_cmd);
@@ -739,7 +563,6 @@ void dgsm_vty_init(void)
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_service_cmd); install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_service_cmd);
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_no_service_cmd); install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_no_service_cmd);
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_no_service_addr_cmd); install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_no_service_addr_cmd);
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_max_age_cmd);
install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_cmd); install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_cmd);
install_node(&mslookup_server_msc_node, NULL); install_node(&mslookup_server_msc_node, NULL);
@@ -750,8 +573,6 @@ void dgsm_vty_init(void)
install_element(MSLOOKUP_NODE, &cfg_mslookup_client_cmd); install_element(MSLOOKUP_NODE, &cfg_mslookup_client_cmd);
install_element(MSLOOKUP_NODE, &cfg_mslookup_no_client_cmd); install_element(MSLOOKUP_NODE, &cfg_mslookup_no_client_cmd);
install_node(&mslookup_client_node, NULL); install_node(&mslookup_client_node, NULL);
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_subscr_cod_fallback_cmd);
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_no_subscr_cod_fallback_cmd);
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_timeout_cmd); install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_timeout_cmd);
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_mdns_bind_cmd); install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_mdns_bind_cmd);
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_mdns_domain_suffix_cmd); install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_mdns_domain_suffix_cmd);
@@ -760,6 +581,4 @@ void dgsm_vty_init(void)
install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_no_gateway_proxy_cmd); install_element(MSLOOKUP_CLIENT_NODE, &cfg_mslookup_client_no_gateway_proxy_cmd);
install_element_ve(&do_mslookup_show_services_cmd); install_element_ve(&do_mslookup_show_services_cmd);
install_element_ve(&do_proxy_show_cmd);
install_element_ve(&do_proxy_del_sub_cmd);
} }

View File

@@ -24,16 +24,14 @@
#include <osmocom/core/msgb.h> #include <osmocom/core/msgb.h>
#include <osmocom/core/logging.h> #include <osmocom/core/logging.h>
#include <osmocom/core/linuxlist.h> #include <osmocom/core/linuxlist.h>
#include <osmocom/abis/ipa.h>
#include <osmocom/abis/ipaccess.h>
#include <osmocom/gsm/gsm48_ie.h> #include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/gsm/apn.h> #include <osmocom/gsm/apn.h>
#include <osmocom/gsm/protocol/ipaccess.h>
#include <osmocom/gsm/ipa.h>
#include <osmocom/gsm/gsm23003.h> #include <osmocom/gsm/gsm23003.h>
#include <osmocom/abis/ipa.h>
#include <osmocom/hlr/gsup_server.h> #include <osmocom/hlr/gsup_server.h>
#include <osmocom/hlr/gsup_router.h> #include <osmocom/hlr/gsup_router.h>
#include <osmocom/hlr/hlr.h>
#define LOG_GSUP_CONN(conn, level, fmt, args...) \ #define LOG_GSUP_CONN(conn, level, fmt, args...) \
LOGP(DLGSUP, level, "GSUP peer %s: " fmt, \ LOGP(DLGSUP, level, "GSUP peer %s: " fmt, \
@@ -50,7 +48,7 @@ static void osmo_gsup_server_send(struct osmo_gsup_conn *conn,
int proto_ext, struct msgb *msg_tx) int proto_ext, struct msgb *msg_tx)
{ {
ipa_prepend_header_ext(msg_tx, proto_ext); ipa_prepend_header_ext(msg_tx, proto_ext);
ipa_prepend_header(msg_tx, IPAC_PROTO_OSMO); ipa_msg_push_header(msg_tx, IPAC_PROTO_OSMO);
ipa_server_conn_send(conn->conn, msg_tx); ipa_server_conn_send(conn->conn, msg_tx);
} }
@@ -181,9 +179,11 @@ static int osmo_gsup_server_read_cb(struct ipa_server_conn *conn,
if (hh->proto == IPAC_PROTO_IPACCESS) { if (hh->proto == IPAC_PROTO_IPACCESS) {
rc = ipa_server_conn_ccm(conn, msg); rc = ipa_server_conn_ccm(conn, msg);
msgb_free(msg); if (rc < 0) {
if (rc < 0) /* conn is already invalid here! */ /* conn is already invalid here! */
return -1; return -1;
}
msgb_free(msg);
return 0; return 0;
} }
@@ -446,16 +446,19 @@ int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup,
* \param[out] gsup The gsup message to populate. * \param[out] gsup The gsup message to populate.
* \param[in] imsi The subscriber's IMSI. * \param[in] imsi The subscriber's IMSI.
* \param[in] msisdn The subscriber's MSISDN. * \param[in] msisdn The subscriber's MSISDN.
* \param[out] msisdn_enc A buffer large enough to store the MSISDN in encoded form.
* \param[in] msisdn_enc_size Size of the buffer (must be >= OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN).
* \param[out] apn_buf A buffer large enough to store an APN (required if cn_domain is OSMO_GSUP_CN_DOMAIN_PS).
* \param[in] apn_buf_size Size of APN buffer (must be >= APN_MAXLEN).
* \param[in] cn_domain The CN Domain of the subscriber connection. * \param[in] cn_domain The CN Domain of the subscriber connection.
* \param[in] talloc_ctx To allocation memory for dynamic fields (msisdn, apn) in the gsup field
* \returns 0 on success, and negative on error. * \returns 0 on success, and negative on error.
*/ */
int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn, int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
enum osmo_gsup_cn_domain cn_domain, uint8_t *msisdn_enc, size_t msisdn_enc_size,
void *talloc_ctx) uint8_t *apn_buf, size_t apn_buf_size,
enum osmo_gsup_cn_domain cn_domain)
{ {
int len; int len;
uint8_t *msisdn_buf = talloc_size(talloc_ctx, OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN);
OSMO_ASSERT(gsup); OSMO_ASSERT(gsup);
*gsup = (struct osmo_gsup_message){ *gsup = (struct osmo_gsup_message){
@@ -464,29 +467,27 @@ int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup,
osmo_strlcpy(gsup->imsi, imsi, sizeof(gsup->imsi)); osmo_strlcpy(gsup->imsi, imsi, sizeof(gsup->imsi));
len = gsm48_encode_bcd_number(msisdn_buf, OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN, 0, msisdn); if (msisdn_enc_size < OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN)
return -ENOSPC;
OSMO_ASSERT(msisdn_enc);
len = gsm48_encode_bcd_number(msisdn_enc, msisdn_enc_size, 0, msisdn);
if (len < 1) { if (len < 1) {
LOGP(DLGSUP, LOGL_ERROR, "%s: Error: cannot encode MSISDN '%s'\n", imsi, msisdn); LOGP(DLGSUP, LOGL_ERROR, "%s: Error: cannot encode MSISDN '%s'\n", imsi, msisdn);
return -ENOSPC; return -ENOSPC;
} }
gsup->msisdn_enc = msisdn_buf; gsup->msisdn_enc = msisdn_enc;
gsup->msisdn_enc_len = len; gsup->msisdn_enc_len = len;
#pragma message "FIXME: deal with encoding the following data: gsup.hlr_enc" #pragma message "FIXME: deal with encoding the following data: gsup.hlr_enc"
gsup->cn_domain = cn_domain; gsup->cn_domain = cn_domain;
if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS) { if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS) {
if (g_hlr->ps.pdp_profile.enabled) { OSMO_ASSERT(apn_buf_size >= APN_MAXLEN);
OSMO_ASSERT(g_hlr->ps.pdp_profile.num_pdp_infos <= ARRAY_SIZE(g_hlr->ps.pdp_profile.pdp_infos)); OSMO_ASSERT(apn_buf);
OSMO_ASSERT(g_hlr->ps.pdp_profile.num_pdp_infos <= ARRAY_SIZE(gsup->pdp_infos)); /* FIXME: PDP infos - use more fine-grained access control
memcpy(gsup->pdp_infos, instead of wildcard APN */
g_hlr->ps.pdp_profile.pdp_infos, osmo_gsup_configure_wildcard_apn(gsup, apn_buf, apn_buf_size);
sizeof(struct osmo_gsup_pdp_info) * g_hlr->ps.pdp_profile.num_pdp_infos);
gsup->num_pdp_infos = g_hlr->ps.pdp_profile.num_pdp_infos;
} else {
uint8_t *apn_buf = talloc_size(talloc_ctx, APN_MAXLEN);
osmo_gsup_configure_wildcard_apn(gsup, apn_buf, APN_MAXLEN);
}
} }
return 0; return 0;

View File

@@ -1,7 +1,7 @@
# This is _NOT_ the library release version, it's an API version. # This is _NOT_ the library release version, it's an API version.
# Please read chapter "Library interface versions" of the libtool documentation # Please read chapter "Library interface versions" of the libtool documentation
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
LIBVERSION=2:0:2 LIBVERSION=1:0:1
AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include \ AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include \
$(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOABIS_CFLAGS) $(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOABIS_CFLAGS)
@@ -11,7 +11,6 @@ lib_LTLIBRARIES = libosmo-gsup-client.la
libosmo_gsup_client_la_SOURCES = \ libosmo_gsup_client_la_SOURCES = \
cni_peer_id.c \ cni_peer_id.c \
gsup_client.c \ gsup_client.c \
gsup_client_mux.c \
gsup_req.c \ gsup_req.c \
$(NULL) $(NULL)

View File

@@ -2,8 +2,6 @@
* *
* All Rights Reserved * All Rights Reserved
* *
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or

View File

@@ -6,8 +6,6 @@
* Author: Jacob Erlbeck * Author: Jacob Erlbeck
* Author: Neels Hofmeyr * Author: Neels Hofmeyr
* *
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
@@ -26,7 +24,6 @@
#include <osmocom/gsupclient/gsup_client.h> #include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/abis/ipa.h> #include <osmocom/abis/ipa.h>
#include <osmocom/gsm/ipa.h>
#include <osmocom/gsm/oap_client.h> #include <osmocom/gsm/oap_client.h>
#include <osmocom/gsm/protocol/ipaccess.h> #include <osmocom/gsm/protocol/ipaccess.h>
#include <osmocom/core/msgb.h> #include <osmocom/core/msgb.h>
@@ -45,7 +42,7 @@ static void gsup_client_send_ping(struct osmo_gsup_client *gsupc)
msg->l2h = msgb_put(msg, 1); msg->l2h = msgb_put(msg, 1);
msg->l2h[0] = IPAC_MSGT_PING; msg->l2h[0] = IPAC_MSGT_PING;
ipa_prepend_header(msg, IPAC_PROTO_IPACCESS); ipa_msg_push_header(msg, IPAC_PROTO_IPACCESS);
ipa_client_conn_send(gsupc->link, msg); ipa_client_conn_send(gsupc->link, msg);
} }
@@ -115,7 +112,7 @@ static void client_send(struct osmo_gsup_client *gsupc, int proto_ext,
struct msgb *msg_tx) struct msgb *msg_tx)
{ {
ipa_prepend_header_ext(msg_tx, proto_ext); ipa_prepend_header_ext(msg_tx, proto_ext);
ipa_prepend_header(msg_tx, IPAC_PROTO_OSMO); ipa_msg_push_header(msg_tx, IPAC_PROTO_OSMO);
ipa_client_conn_send(gsupc->link, msg_tx); ipa_client_conn_send(gsupc->link, msg_tx);
/* msg_tx is now queued and will be freed. */ /* msg_tx is now queued and will be freed. */
} }
@@ -307,7 +304,7 @@ struct osmo_gsup_client *osmo_gsup_client_create3(void *talloc_ctx, struct osmo_
OSMO_ASSERT(config->ipa_dev->unit_name); OSMO_ASSERT(config->ipa_dev->unit_name);
gsupc = talloc(talloc_ctx, struct osmo_gsup_client); gsupc = talloc_zero(talloc_ctx, struct osmo_gsup_client);
OSMO_ASSERT(gsupc); OSMO_ASSERT(gsupc);
*gsupc = (struct osmo_gsup_client){ *gsupc = (struct osmo_gsup_client){
.unit_name = (const char *)config->ipa_dev->unit_name, /* API backwards compat */ .unit_name = (const char *)config->ipa_dev->unit_name, /* API backwards compat */
@@ -450,36 +447,3 @@ struct msgb *osmo_gsup_client_msgb_alloc(void)
{ {
return msgb_alloc_headroom(4000, 64, __func__); return msgb_alloc_headroom(4000, 64, __func__);
} }
void *osmo_gsup_client_get_data(const struct osmo_gsup_client *gsupc)
{
return gsupc->data;
}
void osmo_gsup_client_set_data(struct osmo_gsup_client *gsupc, void *data)
{
gsupc->data = data;
}
const char *osmo_gsup_client_get_rem_addr(const struct osmo_gsup_client *gsupc)
{
if (!gsupc->link)
return NULL;
return gsupc->link->addr;
}
uint16_t osmo_gsup_client_get_rem_port(const struct osmo_gsup_client *gsupc)
{
if (!gsupc->link)
return 0;
return gsupc->link->port;
}
bool osmo_gsup_client_is_connected(const struct osmo_gsup_client *gsupc)
{
return gsupc->is_connected;
}
const struct ipaccess_unit *osmo_gsup_client_get_ipaccess_unit(const struct osmo_gsup_client *gsupc)
{
return gsupc->ipa_dev;
}

View File

@@ -1,196 +0,0 @@
/* Directing individual GSUP messages to their respective handlers. */
/*
* (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved
*
* Author: Neels Hofmeyr
*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <osmocom/core/logging.h>
#include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/gsupclient/gsup_client_mux.h>
static enum osmo_gsup_message_class gsup_client_mux_classify(struct gsup_client_mux *gcm,
const struct osmo_gsup_message *gsup_msg)
{
if (gsup_msg->message_class)
return gsup_msg->message_class;
LOGP(DLGSUP, LOGL_DEBUG, "No explicit GSUP Message Class, trying to guess from message type %s\n",
osmo_gsup_message_type_name(gsup_msg->message_type));
switch (gsup_msg->message_type) {
case OSMO_GSUP_MSGT_PROC_SS_REQUEST:
case OSMO_GSUP_MSGT_PROC_SS_RESULT:
case OSMO_GSUP_MSGT_PROC_SS_ERROR:
return OSMO_GSUP_MESSAGE_CLASS_USSD;
/* GSM 04.11 code implementing MO SMS */
case OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR:
case OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT:
case OSMO_GSUP_MSGT_READY_FOR_SM_ERROR:
case OSMO_GSUP_MSGT_READY_FOR_SM_RESULT:
case OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST:
return OSMO_GSUP_MESSAGE_CLASS_SMS;
default:
return OSMO_GSUP_MESSAGE_CLASS_SUBSCRIBER_MANAGEMENT;
}
}
/* Non-static for unit tests */
int gsup_client_mux_rx(struct osmo_gsup_client *gsup_client, struct msgb *msg)
{
struct gsup_client_mux *gcm = osmo_gsup_client_get_data(gsup_client);
struct osmo_gsup_message gsup;
enum osmo_gsup_message_class message_class;
int rc;
rc = osmo_gsup_decode(msgb_l2(msg), msgb_l2len(msg), &gsup);
if (rc < 0) {
LOGP(DLGSUP, LOGL_ERROR, "Failed to decode GSUP message: '%s' (%d) [ %s]\n",
get_value_string(gsm48_gmm_cause_names, -rc), -rc, osmo_hexdump(msg->data, msg->len));
goto msgb_free_and_return;
}
if (!gsup.imsi[0]) {
LOGP(DLGSUP, LOGL_ERROR, "Failed to decode GSUP message: missing IMSI\n");
if (OSMO_GSUP_IS_MSGT_REQUEST(gsup.message_type))
gsup_client_mux_tx_error_reply(gcm, &gsup, GMM_CAUSE_INV_MAND_INFO);
rc = -GMM_CAUSE_INV_MAND_INFO;
goto msgb_free_and_return;
}
message_class = gsup_client_mux_classify(gcm, &gsup);
if (message_class <= OSMO_GSUP_MESSAGE_CLASS_UNSET || message_class >= ARRAY_SIZE(gcm->rx_cb)) {
LOGP(DLGSUP, LOGL_ERROR, "Failed to classify GSUP message target\n");
rc = -EINVAL;
goto msgb_free_and_return;
}
if (!gcm->rx_cb[message_class].func) {
LOGP(DLGSUP, LOGL_ERROR, "No receiver set up for GSUP Message Class %s\n", osmo_gsup_message_class_name(message_class));
rc = -ENOTSUP;
goto msgb_free_and_return;
}
rc = gcm->rx_cb[message_class].func(gcm, gcm->rx_cb[message_class].data, &gsup);
msgb_free_and_return:
msgb_free(msg);
return rc;
}
/* Make it clear that struct gsup_client_mux should be talloc allocated, so that it can be used as talloc parent. */
struct gsup_client_mux *gsup_client_mux_alloc(void *talloc_ctx)
{
return talloc_zero(talloc_ctx, struct gsup_client_mux);
}
/* Start a GSUP client to serve this gsup_client_mux. */
int gsup_client_mux_start(struct gsup_client_mux *gcm, const char *gsup_server_addr_str, uint16_t gsup_server_port,
struct ipaccess_unit *ipa_dev)
{
gcm->gsup_client = osmo_gsup_client_create2(gcm, ipa_dev,
gsup_server_addr_str,
gsup_server_port,
&gsup_client_mux_rx, NULL);
if (!gcm->gsup_client)
return -ENOMEM;
osmo_gsup_client_set_data(gcm->gsup_client, gcm);
return 0;
}
int gsup_client_mux_tx(struct gsup_client_mux *gcm, const struct osmo_gsup_message *gsup_msg)
{
struct msgb *msg;
int rc;
if (!gcm || !gcm->gsup_client) {
LOGP(DLGSUP, LOGL_ERROR, "GSUP link is down, cannot send GSUP message\n");
return -ENOTSUP;
}
msg = osmo_gsup_client_msgb_alloc();
rc = osmo_gsup_encode(msg, gsup_msg);
if (rc < 0) {
LOGP(DLGSUP, LOGL_ERROR, "Failed to encode GSUP message: '%s'\n", strerror(-rc));
return rc;
}
return osmo_gsup_client_send(gcm->gsup_client, msg);
}
/* Set GSUP source_name to our local IPA name */
void gsup_client_mux_tx_set_source(const struct gsup_client_mux *gcm,
struct osmo_gsup_message *gsup_msg)
{
const char *local_msc_name;
const struct ipaccess_unit *ipa_dev;
if (!gcm)
return;
if (!gcm->gsup_client)
return;
ipa_dev = osmo_gsup_client_get_ipaccess_unit(gcm->gsup_client);
if (!ipa_dev)
return;
local_msc_name = ipa_dev->serno;
if (!local_msc_name)
return;
gsup_msg->source_name = (const uint8_t *) local_msc_name;
gsup_msg->source_name_len = strlen(local_msc_name) + 1;
}
/* Transmit GSUP error in response to original message */
void gsup_client_mux_tx_error_reply(struct gsup_client_mux *gcm, const struct osmo_gsup_message *gsup_orig,
enum gsm48_gmm_cause cause)
{
struct osmo_gsup_message gsup_reply;
/* No need to answer if we couldn't parse an ERROR message type, only REQUESTs need an error reply. */
if (!OSMO_GSUP_IS_MSGT_REQUEST(gsup_orig->message_type))
return;
gsup_reply = (struct osmo_gsup_message){
.cause = cause,
.message_type = OSMO_GSUP_TO_MSGT_ERROR(gsup_orig->message_type),
.message_class = gsup_orig->message_class,
.destination_name = gsup_orig->source_name,
.destination_name_len = gsup_orig->source_name_len,
/* RP-Message-Reference is mandatory for SM Service */
.sm_rp_mr = gsup_orig->sm_rp_mr,
};
OSMO_STRLCPY_ARRAY(gsup_reply.imsi, gsup_orig->imsi);
gsup_client_mux_tx_set_source(gcm, &gsup_reply);
/* For SS/USSD, it's important to keep both session state and ID IEs */
if (gsup_orig->session_state != OSMO_GSUP_SESSION_STATE_NONE) {
gsup_reply.session_state = OSMO_GSUP_SESSION_STATE_END;
gsup_reply.session_id = gsup_orig->session_id;
}
if (osmo_gsup_client_enc_send(gcm->gsup_client, &gsup_reply))
LOGP(DLGSUP, LOGL_ERROR, "Failed to send Error reply (imsi=%s)\n",
osmo_quote_str(gsup_orig->imsi, -1));
}

View File

@@ -2,8 +2,6 @@
* *
* All Rights Reserved * All Rights Reserved
* *
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or

View File

@@ -49,7 +49,6 @@
#include <osmocom/hlr/rand.h> #include <osmocom/hlr/rand.h>
#include <osmocom/hlr/hlr_vty.h> #include <osmocom/hlr/hlr_vty.h>
#include <osmocom/hlr/hlr_ussd.h> #include <osmocom/hlr/hlr_ussd.h>
#include <osmocom/hlr/hlr_sms.h>
#include <osmocom/hlr/dgsm.h> #include <osmocom/hlr/dgsm.h>
#include <osmocom/hlr/proxy.h> #include <osmocom/hlr/proxy.h>
#include <osmocom/hlr/lu_fsm.h> #include <osmocom/hlr/lu_fsm.h>
@@ -86,6 +85,8 @@ osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr)
llist_for_each_entry(co, &g_hlr->gs->clients, list) { llist_for_each_entry(co, &g_hlr->gs->clients, list) {
struct osmo_gsup_message gsup = { }; struct osmo_gsup_message gsup = { };
uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
uint8_t apn[APN_MAXLEN];
struct msgb *msg_out; struct msgb *msg_out;
uint8_t *peer; uint8_t *peer;
int peer_len; int peer_len;
@@ -130,7 +131,8 @@ osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr)
subscr->imsi, cn_domain == OSMO_GSUP_CN_DOMAIN_PS ? "PS" : "CS", subscr->imsi, cn_domain == OSMO_GSUP_CN_DOMAIN_PS ? "PS" : "CS",
osmo_quote_str(peer_compare, -1)); osmo_quote_str(peer_compare, -1));
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, subscr->msisdn, cn_domain, OTC_SELECT) != 0) { if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, subscr->msisdn, msisdn_enc,
sizeof(msisdn_enc), apn, sizeof(apn), cn_domain) != 0) {
LOGP(DLGSUP, LOGL_ERROR, LOGP(DLGSUP, LOGL_ERROR,
"IMSI='%s': Cannot notify GSUP client; could not create gsup message " "IMSI='%s': Cannot notify GSUP client; could not create gsup message "
"for %s:%u\n", subscr->imsi, "for %s:%u\n", subscr->imsi,
@@ -204,34 +206,23 @@ static int subscr_create_on_demand(const char *imsi)
{ {
char msisdn[GSM23003_MSISDN_MAX_DIGITS + 1]; char msisdn[GSM23003_MSISDN_MAX_DIGITS + 1];
int rc; int rc;
unsigned int rand_msisdn_len = g_hlr->subscr_create_on_demand_rand_msisdn_len;
if (!g_hlr->subscr_create_on_demand)
return -1;
if (db_subscr_exists_by_imsi(g_hlr->dbc, imsi) == 0) if (db_subscr_exists_by_imsi(g_hlr->dbc, imsi) == 0)
return -1; return -1;
if (rand_msisdn_len && generate_new_msisdn(msisdn, imsi, rand_msisdn_len) != 0)
switch (g_hlr->subscr_create_on_demand.mode) {
case SUBSCR_COD_MODE_MSISDN_FROM_IMSI:
OSMO_STRLCPY_ARRAY(msisdn, imsi);
break;
case SUBSCR_COD_MODE_RAND_MSISDN:
if (generate_new_msisdn(msisdn, imsi, g_hlr->subscr_create_on_demand.rand_msisdn_len) != 0)
return -1; return -1;
break;
case SUBSCR_COD_MODE_NO_MSISDN:
msisdn[0] = '\0';
break;
case SUBSCR_COD_MODE_DISABLED:
default:
return -1;
}
LOGP(DMAIN, LOGL_INFO, "IMSI='%s': Creating subscriber on demand\n", imsi); LOGP(DMAIN, LOGL_INFO, "IMSI='%s': Creating subscriber on demand\n", imsi);
rc = db_subscr_create(g_hlr->dbc, imsi, g_hlr->subscr_create_on_demand.flags); rc = db_subscr_create(g_hlr->dbc, imsi, g_hlr->subscr_create_on_demand_flags);
if (rc) { if (rc) {
LOGP(DMAIN, LOGL_ERROR, "Failed to create subscriber on demand (rc=%d): IMSI='%s'\n", rc, imsi); LOGP(DMAIN, LOGL_ERROR, "Failed to create subscriber on demand (rc=%d): IMSI='%s'\n", rc, imsi);
return rc; return rc;
} }
if (msisdn[0] == '\0') if (!rand_msisdn_len)
return 0; return 0;
/* Update MSISDN of the new (just allocated) subscriber */ /* Update MSISDN of the new (just allocated) subscriber */
@@ -333,11 +324,7 @@ static int rx_send_auth_info(struct osmo_gsup_req *req)
" Returning slightly inaccurate cause 'IMSI Unknown' via GSUP"); " Returning slightly inaccurate cause 'IMSI Unknown' via GSUP");
return rc; return rc;
case -ENOENT: case -ENOENT:
osmo_gsup_req_respond_err(req, osmo_gsup_req_respond_err(req, g_hlr->reject_cause, "IMSI unknown");
(req->gsup.cn_domain == OSMO_GSUP_CN_DOMAIN_CS) ?
g_hlr->no_proxy_reject_cause.cs :
g_hlr->no_proxy_reject_cause.ps,
"IMSI unknown");
return rc; return rc;
default: default:
osmo_gsup_req_respond_err(req, GMM_CAUSE_NET_FAIL, "failure to look up IMSI in db"); osmo_gsup_req_respond_err(req, GMM_CAUSE_NET_FAIL, "failure to look up IMSI in db");
@@ -395,7 +382,7 @@ static int rx_purge_ms_req(struct osmo_gsup_req *req)
return rc; return rc;
} }
static int rx_check_imei_req(struct osmo_gsup_req *req, bool final) static int rx_check_imei_req(struct osmo_gsup_req *req)
{ {
struct osmo_gsup_message gsup_reply; struct osmo_gsup_message gsup_reply;
char imei[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1] = {0}; char imei[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1] = {0};
@@ -449,7 +436,7 @@ static int rx_check_imei_req(struct osmo_gsup_req *req, bool final)
.message_type = OSMO_GSUP_MSGT_CHECK_IMEI_RESULT, .message_type = OSMO_GSUP_MSGT_CHECK_IMEI_RESULT,
.imei_result = OSMO_GSUP_IMEI_RESULT_ACK, .imei_result = OSMO_GSUP_IMEI_RESULT_ACK,
}; };
return osmo_gsup_req_respond(req, &gsup_reply, false, final); return osmo_gsup_req_respond(req, &gsup_reply, false, true);
} }
static char namebuf[255]; static char namebuf[255];
@@ -570,16 +557,7 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
lu_rx_gsup(req); lu_rx_gsup(req);
break; break;
case OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST: case OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST:
rx_check_imei_req(req, true); rx_check_imei_req(req);
break;
case OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST:
forward_mo_sms(req);
break;
case OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST:
forward_mt_sms(req);
break;
case OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST:
rx_ready_for_sm_req(req);
break; break;
default: default:
LOGP(DMAIN, LOGL_DEBUG, "Unhandled GSUP message type %s\n", LOGP(DMAIN, LOGL_DEBUG, "Unhandled GSUP message type %s\n",
@@ -590,12 +568,6 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
return 0; return 0;
} }
void dgsm_fallback_to_hlr(struct osmo_gsup_req *req) {
LOGP(DDGSM, LOGL_DEBUG, "Fall back to HLR from DGSM for [%s]\n",
osmo_gsup_message_type_name(req->gsup.message_type));
rx_check_imei_req(req, false);
}
static void print_usage(void) static void print_usage(void)
{ {
printf("Usage: osmo-hlr\n"); printf("Usage: osmo-hlr\n");
@@ -755,7 +727,7 @@ static void signal_hdlr(int signal)
} }
static const char vlr_copyright[] = static const char vlr_copyright[] =
"Copyright (C) 2016-2023 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n" "Copyright (C) 2016, 2017 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n" "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
"This is free software: you are free to change and redistribute it.\r\n" "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"; "There is NO WARRANTY, to the extent permitted by law.\r\n";
@@ -764,6 +736,7 @@ static struct vty_app_info vty_info = {
.name = "OsmoHLR", .name = "OsmoHLR",
.version = PACKAGE_VERSION, .version = PACKAGE_VERSION,
.copyright = vlr_copyright, .copyright = vlr_copyright,
.is_config_node = hlr_vty_is_config_node,
.go_parent_cb = hlr_vty_go_parent, .go_parent_cb = hlr_vty_go_parent,
}; };
@@ -780,18 +753,14 @@ int main(int argc, char **argv)
g_hlr = talloc_zero(hlr_ctx, struct hlr); g_hlr = talloc_zero(hlr_ctx, struct hlr);
INIT_LLIST_HEAD(&g_hlr->euse_list); INIT_LLIST_HEAD(&g_hlr->euse_list);
INIT_LLIST_HEAD(&g_hlr->smsc_list);
INIT_LLIST_HEAD(&g_hlr->ss_sessions); INIT_LLIST_HEAD(&g_hlr->ss_sessions);
INIT_LLIST_HEAD(&g_hlr->ussd_routes); INIT_LLIST_HEAD(&g_hlr->ussd_routes);
INIT_LLIST_HEAD(&g_hlr->smsc_routes);
INIT_LLIST_HEAD(&g_hlr->mslookup.server.local_site_services); INIT_LLIST_HEAD(&g_hlr->mslookup.server.local_site_services);
g_hlr->db_file_path = talloc_strdup(g_hlr, HLR_DEFAULT_DB_FILE_PATH); g_hlr->db_file_path = talloc_strdup(g_hlr, HLR_DEFAULT_DB_FILE_PATH);
g_hlr->mslookup.server.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT); g_hlr->mslookup.server.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT);
g_hlr->mslookup.client.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT); g_hlr->mslookup.client.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT);
g_hlr->reject_cause.cs = GMM_CAUSE_PLMN_NOTALLOWED; g_hlr->reject_cause = GMM_CAUSE_IMSI_UNKNOWN;
g_hlr->no_proxy_reject_cause.cs = GMM_CAUSE_PLMN_NOTALLOWED; g_hlr->no_proxy_reject_cause = GMM_CAUSE_IMSI_UNKNOWN;
g_hlr->reject_cause.ps = GMM_CAUSE_NET_FAIL;
g_hlr->no_proxy_reject_cause.ps = GMM_CAUSE_NET_FAIL;
/* Init default (call independent) SS session guard timeout value */ /* Init default (call independent) SS session guard timeout value */
g_hlr->ncss_guard_timeout = NCSS_GUARD_TIMEOUT_DEFAULT; g_hlr->ncss_guard_timeout = NCSS_GUARD_TIMEOUT_DEFAULT;

View File

@@ -1,276 +0,0 @@
/* OsmoHLR SMS-over-GSUP routing implementation */
/* Author: Mychaela N. Falconia <falcon@freecalypso.org>, 2023 - however,
* Mother Mychaela's contributions are NOT subject to copyright.
* No rights reserved, all rights relinquished.
*
* Based on earlier unmerged work by Vadim Yanitskiy, 2019.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gsm/gsup.h>
#include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/gsm/protocol/gsm_04_11.h>
#include <osmocom/hlr/hlr.h>
#include <osmocom/hlr/hlr_sms.h>
#include <osmocom/hlr/gsup_server.h>
#include <osmocom/hlr/gsup_router.h>
#include <osmocom/hlr/logging.h>
#include <osmocom/hlr/db.h>
/***********************************************************************
* core data structures expressing config from VTY
***********************************************************************/
struct hlr_smsc *smsc_find(struct hlr *hlr, const char *name)
{
struct hlr_smsc *smsc;
llist_for_each_entry(smsc, &hlr->smsc_list, list) {
if (!strcmp(smsc->name, name))
return smsc;
}
return NULL;
}
struct hlr_smsc *smsc_alloc(struct hlr *hlr, const char *name)
{
struct hlr_smsc *smsc = smsc_find(hlr, name);
if (smsc)
return NULL;
smsc = talloc_zero(hlr, struct hlr_smsc);
smsc->name = talloc_strdup(smsc, name);
smsc->hlr = hlr;
llist_add_tail(&smsc->list, &hlr->smsc_list);
return smsc;
}
void smsc_free(struct hlr_smsc *smsc)
{
llist_del(&smsc->list);
talloc_free(smsc);
}
struct hlr_smsc_route *smsc_route_find(struct hlr *hlr, const char *num_addr)
{
struct hlr_smsc_route *rt;
llist_for_each_entry(rt, &hlr->smsc_routes, list) {
if (!strcmp(rt->num_addr, num_addr))
return rt;
}
return NULL;
}
struct hlr_smsc_route *smsc_route_alloc(struct hlr *hlr, const char *num_addr,
struct hlr_smsc *smsc)
{
struct hlr_smsc_route *rt;
if (smsc_route_find(hlr, num_addr))
return NULL;
rt = talloc_zero(hlr, struct hlr_smsc_route);
rt->num_addr = talloc_strdup(rt, num_addr);
rt->smsc = smsc;
llist_add_tail(&rt->list, &hlr->smsc_routes);
return rt;
}
void smsc_route_free(struct hlr_smsc_route *rt)
{
llist_del(&rt->list);
talloc_free(rt);
}
/***********************************************************************
* forwarding of MO SMS to SMSCs based on SM-RP-DA
***********************************************************************/
static const struct hlr_smsc *find_smsc_route(const char *smsc_addr)
{
const struct hlr_smsc_route *rt;
rt = smsc_route_find(g_hlr, smsc_addr);
if (rt)
return rt->smsc;
return g_hlr->smsc_default;
}
static void respond_with_sm_rp_cause(struct osmo_gsup_req *req,
uint8_t sm_rp_cause)
{
struct osmo_gsup_message rsp_msg = { };
rsp_msg.sm_rp_cause = &sm_rp_cause;
osmo_gsup_req_respond(req, &rsp_msg, true, true);
}
/* Short Message from MSC/VLR towards SMSC */
void forward_mo_sms(struct osmo_gsup_req *req)
{
uint8_t gsm48_decode_buffer[GSM411_SMSC_ADDR_MAX_OCTETS];
char smsc_addr[GSM411_SMSC_ADDR_MAX_DIGITS+1];
const struct hlr_smsc *smsc;
struct osmo_cni_peer_id dest_peer;
/* Make sure SM-RP-DA (SMSC address) is present */
if (req->gsup.sm_rp_da == NULL || !req->gsup.sm_rp_da_len) {
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO,
"missing SM-RP-DA");
return;
}
if (req->gsup.sm_rp_da_type != OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR) {
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO,
"SM-RP-DA type is not SMSC");
return;
}
/* Enforce the length constrainst on SM-RP-DA, as specified in
* GSM 04.11 section 8.2.5.2. Also enforce absence of ToN/NPI
* extension octets at the same time. */
if (req->gsup.sm_rp_da_len < GSM411_SMSC_ADDR_MIN_OCTETS ||
req->gsup.sm_rp_da_len > GSM411_SMSC_ADDR_MAX_OCTETS ||
!(req->gsup.sm_rp_da[0] & 0x80)) {
/* This form of bogosity originates from the MS,
* not from OsmoMSC or any other Osmocom network elements! */
LOGP(DLSMS, LOGL_NOTICE,
"Rx '%s' (IMSI-%s) contains invalid SM-RP-DA from MS\n",
osmo_gsup_message_type_name(req->gsup.message_type),
req->gsup.imsi);
respond_with_sm_rp_cause(req, GSM411_RP_CAUSE_SEMANT_INC_MSG);
return;
}
/* Decode SMSC address from SM-RP-DA */
gsm48_decode_buffer[0] = req->gsup.sm_rp_da_len - 1;
memcpy(gsm48_decode_buffer + 1, req->gsup.sm_rp_da + 1,
req->gsup.sm_rp_da_len - 1);
gsm48_decode_bcd_number2(smsc_addr, sizeof(smsc_addr),
gsm48_decode_buffer,
req->gsup.sm_rp_da_len, 0);
/* Look for a route to this SMSC */
smsc = find_smsc_route(smsc_addr);
if (smsc == NULL) {
LOGP(DLSMS, LOGL_NOTICE,
"Failed to find a route for '%s' (IMSI-%s, SMSC-Addr-%s)\n",
osmo_gsup_message_type_name(req->gsup.message_type),
req->gsup.imsi, smsc_addr);
respond_with_sm_rp_cause(req,
GSM411_RP_CAUSE_MO_NUM_UNASSIGNED);
return;
}
/* We got the IPA name of our SMSC - forward the message */
osmo_cni_peer_id_set(&dest_peer, OSMO_CNI_PEER_ID_IPA_NAME,
(const uint8_t *) smsc->name,
strlen(smsc->name) + 1);
osmo_gsup_forward_to_local_peer(req->cb_data, &dest_peer, req, NULL);
}
/***********************************************************************
* forwarding of MT SMS from SMSCs to MSC/VLR based on IMSI
***********************************************************************/
void forward_mt_sms(struct osmo_gsup_req *req)
{
struct hlr_subscriber subscr;
struct osmo_cni_peer_id dest_peer;
int rc;
rc = db_subscr_get_by_imsi(g_hlr->dbc, req->gsup.imsi, &subscr);
if (rc < 0) {
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN,
"IMSI unknown");
return;
}
/* is this subscriber currently attached to a VLR? */
if (!subscr.vlr_number[0]) {
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMPL_DETACHED,
"subscriber not attached to a VLR");
return;
}
osmo_cni_peer_id_set(&dest_peer, OSMO_CNI_PEER_ID_IPA_NAME,
(const uint8_t *) subscr.vlr_number,
strlen(subscr.vlr_number) + 1);
osmo_gsup_forward_to_local_peer(req->cb_data, &dest_peer, req, NULL);
}
/***********************************************************************
* READY-FOR-SM handling
*
* An MSC indicates that an MS is ready to receive messages. If one
* or more SMSCs have previously tried to send MT SMS to this MS and
* failed, we should pass this READY-FOR-SM message to them so they
* can resend their queued SMS right away. But which SMSC do we
* forward the message to? 3GPP specs call for a complicated system
* where the HLR remembers which SMSCs have tried and failed to deliver
* MT SMS, and those SMSCs then get notified - but that design is too
* much complexity for the current state of Osmocom. So we keep it
* simple: we iterate over all configured SMSCs and forward a copy
* of the READY-FOR-SM.req message to each.
*
* Routing of responses is another problem: the MSC that sent
* READY-FOR-SM.req expects only one response, and one can even argue
* that the operation is a "success" from the perspective of the MS
* irrespective of whether each given SMSC handled the notification
* successfully or not. Hence our approach: we always return success
* to the MS, and when we forward copies of READY-FOR-SM.req to SMSCs,
* we list the HLR as the message source - this way SMSC responses
* will terminate at this HLR and won't be forwarded to the MSC.
***********************************************************************/
static void forward_req_copy_to_smsc(const struct osmo_gsup_req *req,
const struct hlr_smsc *smsc)
{
const char *my_ipa_name = g_hlr->gsup_unit_name.serno;
struct osmo_gsup_message forward = req->gsup;
struct osmo_ipa_name smsc_ipa_name;
/* set the source to this HLR */
forward.source_name = (const uint8_t *) my_ipa_name;
forward.source_name_len = strlen(my_ipa_name) + 1;
/* send it off */
LOG_GSUP_REQ(req, LOGL_INFO, "Forwarding source-reset copy to %s\n",
smsc->name);
osmo_ipa_name_set(&smsc_ipa_name, (const uint8_t *) smsc->name,
strlen(smsc->name) + 1);
osmo_gsup_enc_send_to_ipa_name(g_hlr->gs, &smsc_ipa_name, &forward);
}
void rx_ready_for_sm_req(struct osmo_gsup_req *req)
{
struct hlr_smsc *smsc;
/* fan request msg out to all SMSCs */
llist_for_each_entry(smsc, &g_hlr->smsc_list, list)
forward_req_copy_to_smsc(req, smsc);
/* send OK response to the MSC and the MS */
osmo_gsup_req_respond_msgt(req, OSMO_GSUP_MSGT_READY_FOR_SM_RESULT,
true);
}

View File

@@ -122,40 +122,9 @@ void ussd_route_del(struct hlr_ussd_route *rt)
talloc_free(rt); talloc_free(rt);
} }
static struct hlr_ussd_route *ussd_route_lookup_for_req(struct hlr *hlr, const struct ss_request *req) static struct hlr_ussd_route *ussd_route_lookup_7bit(struct hlr *hlr, const char *ussd_code)
{ {
const uint8_t cgroup = req->ussd_data_dcs >> 4;
const uint8_t lang = req->ussd_data_dcs & 0x0f;
char ussd_code[GSM0480_USSD_7BIT_STRING_LEN];
struct hlr_ussd_route *rt; struct hlr_ussd_route *rt;
ussd_code[0] = '\0';
/* We support only the Coding Group 0 (GSM 7-bit default alphabeet). In fact,
* the USSD request is usually limited to [*#0-9], so we don't really need to
* support other coding groups and languages. */
switch (cgroup) {
case 0:
/* The Language is usually set to '1111'B (unspecified), but some UEs
* are known to indicate '0000'B (German). */
if (lang != 0x0f) {
LOGP(DSS, LOGL_NOTICE, "USSD DataCodingScheme (0x%02x): "
"the Language is usually set to 15 (unspecified), "
"but the request indicates %u - ignoring this\n",
req->ussd_data_dcs, lang);
/* do not abort, attempt to decode as if it was '1111'B */
}
gsm_7bit_decode_n_ussd(&ussd_code[0], sizeof(ussd_code),
req->ussd_data, (req->ussd_data_len * 8) / 7);
break;
default:
LOGP(DSS, LOGL_ERROR, "USSD DataCodingScheme (0x%02x): "
"Coding Group %u is not supported, expecting Coding Group 0\n",
req->ussd_data_dcs, cgroup);
return NULL;
}
llist_for_each_entry(rt, &hlr->ussd_routes, list) { llist_for_each_entry(rt, &hlr->ussd_routes, list) {
if (!strncmp(ussd_code, rt->prefix, strlen(rt->prefix))) { if (!strncmp(ussd_code, rt->prefix, strlen(rt->prefix))) {
LOGP(DSS, LOGL_DEBUG, "Found %s '%s' (prefix '%s') for USSD " LOGP(DSS, LOGL_DEBUG, "Found %s '%s' (prefix '%s') for USSD "
@@ -634,7 +603,7 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
} else { } else {
/* VLR->EUSE: MO USSD. VLR is known ('conn'), EUSE is to be resolved */ /* VLR->EUSE: MO USSD. VLR is known ('conn'), EUSE is to be resolved */
struct hlr_ussd_route *rt; struct hlr_ussd_route *rt;
rt = ussd_route_lookup_for_req(hlr, &req); rt = ussd_route_lookup_7bit(hlr, (const char *) req.ussd_text);
if (rt) { if (rt) {
if (rt->is_external) { if (rt->is_external) {
ss->is_external = true; ss->is_external = true;
@@ -662,8 +631,7 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
if (!ss) { if (!ss) {
LOGP(DSS, LOGL_ERROR, "%s/0x%08x: CONTINUE for unknown SS session\n", LOGP(DSS, LOGL_ERROR, "%s/0x%08x: CONTINUE for unknown SS session\n",
gsup->imsi, gsup->session_id); gsup->imsi, gsup->session_id);
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_MSGT_INCOMP_P_STATE, osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_INV_MAND_INFO, "CONTINUE for unknown SS session");
"CONTINUE for unknown SS session");
return; return;
} }
@@ -684,8 +652,6 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
if (!ss) { if (!ss) {
LOGP(DSS, LOGL_ERROR, "%s/0x%08x: END for unknown SS session\n", LOGP(DSS, LOGL_ERROR, "%s/0x%08x: END for unknown SS session\n",
gsup->imsi, gsup->session_id); gsup->imsi, gsup->session_id);
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_MSGT_INCOMP_P_STATE,
"END for unknown SS session");
return; return;
} }
@@ -716,5 +682,4 @@ void rx_proc_ss_error(struct osmo_gsup_req *req)
{ {
LOGP(DSS, LOGL_NOTICE, "%s/0x%08x: Process SS ERROR (%s)\n", req->gsup.imsi, req->gsup.session_id, LOGP(DSS, LOGL_NOTICE, "%s/0x%08x: Process SS ERROR (%s)\n", req->gsup.imsi, req->gsup.session_id,
osmo_gsup_session_state_name(req->gsup.session_state)); osmo_gsup_session_state_name(req->gsup.session_state));
osmo_gsup_req_free(req);
} }

View File

@@ -26,12 +26,9 @@
*/ */
#include <errno.h> #include <errno.h>
#include <string.h>
#include <osmocom/core/talloc.h> #include <osmocom/core/talloc.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/apn.h>
#include <osmocom/vty/vty.h> #include <osmocom/vty/vty.h>
#include <osmocom/vty/stats.h> #include <osmocom/vty/stats.h>
#include <osmocom/vty/command.h> #include <osmocom/vty/command.h>
@@ -44,7 +41,6 @@
#include <osmocom/hlr/hlr_vty.h> #include <osmocom/hlr/hlr_vty.h>
#include <osmocom/hlr/hlr_vty_subscr.h> #include <osmocom/hlr/hlr_vty_subscr.h>
#include <osmocom/hlr/hlr_ussd.h> #include <osmocom/hlr/hlr_ussd.h>
#include <osmocom/hlr/hlr_sms.h>
#include <osmocom/hlr/gsup_server.h> #include <osmocom/hlr/gsup_server.h>
static const struct value_string gsm48_gmm_cause_vty_names[] = { static const struct value_string gsm48_gmm_cause_vty_names[] = {
@@ -107,202 +103,26 @@ DEFUN(cfg_gsup,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
struct cmd_node ps_node = { static int config_write_hlr(struct vty *vty)
PS_NODE,
"%s(config-hlr-ps)# ",
1,
};
DEFUN(cfg_ps,
cfg_ps_cmd,
"ps",
"Configure the PS options")
{ {
vty->node = PS_NODE; vty_out(vty, "hlr%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
struct cmd_node ps_pdp_profiles_node = { if (g_hlr->reject_cause != GMM_CAUSE_IMSI_UNKNOWN)
PS_PDP_PROFILES_NODE, vty_out(vty, " reject-cause not-found %s%s",
"%s(config-hlr-ps-pdp-profiles)# ", get_value_string_or_null(gsm48_gmm_cause_vty_names,
1, (uint32_t) g_hlr->reject_cause), VTY_NEWLINE);
}; if (g_hlr->no_proxy_reject_cause != GMM_CAUSE_IMSI_UNKNOWN)
vty_out(vty, " reject-cause no-proxy %s%s",
DEFUN(cfg_ps_pdp_profiles, get_value_string_or_null(gsm48_gmm_cause_vty_names,
cfg_ps_pdp_profiles_cmd, (uint32_t) g_hlr->no_proxy_reject_cause), VTY_NEWLINE);
"pdp-profiles default", if (g_hlr->store_imei)
"Define a PDP profile set.\n" vty_out(vty, " store-imei%s", VTY_NEWLINE);
"Define the global default profile.\n") if (g_hlr->db_file_path && strcmp(g_hlr->db_file_path, HLR_DEFAULT_DB_FILE_PATH))
{ vty_out(vty, " database %s%s", g_hlr->db_file_path, VTY_NEWLINE);
g_hlr->ps.pdp_profile.enabled = true; if (g_hlr->subscr_create_on_demand) {
const char *flags_str = "none";
vty->node = PS_PDP_PROFILES_NODE; uint8_t flags = g_hlr->subscr_create_on_demand_flags;
return CMD_SUCCESS; unsigned int rand_msisdn_len = g_hlr->subscr_create_on_demand_rand_msisdn_len;
}
DEFUN(cfg_no_ps_pdp_profiles,
cfg_no_ps_pdp_profiles_cmd,
"no pdp-profiles default",
NO_STR
"Delete PDP profile.\n"
"Unique identifier for this PDP profile set.\n")
{
g_hlr->ps.pdp_profile.enabled = false;
return CMD_SUCCESS;
}
struct cmd_node ps_pdp_profiles_profile_node = {
PS_PDP_PROFILES_PROFILE_NODE,
"%s(config-hlr-ps-pdp-profile)# ",
1,
};
/* context_id == 0 means the slot is free */
struct osmo_gsup_pdp_info *get_pdp_profile(uint8_t context_id)
{
for (int i = 0; i < OSMO_GSUP_MAX_NUM_PDP_INFO; i++) {
struct osmo_gsup_pdp_info *info = &g_hlr->ps.pdp_profile.pdp_infos[i];
if (info->context_id == context_id)
return info;
}
return NULL;
}
struct osmo_gsup_pdp_info *create_pdp_profile(uint8_t context_id)
{
struct osmo_gsup_pdp_info *info = get_pdp_profile(0);
if (!info)
return NULL;
memset(info, 0, sizeof(*info));
info->context_id = context_id;
info->have_info = 1;
g_hlr->ps.pdp_profile.num_pdp_infos++;
return info;
}
void destroy_pdp_profile(struct osmo_gsup_pdp_info *info)
{
info->context_id = 0;
if (info->apn_enc)
talloc_free((void *) info->apn_enc);
g_hlr->ps.pdp_profile.num_pdp_infos--;
memset(info, 0, sizeof(*info));
}
DEFUN(cfg_ps_pdp_profiles_profile,
cfg_ps_pdp_profiles_profile_cmd,
"profile <1-10>",
"Configure a PDP profile\n"
"Unique PDP context identifier. The lowest profile will be used as default context.\n")
{
struct osmo_gsup_pdp_info *info;
uint8_t context_id = atoi(argv[0]);
info = get_pdp_profile(context_id);
if (!info) {
info = create_pdp_profile(context_id);
if (!info) {
vty_out(vty, "Failed to create profile %d!%s", context_id, VTY_NEWLINE);
return CMD_ERR_INCOMPLETE;
}
}
vty->node = PS_PDP_PROFILES_PROFILE_NODE;
vty->index = info;
return CMD_SUCCESS;
}
DEFUN(cfg_no_ps_pdp_profiles_profile,
cfg_no_ps_pdp_profiles_profile_cmd,
"no profile <1-10>",
NO_STR
"Delete a PDP profile\n"
"Unique PDP context identifier. The lowest profile will be used as default context.\n")
{
struct osmo_gsup_pdp_info *info;
uint8_t context_id = atoi(argv[0]);
info = get_pdp_profile(context_id);
if (info)
destroy_pdp_profile(info);
return CMD_SUCCESS;
}
DEFUN(cfg_ps_pdp_profile_apn, cfg_ps_pdp_profile_apn_cmd,
"apn ID",
"Configure the APN.\n"
"APN name or * for wildcard apn.\n")
{
struct osmo_gsup_pdp_info *info = vty->index;
const char *apn_name = argv[0];
/* apn encoded takes one more byte than strlen() */
size_t apn_enc_len = strlen(apn_name) + 1;
uint8_t *apn_enc;
int ret;
if (apn_enc_len > APN_MAXLEN) {
vty_out(vty, "APN name is too long '%s'. Max is %d!%s", apn_name, APN_MAXLEN, VTY_NEWLINE);
return CMD_ERR_INCOMPLETE;
}
info->apn_enc = apn_enc = (uint8_t *) talloc_zero_size(g_hlr, apn_enc_len);
ret = info->apn_enc_len = osmo_apn_from_str(apn_enc, apn_enc_len, apn_name);
if (ret < 0) {
talloc_free(apn_enc);
info->apn_enc = NULL;
info->apn_enc_len = 0;
vty_out(vty, "Invalid APN name %s!", apn_name);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(cfg_no_ps_pdp_profile_apn, cfg_no_ps_pdp_profile_apn_cmd,
"no apn",
NO_STR
"Delete the APN.\n")
{
struct osmo_gsup_pdp_info *info = vty->index;
if (info->apn_enc) {
talloc_free((void *) info->apn_enc);
info->apn_enc = NULL;
info->apn_enc_len = 0;
}
return CMD_SUCCESS;
}
static void config_write_subscr_create_on_demand(struct vty *vty)
{
const uint8_t flags = g_hlr->subscr_create_on_demand.flags;
const char *flags_str;
switch (g_hlr->subscr_create_on_demand.mode) {
case SUBSCR_COD_MODE_MSISDN_FROM_IMSI:
vty_out(vty, " subscriber-create-on-demand msisdn-from-imsi");
break;
case SUBSCR_COD_MODE_RAND_MSISDN:
vty_out(vty, " subscriber-create-on-demand %u",
g_hlr->subscr_create_on_demand.rand_msisdn_len);
break;
case SUBSCR_COD_MODE_NO_MSISDN:
vty_out(vty, " subscriber-create-on-demand no-msisdn");
break;
case SUBSCR_COD_MODE_DISABLED:
default:
vty_out(vty, " no subscriber-create-on-demand%s", VTY_NEWLINE);
return;
}
if ((flags & DB_SUBSCR_FLAG_NAM_CS) && (flags & DB_SUBSCR_FLAG_NAM_PS)) if ((flags & DB_SUBSCR_FLAG_NAM_CS) && (flags & DB_SUBSCR_FLAG_NAM_PS))
flags_str = "cs+ps"; flags_str = "cs+ps";
@@ -310,37 +130,12 @@ static void config_write_subscr_create_on_demand(struct vty *vty)
flags_str = "cs"; flags_str = "cs";
else if (flags & DB_SUBSCR_FLAG_NAM_PS) else if (flags & DB_SUBSCR_FLAG_NAM_PS)
flags_str = "ps"; flags_str = "ps";
if (rand_msisdn_len)
vty_out(vty, " subscriber-create-on-demand %i %s%s", rand_msisdn_len, flags_str, VTY_NEWLINE);
else else
flags_str = "none"; vty_out(vty, " subscriber-create-on-demand no-msisdn %s%s", flags_str, VTY_NEWLINE);
vty_out(vty, " %s%s", flags_str, VTY_NEWLINE); }
}
static int config_write_hlr(struct vty *vty)
{
vty_out(vty, "hlr%s", VTY_NEWLINE);
if (g_hlr->reject_cause.cs != GMM_CAUSE_PLMN_NOTALLOWED)
vty_out(vty, " reject-cause not-found cs %s%s",
get_value_string_or_null(gsm48_gmm_cause_vty_names,
(uint32_t) g_hlr->reject_cause.cs), VTY_NEWLINE);
if (g_hlr->reject_cause.ps != GMM_CAUSE_PLMN_NOTALLOWED)
vty_out(vty, " reject-cause not-found ps %s%s",
get_value_string_or_null(gsm48_gmm_cause_vty_names,
(uint32_t) g_hlr->reject_cause.ps), VTY_NEWLINE);
if (g_hlr->no_proxy_reject_cause.cs != GMM_CAUSE_NET_FAIL)
vty_out(vty, " reject-cause no-proxy cs %s%s",
get_value_string_or_null(gsm48_gmm_cause_vty_names,
(uint32_t) g_hlr->no_proxy_reject_cause.cs), VTY_NEWLINE);
if (g_hlr->no_proxy_reject_cause.ps != GMM_CAUSE_NET_FAIL)
vty_out(vty, " reject-cause no-proxy ps %s%s",
get_value_string_or_null(gsm48_gmm_cause_vty_names,
(uint32_t) g_hlr->no_proxy_reject_cause.ps), VTY_NEWLINE);
if (g_hlr->store_imei)
vty_out(vty, " store-imei%s", VTY_NEWLINE);
if (g_hlr->db_file_path && strcmp(g_hlr->db_file_path, HLR_DEFAULT_DB_FILE_PATH))
vty_out(vty, " database %s%s", g_hlr->db_file_path, VTY_NEWLINE);
config_write_subscr_create_on_demand(vty);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@@ -354,37 +149,6 @@ static int config_write_hlr_gsup(struct vty *vty)
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static int config_write_hlr_ps(struct vty *vty)
{
vty_out(vty, " ps%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
static int config_write_hlr_ps_pdp_profiles(struct vty *vty)
{
char apn[APN_MAXLEN + 1] = {};
if (!g_hlr->ps.pdp_profile.enabled)
return CMD_SUCCESS;
vty_out(vty, " pdp-profiles default%s", VTY_NEWLINE);
for (int i = 0; i < g_hlr->ps.pdp_profile.num_pdp_infos; i++) {
struct osmo_gsup_pdp_info *pdp_info = &g_hlr->ps.pdp_profile.pdp_infos[i];
if (!pdp_info->context_id)
continue;
vty_out(vty, " profile %d%s", pdp_info->context_id, VTY_NEWLINE);
if (!pdp_info->have_info)
continue;
if (pdp_info->apn_enc && pdp_info->apn_enc_len) {
osmo_apn_to_str(apn, pdp_info->apn_enc, pdp_info->apn_enc_len);
vty_out(vty, " apn %s%s", apn, VTY_NEWLINE);
}
}
return CMD_SUCCESS;
}
static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn) static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn)
{ {
const struct ipa_server_conn *isc = conn->conn; const struct ipa_server_conn *isc = conn->conn;
@@ -448,6 +212,8 @@ DEFUN(cfg_hlr_gsup_ipa_name,
* USSD Entity * USSD Entity
***********************************************************************/ ***********************************************************************/
#include <osmocom/hlr/hlr_ussd.h>
#define USSD_STR "USSD Configuration\n" #define USSD_STR "USSD Configuration\n"
#define UROUTE_STR "Routing Configuration\n" #define UROUTE_STR "Routing Configuration\n"
#define PREFIX_STR "Prefix-Matching Route\n" "USSD Prefix\n" #define PREFIX_STR "Prefix-Matching Route\n" "USSD Prefix\n"
@@ -634,185 +400,21 @@ DEFUN(cfg_ncss_guard_timeout, cfg_ncss_guard_timeout_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
/***********************************************************************
* Routing of SM-RL to GSUP-attached SMSCs
***********************************************************************/
#define SMSC_STR "Configuration of GSUP routing to SMSCs\n"
struct cmd_node smsc_node = {
SMSC_NODE,
"%s(config-hlr-smsc)# ",
1,
};
DEFUN(cfg_smsc_entity, cfg_smsc_entity_cmd,
"smsc entity NAME",
SMSC_STR
"Configure a particular external SMSC\n"
"IPA name of the external SMSC\n")
{
struct hlr_smsc *smsc;
const char *id = argv[0];
smsc = smsc_find(g_hlr, id);
if (!smsc) {
smsc = smsc_alloc(g_hlr, id);
if (!smsc)
return CMD_WARNING;
}
vty->index = smsc;
vty->index_sub = &smsc->description;
vty->node = SMSC_NODE;
return CMD_SUCCESS;
}
DEFUN(cfg_no_smsc_entity, cfg_no_smsc_entity_cmd,
"no smsc entity NAME",
NO_STR SMSC_STR "Remove a particular external SMSC\n"
"IPA name of the external SMSC\n")
{
struct hlr_smsc *smsc = smsc_find(g_hlr, argv[0]);
if (!smsc) {
vty_out(vty, "%% Cannot remove non-existent SMSC %s%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
if (g_hlr->smsc_default == smsc) {
vty_out(vty,
"%% Cannot remove SMSC %s, it is the default route%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
smsc_free(smsc);
return CMD_SUCCESS;
}
DEFUN(cfg_smsc_route, cfg_smsc_route_cmd,
"smsc route NUMBER NAME",
SMSC_STR
"Configure GSUP route to a particular SMSC\n"
"Numeric address of this SMSC, must match EF.SMSP programming in SIMs\n"
"IPA name of the external SMSC\n")
{
struct hlr_smsc *smsc = smsc_find(g_hlr, argv[1]);
struct hlr_smsc_route *rt = smsc_route_find(g_hlr, argv[0]);
if (rt) {
vty_out(vty,
"%% Cannot add [another?] route for SMSC address %s%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
if (!smsc) {
vty_out(vty, "%% Cannot find SMSC '%s'%s", argv[1],
VTY_NEWLINE);
return CMD_WARNING;
}
smsc_route_alloc(g_hlr, argv[0], smsc);
return CMD_SUCCESS;
}
DEFUN(cfg_no_smsc_route, cfg_no_smsc_route_cmd,
"no smsc route NUMBER",
NO_STR SMSC_STR "Remove GSUP route to a particular SMSC\n"
"Numeric address of the SMSC\n")
{
struct hlr_smsc_route *rt = smsc_route_find(g_hlr, argv[0]);
if (!rt) {
vty_out(vty, "%% Cannot find route for SMSC address %s%s",
argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
smsc_route_free(rt);
return CMD_SUCCESS;
}
DEFUN(cfg_smsc_defroute, cfg_smsc_defroute_cmd,
"smsc default-route NAME",
SMSC_STR
"Configure default SMSC route for unknown SMSC numeric addresses\n"
"IPA name of the external SMSC\n")
{
struct hlr_smsc *smsc;
smsc = smsc_find(g_hlr, argv[0]);
if (!smsc) {
vty_out(vty, "%% Cannot find SMSC %s%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
if (g_hlr->smsc_default != smsc) {
vty_out(vty, "Switching default route from %s to %s%s",
g_hlr->smsc_default ? g_hlr->smsc_default->name : "<none>",
smsc->name, VTY_NEWLINE);
g_hlr->smsc_default = smsc;
}
return CMD_SUCCESS;
}
DEFUN(cfg_no_smsc_defroute, cfg_no_smsc_defroute_cmd,
"no smsc default-route",
NO_STR SMSC_STR
"Remove default SMSC route for unknown SMSC numeric addresses\n")
{
g_hlr->smsc_default = NULL;
return CMD_SUCCESS;
}
static void dump_one_smsc(struct vty *vty, struct hlr_smsc *smsc)
{
vty_out(vty, " smsc entity %s%s", smsc->name, VTY_NEWLINE);
}
static int config_write_smsc(struct vty *vty)
{
struct hlr_smsc *smsc;
struct hlr_smsc_route *rt;
llist_for_each_entry(smsc, &g_hlr->smsc_list, list)
dump_one_smsc(vty, smsc);
llist_for_each_entry(rt, &g_hlr->smsc_routes, list) {
vty_out(vty, " smsc route %s %s%s", rt->num_addr,
rt->smsc->name, VTY_NEWLINE);
}
if (g_hlr->smsc_default)
vty_out(vty, " smsc default-route %s%s",
g_hlr->smsc_default->name, VTY_NEWLINE);
return 0;
}
DEFUN(cfg_reject_cause, cfg_reject_cause_cmd, DEFUN(cfg_reject_cause, cfg_reject_cause_cmd,
"reject-cause TYPE CAUSE", "") /* Dynamically Generated */ "reject-cause TYPE CAUSE", "") /* Dynamically Generated */
{ {
int cause_code = get_string_value(gsm48_gmm_cause_vty_names, argv[2]); int cause_code = get_string_value(gsm48_gmm_cause_vty_names, argv[1]);
OSMO_ASSERT(cause_code >= 0); OSMO_ASSERT(cause_code >= 0);
if (strcmp(argv[0], "not-found") == 0) { if (strcmp(argv[0], "not-found") == 0)
if (strcmp(argv[1], "cs") == 0) g_hlr->reject_cause = (enum gsm48_gmm_cause) cause_code;
g_hlr->reject_cause.cs = (enum gsm48_gmm_cause) cause_code; if (strcmp(argv[0], "no-proxy") == 0)
else g_hlr->no_proxy_reject_cause = (enum gsm48_gmm_cause) cause_code;
g_hlr->reject_cause.ps = (enum gsm48_gmm_cause) cause_code;
}
if (strcmp(argv[0], "no-proxy") == 0) {
if (strcmp(argv[1], "cs") == 0)
g_hlr->no_proxy_reject_cause.cs = (enum gsm48_gmm_cause) cause_code;
else
g_hlr->no_proxy_reject_cause.ps = (enum gsm48_gmm_cause) cause_code;
}
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_store_imei, cfg_store_imei_cmd, DEFUN(cfg_store_imei, cfg_store_imei_cmd,
"store-imei", "store-imei",
"Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send" "Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send"
@@ -831,37 +433,29 @@ DEFUN(cfg_no_store_imei, cfg_no_store_imei_cmd,
} }
DEFUN(cfg_subscr_create_on_demand, cfg_subscr_create_on_demand_cmd, DEFUN(cfg_subscr_create_on_demand, cfg_subscr_create_on_demand_cmd,
"subscriber-create-on-demand (no-msisdn|msisdn-from-imsi|<3-15>) (none|cs|ps|cs+ps)", "subscriber-create-on-demand (no-msisdn|<3-15>) (none|cs|ps|cs+ps)",
"Make a new record when a subscriber is first seen.\n" "Make a new record when a subscriber is first seen.\n"
"Do not automatically assign MSISDN.\n" "Do not automatically assign MSISDN.\n"
"Assign MSISDN identical to subscriber's IMSI.\n"
"Length of an automatically assigned MSISDN.\n" "Length of an automatically assigned MSISDN.\n"
"Do not allow any NAM (Network Access Mode) by default.\n" "Do not allow any NAM (Network Access Mode) by default.\n"
"Allow access to circuit switched NAM by default.\n" "Allow access to circuit switched NAM by default.\n"
"Allow access to packet switched NAM by default.\n" "Allow access to packet switched NAM by default.\n"
"Allow access to circuit and packet switched NAM by default.\n") "Allow access to circuit and packet switched NAM by default.\n")
{ {
enum subscr_create_on_demand_mode mode;
unsigned int rand_msisdn_len = 0; unsigned int rand_msisdn_len = 0;
uint8_t flags = 0x00; uint8_t flags = 0x00;
if (strcmp(argv[0], "no-msisdn") == 0) { if (strcmp(argv[0], "no-msisdn") != 0)
mode = SUBSCR_COD_MODE_NO_MSISDN;
} else if (strcmp(argv[0], "msisdn-from-imsi") == 0) {
mode = SUBSCR_COD_MODE_MSISDN_FROM_IMSI;
} else { /* random MSISDN */
mode = SUBSCR_COD_MODE_RAND_MSISDN;
rand_msisdn_len = atoi(argv[0]); rand_msisdn_len = atoi(argv[0]);
}
if (strstr(argv[1], "cs")) if (strstr(argv[1], "cs"))
flags |= DB_SUBSCR_FLAG_NAM_CS; flags |= DB_SUBSCR_FLAG_NAM_CS;
if (strstr(argv[1], "ps")) if (strstr(argv[1], "ps"))
flags |= DB_SUBSCR_FLAG_NAM_PS; flags |= DB_SUBSCR_FLAG_NAM_PS;
g_hlr->subscr_create_on_demand.mode = mode; g_hlr->subscr_create_on_demand = true;
g_hlr->subscr_create_on_demand.rand_msisdn_len = rand_msisdn_len; g_hlr->subscr_create_on_demand_rand_msisdn_len = rand_msisdn_len;
g_hlr->subscr_create_on_demand.flags = flags; g_hlr->subscr_create_on_demand_flags = flags;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@@ -870,7 +464,7 @@ DEFUN(cfg_no_subscr_create_on_demand, cfg_no_subscr_create_on_demand_cmd,
"no subscriber-create-on-demand", "no subscriber-create-on-demand",
"Do not make a new record when a subscriber is first seen.\n") "Do not make a new record when a subscriber is first seen.\n")
{ {
g_hlr->subscr_create_on_demand.mode = SUBSCR_COD_MODE_DISABLED; g_hlr->subscr_create_on_demand = false;
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@@ -901,12 +495,24 @@ int hlr_vty_go_parent(struct vty *vty)
return vty->node; return vty->node;
} }
int hlr_vty_is_config_node(struct vty *vty, int node)
{
switch (node) {
/* add items that are not config */
case CONFIG_NODE:
return 0;
default:
return 1;
}
}
void hlr_vty_init(void *hlr_ctx) void hlr_vty_init(void *hlr_ctx)
{ {
cfg_reject_cause_cmd.string = cfg_reject_cause_cmd.string =
vty_cmd_string_from_valstr(hlr_ctx, vty_cmd_string_from_valstr(hlr_ctx,
gsm48_gmm_cause_vty_names, gsm48_gmm_cause_vty_names,
"reject-cause (not-found|no-proxy) (cs|ps) (", "|", ")", "reject-cause (not-found|no-proxy) (", "|", ")",
VTY_DO_LOWER); VTY_DO_LOWER);
cfg_reject_cause_cmd.doc = cfg_reject_cause_cmd.doc =
@@ -914,9 +520,7 @@ void hlr_vty_init(void *hlr_ctx)
gsm48_gmm_cause_vty_descs, gsm48_gmm_cause_vty_descs,
"GSUP/GMM cause to be sent\n" "GSUP/GMM cause to be sent\n"
"in the case the IMSI could not be found in the database\n" "in the case the IMSI could not be found in the database\n"
"in the case no remote HLR reponded to mslookup GSUP request\n" "in the case no remote HLR reponded to mslookup GSUP request\n",
"for CS domain\n"
"for PS domain\n",
"\n", "", 0); "\n", "", 0);
logging_vty_add_cmds(); logging_vty_add_cmds();
@@ -934,20 +538,6 @@ void hlr_vty_init(void *hlr_ctx)
install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd); install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd);
install_element(GSUP_NODE, &cfg_hlr_gsup_ipa_name_cmd); install_element(GSUP_NODE, &cfg_hlr_gsup_ipa_name_cmd);
/* PS */
install_node(&ps_node, config_write_hlr_ps);
install_element(HLR_NODE, &cfg_ps_cmd);
install_node(&ps_pdp_profiles_node, config_write_hlr_ps_pdp_profiles);
install_element(PS_NODE, &cfg_ps_pdp_profiles_cmd);
install_element(PS_NODE, &cfg_no_ps_pdp_profiles_cmd);
install_node(&ps_pdp_profiles_profile_node, NULL);
install_element(PS_PDP_PROFILES_NODE, &cfg_ps_pdp_profiles_profile_cmd);
install_element(PS_PDP_PROFILES_NODE, &cfg_no_ps_pdp_profiles_profile_cmd);
install_element(PS_PDP_PROFILES_PROFILE_NODE, &cfg_ps_pdp_profile_apn_cmd);
install_element(PS_PDP_PROFILES_PROFILE_NODE, &cfg_no_ps_pdp_profile_apn_cmd);
install_element(HLR_NODE, &cfg_database_cmd); install_element(HLR_NODE, &cfg_database_cmd);
install_element(HLR_NODE, &cfg_euse_cmd); install_element(HLR_NODE, &cfg_euse_cmd);
@@ -959,15 +549,6 @@ void hlr_vty_init(void *hlr_ctx)
install_element(HLR_NODE, &cfg_ussd_defaultroute_cmd); install_element(HLR_NODE, &cfg_ussd_defaultroute_cmd);
install_element(HLR_NODE, &cfg_ussd_no_defaultroute_cmd); install_element(HLR_NODE, &cfg_ussd_no_defaultroute_cmd);
install_element(HLR_NODE, &cfg_ncss_guard_timeout_cmd); install_element(HLR_NODE, &cfg_ncss_guard_timeout_cmd);
install_node(&smsc_node, config_write_smsc);
install_element(HLR_NODE, &cfg_smsc_entity_cmd);
install_element(HLR_NODE, &cfg_no_smsc_entity_cmd);
install_element(HLR_NODE, &cfg_smsc_route_cmd);
install_element(HLR_NODE, &cfg_no_smsc_route_cmd);
install_element(HLR_NODE, &cfg_smsc_defroute_cmd);
install_element(HLR_NODE, &cfg_no_smsc_defroute_cmd);
install_element(HLR_NODE, &cfg_reject_cause_cmd); install_element(HLR_NODE, &cfg_reject_cause_cmd);
install_element(HLR_NODE, &cfg_store_imei_cmd); install_element(HLR_NODE, &cfg_store_imei_cmd);
install_element(HLR_NODE, &cfg_no_store_imei_cmd); install_element(HLR_NODE, &cfg_no_store_imei_cmd);

View File

@@ -1,5 +1,5 @@
/* OsmoHLR subscriber management VTY implementation */ /* OsmoHLR subscriber management VTY implementation */
/* (C) 2017-2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> /* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
* All Rights Reserved * All Rights Reserved
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@@ -77,8 +77,8 @@ static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t
static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr) static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
{ {
int rc; int rc;
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE); vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE);
@@ -137,12 +137,12 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) { if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) {
vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE); vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE);
aud2g = (struct osmo_sub_auth_data2){}; aud2g = (struct osmo_sub_auth_data){};
} }
if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) { if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) {
vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE); vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE);
aud3g = (struct osmo_sub_auth_data2){}; aud3g = (struct osmo_sub_auth_data){};
} }
if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) { if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) {
@@ -154,10 +154,9 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) { if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) {
vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE); vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE);
vty_out(vty, " K=%s%s", vty_out(vty, " K=%s%s", hexdump_buf(aud3g.u.umts.k), VTY_NEWLINE);
osmo_hexdump_nospc(aud3g.u.umts.k, aud3g.u.umts.k_len), VTY_NEWLINE);
vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC", vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC",
osmo_hexdump_nospc(aud3g.u.umts.opc, aud3g.u.umts.opc_len), VTY_NEWLINE); hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE);
vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen); vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen);
if (aud3g.u.umts.sqn) if (aud3g.u.umts.sqn)
vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn); vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn);
@@ -182,11 +181,8 @@ static void subscr_dump_summary_vty(struct hlr_subscriber *subscr, void *data)
vty_out(vty," ------------- "); vty_out(vty," ------------- ");
} }
vty_out(vty, " %-2s%-2s ", subscr->nam_cs ? "CS" : "", subscr->nam_ps ? "PS" : ""); vty_out(vty, " %-2s%-2s ", subscr->nam_cs ? "CS" : "", subscr->nam_ps ? "PS" : "");
if (subscr->last_lu_seen) { if (subscr->last_lu_seen)
/* VLR Number is max length 32, possibly truncate here */
vty_out(vty, " %.22s ", subscr->vlr_number);
dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, true); dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, true);
}
vty_out_newline(vty); vty_out_newline(vty);
} }
@@ -221,8 +217,8 @@ static void dump_summary_table_vty(struct vty *vty, bool header, bool show_ls)
{ {
const char *texts = "ID MSISDN IMSI IMEI NAM"; const char *texts = "ID MSISDN IMSI IMEI NAM";
const char *lines = "----- ------------ ---------------- ---------------- -----"; const char *lines = "----- ------------ ---------------- ---------------- -----";
const char *ls_text = " VLR_NUMBER LAST SEEN "; const char *ls_text = " LAST SEEN";
const char *ls_line = " --------------------- ---------------------"; const char *ls_line = " ------------";
if (header) { if (header) {
if (!show_ls) if (!show_ls)
vty_out(vty, "%s%s%s%s", texts, VTY_NEWLINE, lines, VTY_NEWLINE); vty_out(vty, "%s%s%s%s", texts, VTY_NEWLINE, lines, VTY_NEWLINE);
@@ -464,27 +460,20 @@ static bool is_hexkey_valid(struct vty *vty, const char *label,
return false; return false;
} }
#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor-2g)" #define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor)"
#define AUTH_ALG_TYPES_2G_HELP \ #define AUTH_ALG_TYPES_2G_HELP \
"Use COMP128v1 algorithm\n" \ "Use COMP128v1 algorithm\n" \
"Use COMP128v2 algorithm\n" \ "Use COMP128v2 algorithm\n" \
"Use COMP128v3 algorithm\n" \ "Use COMP128v3 algorithm\n" \
"Use XOR-2G algorithm\n" "Use XOR algorithm\n"
#define AUTH_ALG_TYPES_3G "(milenage|tuak)" #define AUTH_ALG_TYPES_3G "milenage"
#define AUTH_ALG_TYPES_3G_HELP \ #define AUTH_ALG_TYPES_3G_HELP \
"Use Milenage algorithm\n" \ "Use Milenage algorithm\n"
"Use TUAK algorithm\n"
bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo, bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc) int *minlen, int *maxlen)
{ {
/* Default: no OP[c]. True for all 2G algorithms, and 3G-XOR. Overridden below for real 3G AKA algorithms. */
if (minlen_opc)
*minlen_opc = 0;
if (maxlen_opc)
*maxlen_opc = 0;
if (!strcasecmp(alg_str, "none")) { if (!strcasecmp(alg_str, "none")) {
*algo = OSMO_AUTH_ALG_NONE; *algo = OSMO_AUTH_ALG_NONE;
*minlen = *maxlen = 0; *minlen = *maxlen = 0;
@@ -497,28 +486,13 @@ bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
} else if (!strcasecmp(alg_str, "comp128v3")) { } else if (!strcasecmp(alg_str, "comp128v3")) {
*algo = OSMO_AUTH_ALG_COMP128v3; *algo = OSMO_AUTH_ALG_COMP128v3;
*minlen = *maxlen = A38_COMP128_KEY_LEN; *minlen = *maxlen = A38_COMP128_KEY_LEN;
} else if (!strcasecmp(alg_str, "xor-3g")) { } else if (!strcasecmp(alg_str, "xor")) {
*algo = OSMO_AUTH_ALG_XOR_3G; *algo = OSMO_AUTH_ALG_XOR;
*minlen = A38_XOR_MIN_KEY_LEN; *minlen = A38_XOR_MIN_KEY_LEN;
*maxlen = A38_XOR_MAX_KEY_LEN; *maxlen = A38_XOR_MAX_KEY_LEN;
} else if (!strcasecmp(alg_str, "xor-2g")) {
*algo = OSMO_AUTH_ALG_XOR_2G;
*minlen = *maxlen = A38_XOR2G_KEY_LEN;
} else if (!strcasecmp(alg_str, "milenage")) { } else if (!strcasecmp(alg_str, "milenage")) {
*algo = OSMO_AUTH_ALG_MILENAGE; *algo = OSMO_AUTH_ALG_MILENAGE;
*minlen = *maxlen = MILENAGE_KEY_LEN; *minlen = *maxlen = MILENAGE_KEY_LEN;
if (minlen_opc)
*minlen_opc = MILENAGE_KEY_LEN;
if (maxlen_opc)
*maxlen_opc = MILENAGE_KEY_LEN;
} else if (!strcasecmp(alg_str, "tuak")) {
*algo = OSMO_AUTH_ALG_TUAK;
*minlen = 16;
*maxlen = 32;
if (minlen_opc)
*minlen_opc = 32;
if (maxlen_opc)
*maxlen_opc = 32;
} else } else
return false; return false;
return true; return true;
@@ -574,7 +548,7 @@ DEFUN(subscriber_aud2g,
.u.gsm.ki = ki, .u.gsm.ki = ki,
}; };
if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) { if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE); vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }
@@ -633,21 +607,21 @@ DEFUN(subscriber_aud3g,
SUBSCR_UPDATE_HELP SUBSCR_UPDATE_HELP
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n" "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
AUTH_ALG_TYPES_3G_HELP AUTH_ALG_TYPES_3G_HELP
"Set Encryption Key K\n" "K as 32/64 hexadecimal characters\n" "Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
"Set OP key\n" "Set OPC key\n" "OP or OPC as 32/64 hexadecimal characters\n" "Set OP key\n" "Set OPC key\n" "OP or OPC as 32 hexadecimal characters\n"
"Set IND bit length\n" "IND bit length value (default: 5)\n") "Set IND bit length\n" "IND bit length value (default: 5)\n")
{ {
struct hlr_subscriber subscr; struct hlr_subscriber subscr;
int minlen = 0, minlen_opc = 0; int minlen = 0;
int maxlen = 0, maxlen_opc = 0; int maxlen = 0;
int rc; int rc;
const char *id_type = argv[0]; const char *id_type = argv[0];
const char *id = argv[1]; const char *id = argv[1];
const char *alg_type = argv[2]; const char *alg_type = AUTH_ALG_TYPES_3G;
const char *k = argv[3]; const char *k = argv[2];
bool opc_is_op = (strcasecmp("op", argv[4]) == 0); bool opc_is_op = (strcasecmp("op", argv[3]) == 0);
const char *op_opc = argv[5]; const char *op_opc = argv[4];
int ind_bitlen = argc > 7 ? atoi(argv[7]) : 5; int ind_bitlen = argc > 6? atoi(argv[6]) : 5;
struct sub_auth_data_str aud3g = { struct sub_auth_data_str aud3g = {
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.u.umts = { .u.umts = {
@@ -658,7 +632,7 @@ DEFUN(subscriber_aud3g,
}, },
}; };
if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) { if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE); vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }
@@ -666,7 +640,8 @@ DEFUN(subscriber_aud3g,
if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen)) if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
return CMD_WARNING; return CMD_WARNING;
if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc, minlen_opc, maxlen_opc)) if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc,
MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
return CMD_WARNING; return CMD_WARNING;
if (get_subscr_by_argv(vty, id_type, id, &subscr)) if (get_subscr_by_argv(vty, id_type, id, &subscr))
@@ -684,11 +659,11 @@ DEFUN(subscriber_aud3g,
DEFUN(subscriber_aud3g_xor, DEFUN(subscriber_aud3g_xor,
subscriber_aud3g_xor_cmd, subscriber_aud3g_xor_cmd,
SUBSCR_UPDATE "aud3g xor-3g k K" SUBSCR_UPDATE "aud3g xor k K"
" [ind-bitlen] [<0-28>]", " [ind-bitlen] [<0-28>]",
SUBSCR_UPDATE_HELP SUBSCR_UPDATE_HELP
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n" "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
"Use XOR-3G algorithm\n" "Use XOR algorithm\n"
"Set Encryption Key K\n" "K as 32 hexadecimal characters\n" "Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
"Set IND bit length\n" "IND bit length value (default: 5)\n") "Set IND bit length\n" "IND bit length value (default: 5)\n")
{ {
@@ -710,8 +685,8 @@ DEFUN(subscriber_aud3g_xor,
}, },
}; };
if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen, NULL, NULL)) { if (!auth_algo_parse("xor", &aud3g.algo, &minlen, &maxlen)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor-3g", VTY_NEWLINE); vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor", VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }

View File

@@ -136,8 +136,7 @@ static void lu_start(struct osmo_gsup_req *update_location_req)
} }
if (db_subscr_get_by_imsi(g_hlr->dbc, update_location_req->gsup.imsi, &lu->subscr) < 0) { if (db_subscr_get_by_imsi(g_hlr->dbc, update_location_req->gsup.imsi, &lu->subscr) < 0) {
lu_failure(lu, (lu->is_ps) ? g_hlr->reject_cause.ps : g_hlr->reject_cause.cs, lu_failure(lu, g_hlr->reject_cause, "Subscriber does not exist");
"Subscriber does not exist");
return; return;
} }
@@ -242,11 +241,13 @@ static void lu_fsm_wait_insert_data_result_onenter(struct osmo_fsm_inst *fi, uin
struct lu *lu = fi->priv; struct lu *lu = fi->priv;
struct hlr_subscriber *subscr = &lu->subscr; struct hlr_subscriber *subscr = &lu->subscr;
struct osmo_gsup_message gsup; struct osmo_gsup_message gsup;
uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
uint8_t apn[APN_MAXLEN];
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi,
subscr->msisdn, subscr->msisdn, msisdn_enc, sizeof(msisdn_enc),
lu->is_ps ? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS, apn, sizeof(apn),
OTC_SELECT)) { lu->is_ps? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS)) {
lu_failure(lu, GMM_CAUSE_NET_FAIL, "cannot encode Insert Subscriber Data message"); lu_failure(lu, GMM_CAUSE_NET_FAIL, "cannot encode Insert Subscriber Data message");
return; return;
} }
@@ -276,7 +277,6 @@ void lu_fsm_wait_insert_data_result(struct osmo_fsm_inst *fi, uint32_t event, vo
case OSMO_GSUP_MSGT_INSERT_DATA_ERROR: case OSMO_GSUP_MSGT_INSERT_DATA_ERROR:
lu_failure(lu, GMM_CAUSE_NET_FAIL, "Rx %s", osmo_gsup_message_type_name(req->gsup.message_type)); lu_failure(lu, GMM_CAUSE_NET_FAIL, "Rx %s", osmo_gsup_message_type_name(req->gsup.message_type));
osmo_gsup_req_free(req);
break; break;
default: default:

View File

@@ -1,7 +1,7 @@
# This is _NOT_ the library release version, it's an API version. # This is _NOT_ the library release version, it's an API version.
# Please read chapter "Library interface versions" of the libtool documentation # Please read chapter "Library interface versions" of the libtool documentation
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
LIBVERSION=1:1:0 LIBVERSION=1:0:0
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include
AM_CFLAGS = -fPIC -Wall $(PCSC_CFLAGS) $(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS) AM_CFLAGS = -fPIC -Wall $(PCSC_CFLAGS) $(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS)

View File

@@ -45,7 +45,6 @@ static char *domain_from_query(void *ctx, const struct osmo_mslookup_query *quer
/* Get id from query */ /* Get id from query */
switch (query->id.type) { switch (query->id.type) {
case OSMO_MSLOOKUP_ID_IMSI: case OSMO_MSLOOKUP_ID_IMSI:
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
id = query->id.imsi; id = query->id.imsi;
break; break;
case OSMO_MSLOOKUP_ID_MSISDN: case OSMO_MSLOOKUP_ID_MSISDN:

View File

@@ -91,7 +91,6 @@ const struct value_string osmo_mslookup_id_type_names[] = {
{ OSMO_MSLOOKUP_ID_NONE, "none" }, { OSMO_MSLOOKUP_ID_NONE, "none" },
{ OSMO_MSLOOKUP_ID_IMSI, "imsi" }, { OSMO_MSLOOKUP_ID_IMSI, "imsi" },
{ OSMO_MSLOOKUP_ID_MSISDN, "msisdn" }, { OSMO_MSLOOKUP_ID_MSISDN, "msisdn" },
{ OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED, "imsiauth" },
{} {}
}; };
@@ -135,7 +134,6 @@ bool osmo_mslookup_id_valid(const struct osmo_mslookup_id *id)
{ {
switch (id->type) { switch (id->type) {
case OSMO_MSLOOKUP_ID_IMSI: case OSMO_MSLOOKUP_ID_IMSI:
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
return osmo_imsi_str_valid(id->imsi); return osmo_imsi_str_valid(id->imsi);
case OSMO_MSLOOKUP_ID_MSISDN: case OSMO_MSLOOKUP_ID_MSISDN:
return osmo_msisdn_str_valid(id->msisdn); return osmo_msisdn_str_valid(id->msisdn);
@@ -159,7 +157,6 @@ size_t osmo_mslookup_id_name_buf(char *buf, size_t buflen, const struct osmo_msl
struct osmo_strbuf sb = { .buf = buf, .len = buflen }; struct osmo_strbuf sb = { .buf = buf, .len = buflen };
switch (id->type) { switch (id->type) {
case OSMO_MSLOOKUP_ID_IMSI: case OSMO_MSLOOKUP_ID_IMSI:
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
OSMO_STRBUF_PRINTF(sb, "%s", id->imsi); OSMO_STRBUF_PRINTF(sb, "%s", id->imsi);
break; break;
case OSMO_MSLOOKUP_ID_MSISDN: case OSMO_MSLOOKUP_ID_MSISDN:
@@ -301,7 +298,6 @@ int osmo_mslookup_query_init_from_domain_str(struct osmo_mslookup_query *q, cons
id = second_last_dot + 1; id = second_last_dot + 1;
switch (q->id.type) { switch (q->id.type) {
case OSMO_MSLOOKUP_ID_IMSI: case OSMO_MSLOOKUP_ID_IMSI:
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
rc = token(q->id.imsi, sizeof(q->id.imsi), id, last_dot); rc = token(q->id.imsi, sizeof(q->id.imsi), id, last_dot);
if (rc) if (rc)
return rc; return rc;

View File

@@ -154,20 +154,16 @@ void osmo_mslookup_client_rx_result(struct osmo_mslookup_client *client, uint32_
if (result->rc != OSMO_MSLOOKUP_RC_RESULT) if (result->rc != OSMO_MSLOOKUP_RC_RESULT)
return; return;
/* If the client wants to see all results, send this result now */
if (req->handling.search_all && result->age > 0)
req->handling.result_cb(client, request_handle, &req->query, result);
/* If we already stored an earlier successful result, keep that if its age is younger. */ /* If we already stored an earlier successful result, keep that if its age is younger. */
if (req->result.rc == OSMO_MSLOOKUP_RC_RESULT if (req->result.rc == OSMO_MSLOOKUP_RC_RESULT
&& result->age > req->result.age) && result->age >= req->result.age)
return; return;
req->result = *result; req->result = *result;
/* If age == 0, it doesn't get any better, so return the result immediately. */ /* If age == 0, it doesn't get any better, so return the result immediately. */
if (req->result.age == 0) { if (req->result.age == 0) {
osmo_mslookup_request_send_result(req, !req->handling.search_all); osmo_mslookup_request_send_result(req, true);
return; return;
} }

View File

@@ -133,10 +133,6 @@ CSV_HEADERS "\n"
" 1000-5000@sip.voice.123.msisdn Same, but silent for first second\n" " 1000-5000@sip.voice.123.msisdn Same, but silent for first second\n"
" 10000-@smpp.sms.567.msisdn Return 1 result after 10 seconds\n" " 10000-@smpp.sms.567.msisdn Return 1 result after 10 seconds\n"
"\n" "\n"
"--search-all -A\n"
" Do not stop when a response with age of zero comes in.\n"
" This can be used to \"search\" the entire dGSM network if for\n"
" example there is a need to track down so-called \"evil twin\" hlr entries.\n"
"--format -f csv (default)\n" "--format -f csv (default)\n"
" Format result lines in CSV format.\n" " Format result lines in CSV format.\n"
"--no-csv-headers -H\n" "--no-csv-headers -H\n"
@@ -200,7 +196,6 @@ enum result_format {
}; };
static struct { static struct {
bool search_all;
bool daemon; bool daemon;
struct osmo_sockaddr_str mdns_addr; struct osmo_sockaddr_str mdns_addr;
uint32_t min_delay; uint32_t min_delay;
@@ -424,9 +419,9 @@ static void socket_client_close(struct socket_client *c)
{ {
struct osmo_fd *ofd = &c->ofd; struct osmo_fd *ofd = &c->ofd;
osmo_fd_unregister(ofd);
close(ofd->fd); close(ofd->fd);
ofd->fd = -1; ofd->fd = -1;
osmo_fd_unregister(ofd);
llist_del(&c->entry); llist_del(&c->entry);
talloc_free(c); talloc_free(c);
@@ -434,11 +429,7 @@ static void socket_client_close(struct socket_client *c)
void socket_client_respond_result(struct socket_client *c, const char *response) void socket_client_respond_result(struct socket_client *c, const char *response)
{ {
size_t len = strlen(response); write(c->ofd.fd, response, strlen(response));
int rc = write(c->ofd.fd, response, len);
if (rc != len)
print_error("%s: write() returned %d instead of %zu\n", __func__, rc, len);
} }
static int socket_read_cb(struct osmo_fd *ofd) static int socket_read_cb(struct osmo_fd *ofd)
@@ -535,13 +526,8 @@ int socket_accept(struct osmo_fd *ofd, unsigned int flags)
llist_add(&c->entry, &globals.socket_clients); llist_add(&c->entry, &globals.socket_clients);
if (globals.format == FORMAT_CSV && cmdline_opts.csv_headers) { if (globals.format == FORMAT_CSV && cmdline_opts.csv_headers)
size_t len = strlen(CSV_HEADERS); write(c->ofd.fd, CSV_HEADERS, strlen(CSV_HEADERS));
int rc = write(c->ofd.fd, CSV_HEADERS, strlen(CSV_HEADERS));
if (rc != len)
print_error("%s: write() returned %d instead of %zu\n", __func__, rc, len);
}
return 0; return 0;
} }
@@ -575,9 +561,9 @@ void socket_close(void)
llist_for_each_entry_safe(c, n, &globals.socket_clients, entry) llist_for_each_entry_safe(c, n, &globals.socket_clients, entry)
socket_client_close(c); socket_client_close(c);
if (osmo_fd_is_registered(&globals.socket_ofd)) { if (osmo_fd_is_registered(&globals.socket_ofd)) {
osmo_fd_unregister(&globals.socket_ofd);
close(globals.socket_ofd.fd); close(globals.socket_ofd.fd);
globals.socket_ofd.fd = -1; globals.socket_ofd.fd = -1;
osmo_fd_unregister(&globals.socket_ofd);
} }
} }
@@ -642,7 +628,6 @@ void start_query_str(const char *query_str)
const char *domain_str = query_str; const char *domain_str = query_str;
char *at; char *at;
struct osmo_mslookup_query_handling h = { struct osmo_mslookup_query_handling h = {
.search_all = cmdline_opts.search_all,
.min_wait_milliseconds = cmdline_opts.min_delay, .min_wait_milliseconds = cmdline_opts.min_delay,
.result_timeout_milliseconds = cmdline_opts.timeout, .result_timeout_milliseconds = cmdline_opts.timeout,
.result_cb = mslookup_result_cb, .result_cb = mslookup_result_cb,
@@ -745,7 +730,6 @@ int main(int argc, char **argv)
int option_index = 0; int option_index = 0;
static struct option long_options[] = { static struct option long_options[] = {
{ "search-all", 0, 0, 'A' },
{ "format", 1, 0, 'f' }, { "format", 1, 0, 'f' },
{ "no-csv-headers", 0, 0, 'H' }, { "no-csv-headers", 0, 0, 'H' },
{ "daemon", 0, 0, 'd' }, { "daemon", 0, 0, 'd' },
@@ -771,15 +755,12 @@ int main(int argc, char **argv)
} \ } \
} while (0) } while (0)
c = getopt_long(argc, argv, "Af:Hdm:M:D:t:T:s:SqhV", long_options, &option_index); c = getopt_long(argc, argv, "f:Hdm:M:D:t:T:s:SqhV", long_options, &option_index);
if (c == -1) if (c == -1)
break; break;
switch (c) { switch (c) {
case 'A':
cmdline_opts.search_all = true;
break;
case 'f': case 'f':
cmdline_opts.format_str = optarg; cmdline_opts.format_str = optarg;
break; break;

View File

@@ -192,37 +192,12 @@ static void mslookup_server_rx_hlr_gsup(const struct osmo_mslookup_query *query,
{ {
const struct mslookup_service_host *host; const struct mslookup_service_host *host;
int rc; int rc;
bool exists = false;
bool auth_imsi_only = false;
bool created_on_demand = false;
switch (query->id.type) { switch (query->id.type) {
case OSMO_MSLOOKUP_ID_IMSI_AUTHORIZED:
auth_imsi_only = true;
case OSMO_MSLOOKUP_ID_IMSI: case OSMO_MSLOOKUP_ID_IMSI:
/* Entries that have been created by subscriber create on demand
will have default msisdn length. and will not have any vlr_number entry.
We should not answer for these, unless they have CS/PS service. */
if (g_hlr->mslookup.ignore_created_on_demand) {
rc = db_subscr_is_created_on_demand_by_imsi(g_hlr->dbc, query->id.imsi,
g_hlr->subscr_create_on_demand.rand_msisdn_len);
if (!rc) {
exists = true;
created_on_demand = true;
rc = -ENOENT;
break;
}
}
rc = db_subscr_exists_by_imsi(g_hlr->dbc, query->id.imsi); rc = db_subscr_exists_by_imsi(g_hlr->dbc, query->id.imsi);
if (g_hlr->mslookup.auth_imsi_only || auth_imsi_only) {
if (!rc)
exists = true;
rc = db_subscr_authorized_by_imsi(g_hlr->dbc, query->id.imsi);
}
break; break;
case OSMO_MSLOOKUP_ID_MSISDN: case OSMO_MSLOOKUP_ID_MSISDN:
rc = db_subscr_exists_by_msisdn(g_hlr->dbc, query->id.msisdn); rc = db_subscr_exists_by_msisdn(g_hlr->dbc, query->id.msisdn);
/* FIXME: The log message below might not match */
break; break;
default: default:
LOGP(DMSLOOKUP, LOGL_ERROR, "Unknown mslookup ID type: %d\n", query->id.type); LOGP(DMSLOOKUP, LOGL_ERROR, "Unknown mslookup ID type: %d\n", query->id.type);
@@ -231,11 +206,8 @@ static void mslookup_server_rx_hlr_gsup(const struct osmo_mslookup_query *query,
} }
if (rc) { if (rc) {
LOGP(DMSLOOKUP, LOGL_DEBUG, "%s: %s%s%s in local HLR\n", LOGP(DMSLOOKUP, LOGL_DEBUG, "%s: does not exist in local HLR\n",
osmo_mslookup_result_name_c(OTC_SELECT, query, NULL), osmo_mslookup_result_name_c(OTC_SELECT, query, NULL));
(exists) ? "exists but" : "does not exist",
(created_on_demand) ? " is created on demand and since untouched" : "",
(exists && !created_on_demand) ? " is not authorized" : "");
*result = not_found; *result = not_found;
return; return;
} }

View File

@@ -92,11 +92,7 @@ static void proxy_pending_req_remote_hlr_connect_result(struct osmo_gsup_req *re
osmo_gsup_req_respond(req, &gsup_reply, false, true); osmo_gsup_req_respond(req, &gsup_reply, false, true);
return; return;
} }
osmo_gsup_req_respond_err(req, g_hlr->no_proxy_reject_cause,
osmo_gsup_req_respond_err(req,
(req->gsup.cn_domain == OSMO_GSUP_CN_DOMAIN_CS) ?
g_hlr->no_proxy_reject_cause.cs :
g_hlr->no_proxy_reject_cause.ps,
"Proxy: Failed to connect to home HLR"); "Proxy: Failed to connect to home HLR");
return; return;
} }
@@ -117,19 +113,6 @@ static bool proxy_deferred_gsup_req_waiting(struct proxy *proxy, const char *ims
return false; return false;
} }
struct osmo_gsup_req *proxy_deferred_gsup_req_get_by_imsi(struct proxy *proxy, const char *imsi)
{
struct proxy_pending_gsup_req *p;
OSMO_ASSERT(imsi);
llist_for_each_entry(p, &proxy->pending_gsup_reqs, entry) {
if (strcmp(p->req->gsup.imsi, imsi))
continue;
return p->req;
}
return NULL;
}
/* Result of looking for remote HLR. If it failed, pass remote_hlr as NULL. On failure, the remote_hlr may be passed /* Result of looking for remote HLR. If it failed, pass remote_hlr as NULL. On failure, the remote_hlr may be passed
* NULL. */ * NULL. */
static void proxy_deferred_gsup_req_pop(struct proxy *proxy, const char *imsi, struct remote_hlr *remote_hlr) static void proxy_deferred_gsup_req_pop(struct proxy *proxy, const char *imsi, struct remote_hlr *remote_hlr)

View File

@@ -20,7 +20,7 @@
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/gsup.h> #include <osmocom/gsm/gsup.h>
#include <osmocom/gsm/gsm23003.h> #include <osmocom/gsm/gsm23003.h>
#include <osmocom/gsm/ipa.h> #include <osmocom/abis/ipa.h>
#include <osmocom/gsupclient/gsup_client.h> #include <osmocom/gsupclient/gsup_client.h>
#include <osmocom/hlr/logging.h> #include <osmocom/hlr/logging.h>
#include <osmocom/hlr/hlr.h> #include <osmocom/hlr/hlr.h>
@@ -66,7 +66,7 @@ static void remote_hlr_err_reply(struct remote_hlr *rh, const struct osmo_gsup_m
* The local MSC shall be indicated by gsup.destination_name. */ * The local MSC shall be indicated by gsup.destination_name. */
static int remote_hlr_rx(struct osmo_gsup_client *gsupc, struct msgb *msg) static int remote_hlr_rx(struct osmo_gsup_client *gsupc, struct msgb *msg)
{ {
struct remote_hlr *rh = osmo_gsup_client_get_data(gsupc); struct remote_hlr *rh = gsupc->data;
struct proxy_subscr proxy_subscr; struct proxy_subscr proxy_subscr;
struct osmo_gsup_message gsup; struct osmo_gsup_message gsup;
int rc; int rc;
@@ -108,7 +108,7 @@ struct remote_hlr_pending_up {
static bool remote_hlr_up_down(struct osmo_gsup_client *gsupc, bool up) static bool remote_hlr_up_down(struct osmo_gsup_client *gsupc, bool up)
{ {
struct remote_hlr *remote_hlr = osmo_gsup_client_get_data(gsupc); struct remote_hlr *remote_hlr = gsupc->data;
struct remote_hlr_pending_up *p, *n; struct remote_hlr_pending_up *p, *n;
if (!up) { if (!up) {
LOG_REMOTE_HLR(remote_hlr, LOGL_NOTICE, "link to remote HLR is down, removing GSUP client\n"); LOG_REMOTE_HLR(remote_hlr, LOGL_NOTICE, "link to remote HLR is down, removing GSUP client\n");
@@ -127,7 +127,7 @@ static bool remote_hlr_up_down(struct osmo_gsup_client *gsupc, bool up)
bool remote_hlr_is_up(struct remote_hlr *remote_hlr) bool remote_hlr_is_up(struct remote_hlr *remote_hlr)
{ {
return remote_hlr && remote_hlr->gsupc && osmo_gsup_client_is_connected(remote_hlr->gsupc); return remote_hlr && remote_hlr->gsupc && remote_hlr->gsupc->is_connected;
} }
struct remote_hlr *remote_hlr_get_or_connect(const struct osmo_sockaddr_str *addr, bool connect, struct remote_hlr *remote_hlr_get_or_connect(const struct osmo_sockaddr_str *addr, bool connect,
@@ -180,7 +180,7 @@ struct remote_hlr *remote_hlr_get_or_connect(const struct osmo_sockaddr_str *add
return NULL; return NULL;
} }
osmo_gsup_client_set_data(rh->gsupc, rh); rh->gsupc->data = rh;
llist_add(&rh->entry, &remote_hlrs); llist_add(&rh->entry, &remote_hlrs);
add_result_cb: add_result_cb:

View File

@@ -2,12 +2,12 @@ SUBDIRS = gen_ts_55_205_test_sets
AM_CPPFLAGS = \ AM_CPPFLAGS = \
$(all_includes) \ $(all_includes) \
-I$(top_srcdir)/include \
$(NULL) $(NULL)
AM_CFLAGS = \ AM_CFLAGS = \
-Wall \ -Wall \
-ggdb3 \ -ggdb3 \
-I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \ $(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \ $(LIBOSMOGSM_CFLAGS) \
$(NULL) $(NULL)
@@ -30,8 +30,8 @@ auc_test_SOURCES = \
$(NULL) $(NULL)
auc_test_LDADD = \ auc_test_LDADD = \
$(top_builddir)/src/auc.o \ $(top_srcdir)/src/auc.c \
$(top_builddir)/src/logging.o \ $(top_srcdir)/src/logging.c \
$(LIBOSMOCORE_LIBS) \ $(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \ $(LIBOSMOGSM_LIBS) \
$(NULL) $(NULL)
@@ -41,8 +41,8 @@ auc_ts_55_205_test_sets_SOURCES = \
$(NULL) $(NULL)
auc_ts_55_205_test_sets_LDADD = \ auc_ts_55_205_test_sets_LDADD = \
$(top_builddir)/src/auc.o \ $(top_srcdir)/src/auc.c \
$(top_builddir)/src/logging.o \ $(top_srcdir)/src/logging.c \
$(LIBOSMOCORE_LIBS) \ $(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \ $(LIBOSMOGSM_LIBS) \
$(NULL) $(NULL)

View File

@@ -116,14 +116,14 @@ int rand_get(uint8_t *rand, unsigned int len)
/* Subscriber with 2G-only (COMP128v1) authentication data */ /* Subscriber with 2G-only (COMP128v1) authentication data */
static void test_gen_vectors_2g_only(void) static void test_gen_vectors_2g_only(void)
{ {
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
int rc; int rc;
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data2){ aud2g = (struct osmo_sub_auth_data){
.type = OSMO_AUTH_TYPE_GSM, .type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_COMP128v1, .algo = OSMO_AUTH_ALG_COMP128v1,
}; };
@@ -131,7 +131,7 @@ static void test_gen_vectors_2g_only(void)
osmo_hexparse("EB215756028D60E3275E613320AEC880", osmo_hexparse("EB215756028D60E3275E613320AEC880",
aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki)); aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
aud3g = (struct osmo_sub_auth_data2){ 0 }; aud3g = (struct osmo_sub_auth_data){ 0 };
next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true); next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
@@ -179,14 +179,14 @@ static void test_gen_vectors_2g_only(void)
* reflects the default configuration of sysmoUSIM-SJS1 */ * reflects the default configuration of sysmoUSIM-SJS1 */
static void test_gen_vectors_2g_plus_3g(void) static void test_gen_vectors_2g_plus_3g(void)
{ {
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
int rc; int rc;
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data2){ aud2g = (struct osmo_sub_auth_data){
.type = OSMO_AUTH_TYPE_GSM, .type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_COMP128v1, .algo = OSMO_AUTH_ALG_COMP128v1,
}; };
@@ -194,11 +194,9 @@ static void test_gen_vectors_2g_plus_3g(void)
osmo_hexparse("EB215756028D60E3275E613320AEC880", osmo_hexparse("EB215756028D60E3275E613320AEC880",
aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki)); aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
aud3g = (struct osmo_sub_auth_data2){ aud3g = (struct osmo_sub_auth_data){
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 31, .u.umts.sqn = 31,
}; };
@@ -294,8 +292,8 @@ void _test_gen_vectors_3g_only__expect_vecs(struct osmo_auth_vector vecs[3])
* tuples are suitable for both 2G and 3G authentication */ * tuples are suitable for both 2G and 3G authentication */
static void test_gen_vectors_3g_only(void) static void test_gen_vectors_3g_only(void)
{ {
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
struct osmo_auth_vector vecs[3]; struct osmo_auth_vector vecs[3];
uint8_t auts[14]; uint8_t auts[14];
@@ -304,13 +302,11 @@ static void test_gen_vectors_3g_only(void)
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data2){ 0 }; aud2g = (struct osmo_sub_auth_data){ 0 };
aud3g = (struct osmo_sub_auth_data2){ aud3g = (struct osmo_sub_auth_data){
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 31, .u.umts.sqn = 31,
}; };
@@ -470,20 +466,18 @@ static void test_gen_vectors_3g_only(void)
* 2G and 3G authentication */ * 2G and 3G authentication */
static void test_gen_vectors_3g_xor(void) static void test_gen_vectors_3g_xor(void)
{ {
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
int rc; int rc;
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data2){ 0 }; aud2g = (struct osmo_sub_auth_data){ 0 };
aud3g = (struct osmo_sub_auth_data2){ aud3g = (struct osmo_sub_auth_data){
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_XOR_3G, .algo = OSMO_AUTH_ALG_XOR,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 0, .u.umts.sqn = 0,
}; };
@@ -523,43 +517,39 @@ void test_gen_vectors_bad_args(void)
int rc; int rc;
int i; int i;
struct osmo_sub_auth_data2 aud2g = { struct osmo_sub_auth_data aud2g = {
.type = OSMO_AUTH_TYPE_GSM, .type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_COMP128v1, .algo = OSMO_AUTH_ALG_COMP128v1,
}; };
struct osmo_sub_auth_data2 aud3g = { struct osmo_sub_auth_data aud3g = {
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
}; };
struct osmo_sub_auth_data2 aud2g_noalg = { struct osmo_sub_auth_data aud2g_noalg = {
.type = OSMO_AUTH_TYPE_GSM, .type = OSMO_AUTH_TYPE_GSM,
.algo = OSMO_AUTH_ALG_NONE, .algo = OSMO_AUTH_ALG_NONE,
}; };
struct osmo_sub_auth_data2 aud3g_noalg = { struct osmo_sub_auth_data aud3g_noalg = {
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_NONE, .algo = OSMO_AUTH_ALG_NONE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
}; };
struct osmo_sub_auth_data2 aud_notype = { struct osmo_sub_auth_data aud_notype = {
.type = OSMO_AUTH_TYPE_NONE, .type = OSMO_AUTH_TYPE_NONE,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
}; };
struct osmo_sub_auth_data2 no_aud = { struct osmo_sub_auth_data no_aud = {
.type = OSMO_AUTH_TYPE_NONE, .type = OSMO_AUTH_TYPE_NONE,
.algo = OSMO_AUTH_ALG_NONE, .algo = OSMO_AUTH_ALG_NONE,
}; };
struct { struct {
struct osmo_sub_auth_data2 *aud2g; struct osmo_sub_auth_data *aud2g;
struct osmo_sub_auth_data2 *aud3g; struct osmo_sub_auth_data *aud3g;
uint8_t *rand_auts; uint8_t *rand_auts;
uint8_t *auts; uint8_t *auts;
const char *label; const char *label;

View File

@@ -24,20 +24,18 @@
static void {func_name}(void) static void {func_name}(void)
{{ {{
struct osmo_sub_auth_data2 aud2g; struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data2 aud3g; struct osmo_sub_auth_data aud3g;
struct osmo_auth_vector vec; struct osmo_auth_vector vec;
int rc; int rc;
comment_start(); comment_start();
aud2g = (struct osmo_sub_auth_data2){{ 0 }}; aud2g = (struct osmo_sub_auth_data){{ 0 }};
aud3g = (struct osmo_sub_auth_data2){{ aud3g = (struct osmo_sub_auth_data){{
.type = OSMO_AUTH_TYPE_UMTS, .type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_MILENAGE, .algo = OSMO_AUTH_ALG_MILENAGE,
.u.umts.k_len = 16,
.u.umts.opc_len = 16,
.u.umts.sqn = 31, .u.umts.sqn = 31,
}}; }};
@@ -50,7 +48,6 @@ static void {func_name}(void)
fake_rand, sizeof(fake_rand)); fake_rand, sizeof(fake_rand));
vec = (struct osmo_auth_vector){{ {{0}} }}; vec = (struct osmo_auth_vector){{ {{0}} }};
vec.res_len = 8;
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64); VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL); rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
VERBOSE_ASSERT(rc, == 1, "%d"); VERBOSE_ASSERT(rc, == 1, "%d");

View File

@@ -1,10 +1,7 @@
AM_CPPFLAGS = \ AM_CFLAGS = \
$(all_includes) \ $(all_includes) \
-I$(top_srcdir)/include \ -I$(top_srcdir)/include \
-I$(top_builddir)/include \ -I$(top_builddir)/include \
$(NULL)
AM_CFLAGS = \
-Wall \ -Wall \
-ggdb3 \ -ggdb3 \
$(LIBOSMOCORE_CFLAGS) \ $(LIBOSMOCORE_CFLAGS) \

View File

@@ -122,16 +122,16 @@ static void _fill_invalid(void *dest, size_t size)
/* Not linking the real auc_compute_vectors(), just returning num_vec. /* Not linking the real auc_compute_vectors(), just returning num_vec.
* This gets called by db_get_auc(), but we're only interested in its rc. */ * This gets called by db_get_auc(), but we're only interested in its rc. */
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec, int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
struct osmo_sub_auth_data2 *aud2g, struct osmo_sub_auth_data *aud2g,
struct osmo_sub_auth_data2 *aud3g, struct osmo_sub_auth_data *aud3g,
const uint8_t *rand_auts, const uint8_t *auts) const uint8_t *rand_auts, const uint8_t *auts)
{ return num_vec; } { return num_vec; }
static struct db_context *dbc = NULL; static struct db_context *dbc = NULL;
static void *ctx = NULL; static void *ctx = NULL;
static struct hlr_subscriber g_subscr; static struct hlr_subscriber g_subscr;
static struct osmo_sub_auth_data2 g_aud2g; static struct osmo_sub_auth_data g_aud2g;
static struct osmo_sub_auth_data2 g_aud3g; static struct osmo_sub_auth_data g_aud3g;
static int g_rc; static int g_rc;
static int64_t g_id; static int64_t g_id;
@@ -180,21 +180,18 @@ void dump_subscr(struct hlr_subscriber *subscr)
#undef Pb #undef Pb
} }
void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud) void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
{ {
if (aud->type == OSMO_AUTH_TYPE_NONE) { if (aud->type == OSMO_AUTH_TYPE_NONE) {
fprintf(stderr, "%s: none\n", label); fprintf(stderr, "%s: none\n", label);
return; return;
} }
fprintf(stderr, "%s: struct osmo_sub_auth_data2 {\n", label); fprintf(stderr, "%s: struct osmo_sub_auth_data {\n", label);
#define Pf(name, fmt) \ #define Pf(name, fmt) \
Pfo(name, fmt, aud) Pfo(name, fmt, aud)
#define Phex(name) \ #define Phex(name) \
Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name))) Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name)))
#define Phexl(name, len) \
Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, aud->len))
Pfv(type, "%s", osmo_sub_auth_type_name(aud->type)); Pfv(type, "%s", osmo_sub_auth_type_name(aud->type));
Pfv(algo, "%s", osmo_auth_alg_name(aud->algo)); Pfv(algo, "%s", osmo_auth_alg_name(aud->algo));
@@ -203,9 +200,9 @@ void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
Phex(u.gsm.ki); Phex(u.gsm.ki);
break; break;
case OSMO_AUTH_TYPE_UMTS: case OSMO_AUTH_TYPE_UMTS:
Phexl(u.umts.opc, u.umts.opc_len); Phex(u.umts.opc);
Pf(u.umts.opc_is_op, "%u"); Pf(u.umts.opc_is_op, "%u");
Phexl(u.umts.k, u.umts.k_len); Phex(u.umts.k);
Phex(u.umts.amf); Phex(u.umts.amf);
if (aud->u.umts.sqn) { if (aud->u.umts.sqn) {
Pf(u.umts.sqn, "%"PRIu64); Pf(u.umts.sqn, "%"PRIu64);
@@ -222,7 +219,6 @@ void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
#undef Pf #undef Pf
#undef Phex #undef Phex
#undef Phexl
} }
void db_raw_sql(struct db_context *dbc, const char *sql) void db_raw_sql(struct db_context *dbc, const char *sql)
@@ -590,7 +586,7 @@ static void test_subscr_aud(void)
ASSERT_SEL_AUD(imsi0, 0, id); ASSERT_SEL_AUD(imsi0, 0, id);
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id, ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")), mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
0); 0);
ASSERT_SEL_AUD(imsi0, 0, id); ASSERT_SEL_AUD(imsi0, 0, id);
@@ -608,7 +604,7 @@ static void test_subscr_aud(void)
-ENOENT); -ENOENT);
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id, ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")), mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
0); 0);
ASSERT_SEL_AUD(imsi0, 0, id); ASSERT_SEL_AUD(imsi0, 0, id);
@@ -711,12 +707,12 @@ static void test_subscr_aud(void)
ASSERT_SEL_AUD(imsi0, 0, id); ASSERT_SEL_AUD(imsi0, 0, id);
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id, ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f000000000000f00000000000f000000f00000000")), mk_aud_2g(OSMO_AUTH_ALG_XOR, "f000000000000f00000000000f000000f00000000")),
-EINVAL); -EINVAL);
ASSERT_SEL_AUD(imsi0, 0, id); ASSERT_SEL_AUD(imsi0, 0, id);
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id, ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f00")), mk_aud_2g(OSMO_AUTH_ALG_XOR, "f00")),
-EINVAL); -EINVAL);
ASSERT_SEL_AUD(imsi0, 0, id); ASSERT_SEL_AUD(imsi0, 0, id);

View File

@@ -824,7 +824,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "01234567
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v1, .algo = COMP128v1,
.u.gsm.ki = '0123456789abcdef0123456789abcdef', .u.gsm.ki = '0123456789abcdef0123456789abcdef',
@@ -841,7 +841,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "01234567
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v1, .algo = COMP128v1,
.u.gsm.ki = '0123456789abcdef0123456789abcdef', .u.gsm.ki = '0123456789abcdef0123456789abcdef',
@@ -853,7 +853,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v2, "BeadedBe
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v2, .algo = COMP128v2,
.u.gsm.ki = 'beadedbeeaced1ebbeddefacedfacade', .u.gsm.ki = 'beadedbeeaced1ebbeddefacedfacade',
@@ -865,21 +865,21 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v3, "DeafBedd
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'deafbeddedbabeacceededfadeddecaf', .u.gsm.ki = 'deafbeddedbabeacceededfadeddecaf',
} }
3G: none 3G: none
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")) --> 0 db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")) --> 0
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = XOR-2G, .algo = XOR,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: none 3G: none
@@ -900,14 +900,14 @@ DAUC IMSI='123456789000000': No 3G Auth Data
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)) --> -ENOENT db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)) --> -ENOENT
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")) --> 0 db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")) --> 0
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = XOR-2G, .algo = XOR,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: none 3G: none
@@ -932,7 +932,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -954,7 +954,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -970,7 +970,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'deaf0ff1ced0d0dabbedd1ced1cef00d', .u.umts.opc = 'deaf0ff1ced0d0dabbedd1ced1cef00d',
@@ -985,7 +985,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1001,7 +1001,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'cededeffacedacefacedbadfadedbeef', .u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
@@ -1033,7 +1033,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'cededeffacedacefacedbadfadedbeef', .u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
@@ -1069,12 +1069,12 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_3g(OSMO_AUTH_ALG_MILENAGE, "BeefedCaf
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1097,12 +1097,12 @@ DAUC Cannot update auth tokens: Unknown auth algo: 99999
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1112,17 +1112,17 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
.u.umts.ind_bitlen = 5, .u.umts.ind_bitlen = 5,
} }
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f000000000000f00000000000f000000f00000000")) --> -EINVAL db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "f000000000000f00000000000f000000f00000000")) --> -EINVAL
DAUC Cannot update auth tokens: Invalid KI: 'f000000000000f00000000000f000000f00000000' DAUC Cannot update auth tokens: Invalid KI: 'f000000000000f00000000000f000000f00000000'
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1132,17 +1132,17 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
.u.umts.ind_bitlen = 5, .u.umts.ind_bitlen = 5,
} }
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f00")) --> -EINVAL db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "f00")) --> -EINVAL
DAUC Cannot update auth tokens: Invalid KI: 'f00' DAUC Cannot update auth tokens: Invalid KI: 'f00'
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1157,12 +1157,12 @@ DAUC Cannot update auth tokens: auth algo not suited for 2G: MILENAGE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1177,12 +1177,12 @@ DAUC Cannot update auth tokens: Invalid OP/OPC: '0f000000000000f00000000000f0000
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1197,12 +1197,12 @@ DAUC Cannot update auth tokens: Invalid K: '000000000000f00000000000f000000'
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1217,12 +1217,12 @@ DAUC Cannot update auth tokens: Invalid ind_bitlen: 29
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1237,12 +1237,12 @@ DAUC Cannot update auth tokens: Invalid OP/OPC: 'X000000000000f00000000000f00000
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1257,12 +1257,12 @@ DAUC Cannot update auth tokens: Invalid K: 'f000000000000 f00000000000 f000000'
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
2G: struct osmo_sub_auth_data2 { 2G: struct osmo_sub_auth_data {
.type = GSM, .type = GSM,
.algo = COMP128v3, .algo = COMP128v3,
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef', .u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
} }
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1338,7 +1338,7 @@ sqlite3_prepare_v2(dbc->db, sql, -1, &stmt, NULL) --> SQLITE_OK
sqlite3_step(stmt) --> SQLITE_DONE sqlite3_step(stmt) --> SQLITE_DONE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -ENOKEY db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -ENOKEY
DAUC IMSI='123456789000000': Error reading Ki, expected min length 16 but has length 15 DAUC IMSI='123456789000000': Error reading Ki, expected length 16 but has length 15
DAUC IMSI='123456789000000': No 3G Auth Data DAUC IMSI='123456789000000': No 3G Auth Data
@@ -1359,7 +1359,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
DAUC IMSI='123456789000000': Error reading K, expected min length 16 but has length 15 DAUC IMSI='123456789000000': Error reading K, expected length 16 but has length 15
@@ -1374,7 +1374,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
DAUC IMSI='123456789000000': Error reading OP, expected min length 16 but has length 15 DAUC IMSI='123456789000000': Error reading OP, expected length 16 but has length 15
@@ -1389,7 +1389,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5 db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
DAUC IMSI='123456789000000': Error reading OPC, expected min length 16 but has length 15 DAUC IMSI='123456789000000': Error reading OPC, expected length 16 but has length 15
@@ -1458,7 +1458,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1477,7 +1477,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1495,7 +1495,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1513,7 +1513,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1534,7 +1534,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1550,7 +1550,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1568,7 +1568,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
@@ -1586,7 +1586,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
DAUC IMSI='123456789000000': No 2G Auth Data DAUC IMSI='123456789000000': No 2G Auth Data
2G: none 2G: none
3G: struct osmo_sub_auth_data2 { 3G: struct osmo_sub_auth_data {
.type = UMTS, .type = UMTS,
.algo = MILENAGE, .algo = MILENAGE,
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee', .u.umts.opc = 'beefedcafefaceacedaddeddecadefee',

View File

@@ -43,5 +43,5 @@ OsmoHLR# subscriber imsi 5555555 create
MSISDN: none MSISDN: none
OsmoHLR# subscriber imsi 5555555 update msisdn 55555555555555 OsmoHLR# subscriber imsi 5555555 update msisdn 55555555555555
% Updated subscriber IMSI='5555555' to MSISDN='55555555555555' % Updated subscriber IMSI='5555555' to MSISDN='55555555555555'
OsmoHLR# subscriber imsi 5555555 update aud2g xor-2g ki 55555555555555555555555555555555 OsmoHLR# subscriber imsi 5555555 update aud2g xor ki 55555555555555555555555555555555
OsmoHLR# subscriber imsi 5555555 update aud3g milenage k 55555555555555555555555555555555 opc 55555555555555555555555555555555 OsmoHLR# subscriber imsi 5555555 update aud3g milenage k 55555555555555555555555555555555 opc 55555555555555555555555555555555

View File

@@ -12,7 +12,7 @@ Table auc_2g contents:
algo_id_2g|ki|subscriber_id algo_id_2g|ki|subscriber_id
1|BeefedCafeFaceAcedAddedDecadeFee|1 1|BeefedCafeFaceAcedAddedDecadeFee|1
2|33333333333333333333333333333333|4 2|33333333333333333333333333333333|4
6|55555555555555555555555555555555|6 4|55555555555555555555555555555555|6
Table: auc_3g Table: auc_3g
name|type|notnull|dflt_value|pk name|type|notnull|dflt_value|pk
@@ -86,7 +86,6 @@ DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 3
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 4 DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 4
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 5 DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 5
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 6 DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 6
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 7
DMAIN Cmdline option --db-check: Database was opened successfully, quitting. DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
Resulting db: Resulting db:
@@ -101,15 +100,15 @@ Table auc_2g contents:
algo_id_2g|ki|subscriber_id algo_id_2g|ki|subscriber_id
1|BeefedCafeFaceAcedAddedDecadeFee|1 1|BeefedCafeFaceAcedAddedDecadeFee|1
2|33333333333333333333333333333333|4 2|33333333333333333333333333333333|4
6|55555555555555555555555555555555|6 4|55555555555555555555555555555555|6
Table: auc_3g Table: auc_3g
name|type|notnull|dflt_value|pk name|type|notnull|dflt_value|pk
algo_id_3g|INTEGER|1||0 algo_id_3g|INTEGER|1||0
ind_bitlen|INTEGER|1|5|0 ind_bitlen|INTEGER|1|5|0
k|VARCHAR(64)|1||0 k|VARCHAR(32)|1||0
op|VARCHAR(64)|0||0 op|VARCHAR(32)|0||0
opc|VARCHAR(64)|0||0 opc|VARCHAR(32)|0||0
sqn|INTEGER|1|0|0 sqn|INTEGER|1|0|0
subscriber_id|INTEGER|0||1 subscriber_id|INTEGER|0||1
@@ -180,5 +179,5 @@ osmo-hlr --database $db --db-check --config-file $srcdir/osmo-hlr.cfg
rc = 0 rc = 0
DMAIN hlr starting DMAIN hlr starting
DDB using database: <PATH>test.db DDB using database: <PATH>test.db
DDB Database <PATH>test.db' has HLR DB schema version 7 DDB Database <PATH>test.db' has HLR DB schema version 6
DMAIN Cmdline option --db-check: Database was opened successfully, quitting. DMAIN Cmdline option --db-check: Database was opened successfully, quitting.

View File

@@ -61,7 +61,7 @@ CREATE TABLE auc_2g (
); );
INSERT INTO auc_2g VALUES(1,1,'BeefedCafeFaceAcedAddedDecadeFee'); INSERT INTO auc_2g VALUES(1,1,'BeefedCafeFaceAcedAddedDecadeFee');
INSERT INTO auc_2g VALUES(4,2,'33333333333333333333333333333333'); INSERT INTO auc_2g VALUES(4,2,'33333333333333333333333333333333');
INSERT INTO auc_2g VALUES(6,6,'55555555555555555555555555555555'); INSERT INTO auc_2g VALUES(6,4,'55555555555555555555555555555555');
CREATE TABLE auc_3g ( CREATE TABLE auc_3g (
subscriber_id INTEGER PRIMARY KEY, -- subscriber.id subscriber_id INTEGER PRIMARY KEY, -- subscriber.id
algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value

View File

@@ -1,9 +1,9 @@
AM_CPPFLAGS = \ AM_CPPFLAGS = \
$(all_includes) \ $(all_includes) \
-I$(top_srcdir)/include \
$(NULL) $(NULL)
AM_CFLAGS = \ AM_CFLAGS = \
-I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \ $(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \ $(LIBOSMOGSM_CFLAGS) \
$(NULL) $(NULL)

View File

@@ -1,11 +1,11 @@
AM_CPPFLAGS = \ AM_CPPFLAGS = \
$(all_includes) \ $(all_includes) \
-I$(top_srcdir)/include \
$(NULL) $(NULL)
AM_CFLAGS = \ AM_CFLAGS = \
-Wall \ -Wall \
-ggdb3 \ -ggdb3 \
-I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \ $(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOGSM_CFLAGS) \ $(LIBOSMOGSM_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \ $(LIBOSMOABIS_CFLAGS) \

View File

@@ -47,14 +47,12 @@ OsmoHLR(config-hlr)# ?
no Negate a command or set its defaults no Negate a command or set its defaults
ussd USSD Configuration ussd USSD Configuration
ncss-guard-timeout Set guard timer for NCSS (call independent SS) session activity ncss-guard-timeout Set guard timer for NCSS (call independent SS) session activity
smsc Configuration of GSUP routing to SMSCs
reject-cause GSUP/GMM cause to be sent reject-cause GSUP/GMM cause to be sent
store-imei Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send Check IMEI requests (for OsmoMSC, you may want to set 'check-imei-rqd 1'). store-imei Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send Check IMEI requests (for OsmoMSC, you may want to set 'check-imei-rqd 1').
subscriber-create-on-demand Make a new record when a subscriber is first seen. subscriber-create-on-demand Make a new record when a subscriber is first seen.
OsmoHLR(config-hlr)# list OsmoHLR(config-hlr)# list
... ...
gsup gsup
ps
database PATH database PATH
euse NAME euse NAME
no euse NAME no euse NAME
@@ -64,16 +62,10 @@ OsmoHLR(config-hlr)# list
ussd default-route external EUSE ussd default-route external EUSE
no ussd default-route no ussd default-route
ncss-guard-timeout <0-255> ncss-guard-timeout <0-255>
smsc entity NAME
no smsc entity NAME
smsc route NUMBER NAME
no smsc route NUMBER
smsc default-route NAME
no smsc default-route
reject-cause (not-found|no-proxy) (imsi-unknown|illegal-ms|plmn-not-allowed|la-not-allowed|roaming-not-allowed|no-suitable-cell-in-la|net-fail|congestion|auth-unacceptable|proto-error-unspec) reject-cause (not-found|no-proxy) (imsi-unknown|illegal-ms|plmn-not-allowed|la-not-allowed|roaming-not-allowed|no-suitable-cell-in-la|net-fail|congestion|auth-unacceptable|proto-error-unspec)
store-imei store-imei
no store-imei no store-imei
subscriber-create-on-demand (no-msisdn|msisdn-from-imsi|<3-15>) (none|cs|ps|cs+ps) subscriber-create-on-demand (no-msisdn|<3-15>) (none|cs|ps|cs+ps)
no subscriber-create-on-demand no subscriber-create-on-demand
OsmoHLR(config-hlr)# gsup OsmoHLR(config-hlr)# gsup
@@ -113,22 +105,13 @@ log stderr
logging level dgsm notice logging level dgsm notice
... ...
hlr hlr
reject-cause not-found plmn-not-allowed
reject-cause no-proxy net-fail
store-imei store-imei
database hlr_vty_test.db database hlr_vty_test.db
no subscriber-create-on-demand
gsup gsup
bind ip 127.0.0.1 bind ip 127.0.0.1
ipa-name unnamed-HLR ipa-name unnamed-HLR
ussd route prefix *#100# internal own-msisdn ussd route prefix *#100# internal own-msisdn
ussd route prefix *#101# internal own-imsi ussd route prefix *#101# internal own-imsi
ps
pdp-profiles default
profile 1
apn internet
profile 2
apn *
end end
OsmoHLR# configure terminal OsmoHLR# configure terminal
@@ -465,44 +448,3 @@ mslookup
client client
mdns bind 239.192.23.42 4266 mdns bind 239.192.23.42 4266
... ...
OsmoHLR(config-mslookup-server)# end
OsmoHLR# configure terminal
OsmoHLR(config)# hlr
OsmoHLR(config-hlr)# ps?
ps Configure the PS options
OsmoHLR(config-hlr)# ps
OsmoHLR(config-hlr-ps)# list
...
pdp-profiles default
no pdp-profiles default
...
OsmoHLR(config-hlr-ps)# no pdp-profiles default
OsmoHLR(config-hlr-ps)# pdp-profiles default
OsmoHLR(config-hlr-ps-pdp-profiles)# ?
...
profile Configure a PDP profile
...
OsmoHLR(config-hlr-ps-pdp-profiles)# profile 1
OsmoHLR(config-hlr-ps-pdp-profile)# ?
...
apn Configure the APN.
...
OsmoHLR(config-hlr-ps-pdp-profile)# apn internet
OsmoHLR(config-hlr-ps-pdp-profile)# exit
OsmoHLR(config-hlr-ps-pdp-profiles)# profile 2
OsmoHLR(config-hlr-ps-pdp-profile)# apn *
OsmoHLR(config-hlr-ps-pdp-profile)# show running-config
...
ps
pdp-profiles default
profile 1
apn internet
profile 2
apn *
...

View File

@@ -10,14 +10,6 @@ hlr
subscriber-create-on-demand no-msisdn none subscriber-create-on-demand no-msisdn none
... ...
OsmoHLR(config-hlr)# subscriber-create-on-demand msisdn-from-imsi cs+ps
OsmoHLR(config-hlr)# show running-config
...
hlr
...
subscriber-create-on-demand msisdn-from-imsi cs+ps
...
OsmoHLR(config-hlr)# subscriber-create-on-demand 3 none OsmoHLR(config-hlr)# subscriber-create-on-demand 3 none
OsmoHLR(config-hlr)# show running-config OsmoHLR(config-hlr)# show running-config
... ...

View File

@@ -674,12 +674,9 @@ lmsi 00000000
GET 112 subscriber.by-imsi-901991234567891.aud2g GET 112 subscriber.by-imsi-901991234567891.aud2g
GET_REPLY 112 subscriber.by-imsi-901991234567891.aud2g none GET_REPLY 112 subscriber.by-imsi-901991234567891.aud2g none
SET 113 subscriber.by-imsi-901991234567891.aud2g xor-2g,c01ffedc1cadaeac1d1f1edacac1ab0a SET 113 subscriber.by-imsi-901991234567891.aud2g xor,c01ffedc1cadaeac1d1f1edacac1ab0a
SET_REPLY 113 subscriber.by-imsi-901991234567891.aud2g OK SET_REPLY 113 subscriber.by-imsi-901991234567891.aud2g OK
GET 114 subscriber.by-imsi-901991234567891.aud2g
GET_REPLY 114 subscriber.by-imsi-901991234567891.aud2g XOR-2G,c01ffedc1cadaeac1d1f1edacac1ab0a
SET 115 subscriber.by-imsi-901991234567891.aud2g none SET 115 subscriber.by-imsi-901991234567891.aud2g none
SET_REPLY 115 subscriber.by-imsi-901991234567891.aud2g OK SET_REPLY 115 subscriber.by-imsi-901991234567891.aud2g OK

View File

@@ -8,10 +8,10 @@ OsmoHLR# list
subscriber (imsi|msisdn|id|imei) IDENT delete subscriber (imsi|msisdn|id|imei) IDENT delete
subscriber (imsi|msisdn|id|imei) IDENT update msisdn (none|MSISDN) subscriber (imsi|msisdn|id|imei) IDENT update msisdn (none|MSISDN)
subscriber (imsi|msisdn|id|imei) IDENT update aud2g none subscriber (imsi|msisdn|id|imei) IDENT update aud2g none
subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor-2g) ki KI subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor) ki KI
subscriber (imsi|msisdn|id|imei) IDENT update aud3g none subscriber (imsi|msisdn|id|imei) IDENT update aud3g none
subscriber (imsi|msisdn|id|imei) IDENT update aud3g (milenage|tuak) k K (op|opc) OP_C [ind-bitlen] [<0-28>] subscriber (imsi|msisdn|id|imei) IDENT update aud3g milenage k K (op|opc) OP_C [ind-bitlen] [<0-28>]
subscriber (imsi|msisdn|id|imei) IDENT update aud3g xor-3g k K [ind-bitlen] [<0-28>] subscriber (imsi|msisdn|id|imei) IDENT update aud3g xor k K [ind-bitlen] [<0-28>]
subscriber (imsi|msisdn|id|imei) IDENT update imei (none|IMEI) subscriber (imsi|msisdn|id|imei) IDENT update imei (none|IMEI)
subscriber (imsi|msisdn|id|imei) IDENT update network-access-mode (none|cs|ps|cs+ps) subscriber (imsi|msisdn|id|imei) IDENT update network-access-mode (none|cs|ps|cs+ps)
show mslookup services show mslookup services
@@ -144,7 +144,7 @@ OsmoHLR# subscriber imsi 123456789023000 update aud2g ?
comp128v1 Use COMP128v1 algorithm comp128v1 Use COMP128v1 algorithm
comp128v2 Use COMP128v2 algorithm comp128v2 Use COMP128v2 algorithm
comp128v3 Use COMP128v3 algorithm comp128v3 Use COMP128v3 algorithm
xor-2g Use XOR-2G algorithm xor Use XOR algorithm
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ? OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ?
ki Set Ki Encryption Key ki Set Ki Encryption Key
@@ -155,12 +155,12 @@ OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki ?
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki val ? OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki val ?
<cr> <cr>
OsmoHLR# subscriber imsi 123456789023000 update aud2g xor-2g ki Deaf0ff1ceD0d0DabbedD1ced1ceF00d OsmoHLR# subscriber imsi 123456789023000 update aud2g xor ki Deaf0ff1ceD0d0DabbedD1ced1ceF00d
OsmoHLR# subscriber imsi 123456789023000 show OsmoHLR# subscriber imsi 123456789023000 show
ID: 101 ID: 101
IMSI: 123456789023000 IMSI: 123456789023000
MSISDN: 423 MSISDN: 423
2G auth: XOR-2G ...
KI=deaf0ff1ced0d0dabbedd1ced1cef00d KI=deaf0ff1ced0d0dabbedd1ced1cef00d
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki BeefedCafeFaceAcedAddedDecadeFee OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki BeefedCafeFaceAcedAddedDecadeFee
@@ -241,7 +241,7 @@ OsmoHLR# subscriber id 101 show
2G auth: COMP128v3 2G auth: COMP128v3
KI=c01ffedc1cadaeac1d1f1edacac1ab0a KI=c01ffedc1cadaeac1d1f1edacac1ab0a
OsmoHLR# subscriber id 101 update aud2g xor-2g ki CoiffedCicadaeAcidifiedAcaciaBoa OsmoHLR# subscriber id 101 update aud2g xor ki CoiffedCicadaeAcidifiedAcaciaBoa
% Invalid value for KI: 'CoiffedCicadaeAcidifiedAcaciaBoa' % Invalid value for KI: 'CoiffedCicadaeAcidifiedAcaciaBoa'
OsmoHLR# subscriber id 101 show OsmoHLR# subscriber id 101 show
ID: 101 ID: 101
@@ -250,7 +250,7 @@ OsmoHLR# subscriber id 101 show
2G auth: COMP128v3 2G auth: COMP128v3
KI=c01ffedc1cadaeac1d1f1edacac1ab0a KI=c01ffedc1cadaeac1d1f1edacac1ab0a
OsmoHLR# subscriber id 101 update aud2g xor-2g ki C01ffedC1cadaeAc1d1f1edAcac1aB0aX OsmoHLR# subscriber id 101 update aud2g xor ki C01ffedC1cadaeAc1d1f1edAcac1aB0aX
% Invalid value for KI: 'C01ffedC1cadaeAc1d1f1edAcac1aB0aX' % Invalid value for KI: 'C01ffedC1cadaeAc1d1f1edAcac1aB0aX'
OsmoHLR# subscriber id 101 show OsmoHLR# subscriber id 101 show
ID: 101 ID: 101
@@ -269,21 +269,20 @@ OsmoHLR# subscriber id 101 show
OsmoHLR# subscriber imsi 123456789023000 update aud3g ? OsmoHLR# subscriber imsi 123456789023000 update aud3g ?
none Delete 3G authentication data none Delete 3G authentication data
milenage Use Milenage algorithm milenage Use Milenage algorithm
tuak Use TUAK algorithm xor Use XOR algorithm
xor-3g Use XOR-3G algorithm
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage ? OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage ?
k Set Encryption Key K k Set Encryption Key K
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k ? OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k ?
K K as 32/64 hexadecimal characters K K as 32 hexadecimal characters
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d ? OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d ?
op Set OP key op Set OP key
opc Set OPC key opc Set OPC key
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc ? OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc ?
OP_C OP or OPC as 32/64 hexadecimal characters OP_C OP or OPC as 32 hexadecimal characters
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc CededEffacedAceFacedBadFadedBeef ? OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc CededEffacedAceFacedBadFadedBeef ?
[ind-bitlen] Set IND bit length [ind-bitlen] Set IND bit length

View File

@@ -130,7 +130,7 @@ ERROR 54 Value failed verification.
SET 55 subscriber.by-imsi-901990000000003.aud2g foobar,2134 SET 55 subscriber.by-imsi-901990000000003.aud2g foobar,2134
ERROR 55 Unknown auth algorithm. ERROR 55 Unknown auth algorithm.
SET 56 subscriber.by-imsi-901990000000003.aud2g xor-2g,2134 SET 56 subscriber.by-imsi-901990000000003.aud2g xor,2134
ERROR 56 Invalid KI. ERROR 56 Invalid KI.
SET 57 subscriber.by-imsi-901990000000003.aud3g foobar SET 57 subscriber.by-imsi-901990000000003.aud3g foobar
@@ -139,17 +139,17 @@ ERROR 57 Value failed verification.
SET 58 subscriber.by-imsi-901990000000003.aud3g foobar,2134 SET 58 subscriber.by-imsi-901990000000003.aud3g foobar,2134
ERROR 58 Unknown auth algorithm. ERROR 58 Unknown auth algorithm.
SET 59 subscriber.by-imsi-901990000000003.aud3g milenage,2134 SET 60 subscriber.by-imsi-901990000000003.aud3g milenage,2134
ERROR 59 Invalid KI. ERROR 60 Invalid KI.
SET 60 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,AAA SET 61 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,AAA
ERROR 60 Invalid format.
SET 61 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC
ERROR 61 Invalid format. ERROR 61 Invalid format.
SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,zzz SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC
ERROR 62 Invalid OP/OPC. ERROR 62 Invalid format.
SET 63 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308, SET 63 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,zzz
ERROR 63 Invalid format. ERROR 63 Invalid OP/OPC.
SET 64 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,
ERROR 64 Invalid format.

View File

@@ -27,7 +27,12 @@ AT_KEYWORDS([db])
cat $abs_srcdir/db/db_test.ok > expout cat $abs_srcdir/db/db_test.ok > expout
cat $abs_srcdir/db/db_test.err > experr cat $abs_srcdir/db/db_test.err > experr
sqlite3 db_test.db < $abs_top_srcdir/sql/hlr.sql sqlite3 db_test.db < $abs_top_srcdir/sql/hlr.sql
AT_CHECK([$abs_top_builddir/tests/db/db_test], [], [expout], [experr])
# Compatibility with libosmocore I446e54d0ddf4a18c46ee022b1249af73552e3ce1
$abs_top_builddir/tests/db/db_test >out 2>err
sed -i "s/XOR-3G,/XOR,/g" err
AT_CHECK([cat out; cat err >&2], [], [expout], [experr])
AT_CLEANUP AT_CLEANUP
# AT_SKIP_IF: disable for old sqlite versions, because the way we dump tables in the test doesn't work with it. # AT_SKIP_IF: disable for old sqlite versions, because the way we dump tables in the test doesn't work with it.