mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr.git
synced 2025-11-02 21:23:30 +00:00
Compare commits
2 Commits
1.7.0
...
neels/for_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
472bb0733d | ||
|
|
d118efb789 |
17
.gitignore
vendored
17
.gitignore
vendored
@@ -26,7 +26,6 @@ m4
|
|||||||
*.m4
|
*.m4
|
||||||
missing
|
missing
|
||||||
.deps
|
.deps
|
||||||
*~
|
|
||||||
|
|
||||||
*.pc
|
*.pc
|
||||||
.libs
|
.libs
|
||||||
@@ -70,19 +69,3 @@ doc/manuals/common
|
|||||||
doc/manuals/build
|
doc/manuals/build
|
||||||
|
|
||||||
contrib/osmo-hlr.spec
|
contrib/osmo-hlr.spec
|
||||||
/debian/.debhelper/
|
|
||||||
/debian/libosmo-gsup-client-dev/
|
|
||||||
/debian/files
|
|
||||||
/debian/autoreconf.after
|
|
||||||
/debian/autoreconf.before
|
|
||||||
/debian/libosmo-gsup-client0/
|
|
||||||
/debian/libosmo-mslookup0/
|
|
||||||
/debian/osmo-hlr-dbg/
|
|
||||||
/debian/tmp/
|
|
||||||
/doc/manuals/vty/hlr_vty_reference.xml
|
|
||||||
/debian/libosmo-mslookup-dev/
|
|
||||||
/debian/osmo-hlr-doc/
|
|
||||||
/debian/osmo-hlr/
|
|
||||||
/debian/osmo-mslookup-utils/
|
|
||||||
/debian/*.log
|
|
||||||
/debian/*.substvars
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
AUTOMAKE_OPTIONS = foreign dist-bzip2
|
AUTOMAKE_OPTIONS = foreign dist-bzip2
|
||||||
|
|
||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
|
doc \
|
||||||
src \
|
src \
|
||||||
include \
|
include \
|
||||||
doc \
|
|
||||||
sql \
|
sql \
|
||||||
contrib \
|
contrib \
|
||||||
tests \
|
tests \
|
||||||
|
|||||||
65
README.md
65
README.md
@@ -1,65 +0,0 @@
|
|||||||
osmo-hlr - Osmocom HLR Implementation
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
This repository contains a C-language implementation of a GSM Home
|
|
||||||
Location Register (HLR). It is part of the
|
|
||||||
[Osmocom](https://osmocom.org/) Open Source Mobile Communications
|
|
||||||
project.
|
|
||||||
|
|
||||||
Warning: While the HLR logical functionality is implemented, OsmoHLR
|
|
||||||
does not use the ETSI/3GPP TCAP/MAP protocol stack. Instead, a much
|
|
||||||
simpler custom protocol (GSUP) is used. This means, OsmoHLR is of
|
|
||||||
no use outside the context of an Osmocom core network. You can use
|
|
||||||
it with OsmoMSC, OsmoSGSN etc. - but not with third party components.
|
|
||||||
|
|
||||||
Homepage
|
|
||||||
--------
|
|
||||||
|
|
||||||
The official homepage of the project is
|
|
||||||
https://osmocom.org/projects/osmo-hlr/wiki
|
|
||||||
|
|
||||||
GIT Repository
|
|
||||||
--------------
|
|
||||||
|
|
||||||
You can clone from the official osmo-hlr.git repository using
|
|
||||||
|
|
||||||
git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
|
|
||||||
|
|
||||||
There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr>
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
-------------
|
|
||||||
|
|
||||||
User Manuals and VTY reference manuals are [optionally] built in PDF form
|
|
||||||
as part of the build process.
|
|
||||||
|
|
||||||
Pre-rendered PDF version of the current "master" can be found at
|
|
||||||
[User Manual](https://ftp.osmocom.org/docs/latest/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)
|
|
||||||
|
|
||||||
Mailing List
|
|
||||||
------------
|
|
||||||
|
|
||||||
Discussions related to osmo-hlr are happening on the
|
|
||||||
openbsc@lists.osmocom.org mailing list, please see
|
|
||||||
https://lists.osmocom.org/mailman/listinfo/openbsc for subscription
|
|
||||||
options and the list archive.
|
|
||||||
|
|
||||||
Please observe the [Osmocom Mailing List
|
|
||||||
Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
|
|
||||||
when posting.
|
|
||||||
|
|
||||||
Contributing
|
|
||||||
------------
|
|
||||||
|
|
||||||
Our coding standards are described at
|
|
||||||
https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
|
|
||||||
|
|
||||||
We us a gerrit based patch submission/review process for managing
|
|
||||||
contributions. Please see
|
|
||||||
https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for
|
|
||||||
more details
|
|
||||||
|
|
||||||
The current patch queue for osmo-hlr can be seen at
|
|
||||||
https://gerrit.osmocom.org/#/q/project:osmo-hlr+status:open
|
|
||||||
@@ -7,3 +7,4 @@
|
|||||||
# 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
|
||||||
|
osmo-hlr update osmo-gsm-manuals dependency to > 0.3.0 for vty_cpu_sched.adoc include
|
||||||
|
|||||||
16
configure.ac
16
configure.ac
@@ -12,8 +12,6 @@ AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip 1.9])
|
|||||||
|
|
||||||
AC_CONFIG_TESTDIR(tests)
|
AC_CONFIG_TESTDIR(tests)
|
||||||
|
|
||||||
CFLAGS="$CFLAGS -std=gnu11"
|
|
||||||
|
|
||||||
dnl kernel style compile messages
|
dnl kernel style compile messages
|
||||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
@@ -41,11 +39,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.9.0)
|
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0)
|
||||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.9.0)
|
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.4.0)
|
||||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0)
|
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.4.0)
|
||||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.0)
|
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.4.0)
|
||||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.5.0)
|
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
|
||||||
|
|
||||||
PKG_CHECK_MODULES(SQLITE3, sqlite3)
|
PKG_CHECK_MODULES(SQLITE3, sqlite3)
|
||||||
|
|
||||||
@@ -93,7 +91,6 @@ AC_ARG_ENABLE(werror,
|
|||||||
if test x"$werror" = x"yes"
|
if test x"$werror" = x"yes"
|
||||||
then
|
then
|
||||||
WERROR_FLAGS="-Werror"
|
WERROR_FLAGS="-Werror"
|
||||||
WERROR_FLAGS+=" -Werror=implicit-int -Werror=int-conversion -Werror=old-style-definition"
|
|
||||||
WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
|
WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
|
||||||
WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
|
WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
|
||||||
CFLAGS="$CFLAGS $WERROR_FLAGS"
|
CFLAGS="$CFLAGS $WERROR_FLAGS"
|
||||||
@@ -108,7 +105,7 @@ if test "x$enable_ext_tests" = "xyes" ; then
|
|||||||
AM_PATH_PYTHON
|
AM_PATH_PYTHON
|
||||||
AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmotestvty.py,yes)
|
AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmotestvty.py,yes)
|
||||||
if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then
|
if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then
|
||||||
AC_MSG_ERROR([Please install https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests to run the VTY/CTRL tests.])
|
AC_MSG_ERROR([Please install git://osmocom.org/python/osmo-python-tests to run the VTY/CTRL tests.])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
AC_MSG_CHECKING([whether to enable VTY/CTRL tests])
|
AC_MSG_CHECKING([whether to enable VTY/CTRL tests])
|
||||||
@@ -207,6 +204,7 @@ AC_OUTPUT(
|
|||||||
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
|
||||||
|
tests/gsup_server/Makefile
|
||||||
tests/gsup/Makefile
|
tests/gsup/Makefile
|
||||||
tests/db/Makefile
|
tests/db/Makefile
|
||||||
tests/db_upgrade/Makefile
|
tests/db_upgrade/Makefile
|
||||||
|
|||||||
@@ -2,13 +2,3 @@ SUBDIRS = \
|
|||||||
systemd \
|
systemd \
|
||||||
dgsm \
|
dgsm \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXTRA_DIST = osmo-hlr-post-upgrade.sh
|
|
||||||
|
|
||||||
install-data-hook:
|
|
||||||
install -Dm755 $(srcdir)/osmo-hlr-post-upgrade.sh \
|
|
||||||
-t $(DESTDIR)$(datadir)/osmocom/
|
|
||||||
|
|
||||||
uninstall-hook:
|
|
||||||
@$(PRE_UNINSTALL)
|
|
||||||
$(RM) $(DESTDIR)$(datadir)/osmocom/osmo-hlr-post-upgrade.sh
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ osmo-build-dep.sh libosmo-abis
|
|||||||
# Additional configure options and depends
|
# Additional configure options and depends
|
||||||
CONFIG=""
|
CONFIG=""
|
||||||
if [ "$WITH_MANUALS" = "1" ]; then
|
if [ "$WITH_MANUALS" = "1" ]; then
|
||||||
|
osmo-build-dep.sh osmo-gsm-manuals
|
||||||
CONFIG="--enable-manuals"
|
CONFIG="--enable-manuals"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -56,11 +57,11 @@ autoreconf --install --force
|
|||||||
$CONFIG
|
$CONFIG
|
||||||
$MAKE $PARALLEL_MAKE
|
$MAKE $PARALLEL_MAKE
|
||||||
$MAKE check || cat-testlogs.sh
|
$MAKE check || cat-testlogs.sh
|
||||||
DISTCHECK_CONFIGURE_FLAGS="$CONFIG" $MAKE $PARALLEL_MAKE distcheck || cat-testlogs.sh
|
DISTCHECK_CONFIGURE_FLAGS="$CONFIG" $MAKE distcheck || cat-testlogs.sh
|
||||||
|
|
||||||
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
|
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
|
||||||
make -C "$base/doc/manuals" publish
|
make -C "$base/doc/manuals" publish
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$MAKE $PARALLEL_MAKE maintainer-clean
|
$MAKE maintainer-clean
|
||||||
osmo-clean-workspace.sh
|
osmo-clean-workspace.sh
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
#!/bin/sh -e
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
# Copyright 2021 sysmocom s.f.m.c GmbH <info@sysmocom.de>
|
|
||||||
#
|
|
||||||
# Packagers are supposed to call this script in post-upgrade, so it can safely
|
|
||||||
# upgrade the database scheme if required.
|
|
||||||
|
|
||||||
DB="/var/lib/osmocom/hlr.db"
|
|
||||||
IS_ACTIVE=0
|
|
||||||
|
|
||||||
msg() {
|
|
||||||
echo "osmo-hlr-post-upgrade: $@"
|
|
||||||
}
|
|
||||||
|
|
||||||
err() {
|
|
||||||
msg "ERROR: $@"
|
|
||||||
}
|
|
||||||
|
|
||||||
open_db() {
|
|
||||||
# Attempt to open the database with osmo-hlr-db-tool, it will fail if
|
|
||||||
# upgrading the schema is required
|
|
||||||
osmo-hlr-db-tool -s -l "$DB" create
|
|
||||||
}
|
|
||||||
|
|
||||||
check_upgrade_required() {
|
|
||||||
if ! [ -e "$DB" ]; then
|
|
||||||
msg "nothing to do (no existing database)"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if open_db 2>/dev/null; then
|
|
||||||
msg "nothing to do (database version is up to date)"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg "database upgrade is required"
|
|
||||||
}
|
|
||||||
|
|
||||||
stop_service() {
|
|
||||||
if systemctl is-active -q osmo-hlr; then
|
|
||||||
IS_ACTIVE=1
|
|
||||||
msg "stopping osmo-hlr service"
|
|
||||||
systemctl stop osmo-hlr
|
|
||||||
|
|
||||||
# Verify that it stopped
|
|
||||||
for i in $(seq 1 100); do
|
|
||||||
if ! systemctl is-active -q osmo-hlr; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
|
|
||||||
err "failed to stop osmo-hlr service"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
msg "osmo-hlr service is not running"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
create_backup() {
|
|
||||||
backup="$DB.$(date +%Y%m%d%H%M%S).bak"
|
|
||||||
msg "creating backup: $backup"
|
|
||||||
if [ -e "$backup" ]; then
|
|
||||||
err "backup already exists: $backup"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cp "$DB" "$backup"
|
|
||||||
}
|
|
||||||
|
|
||||||
upgrade() {
|
|
||||||
msg "performing database upgrade"
|
|
||||||
osmo-hlr-db-tool -s -U -l "$DB" create
|
|
||||||
|
|
||||||
if ! open_db 2>/dev/null; then
|
|
||||||
err "failed to open the database after upgrade"
|
|
||||||
err "osmo-hlr-db-tool output:"
|
|
||||||
open_db
|
|
||||||
# exit because of "set -e"
|
|
||||||
fi
|
|
||||||
|
|
||||||
msg "database upgrade successful"
|
|
||||||
}
|
|
||||||
|
|
||||||
start_service() {
|
|
||||||
if [ "$IS_ACTIVE" = "1" ]; then
|
|
||||||
msg "starting osmo-hlr service"
|
|
||||||
systemctl start osmo-hlr
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
check_upgrade_required
|
|
||||||
stop_service
|
|
||||||
create_backup
|
|
||||||
upgrade
|
|
||||||
start_service
|
|
||||||
@@ -29,11 +29,11 @@ BuildRequires: python3
|
|||||||
%if 0%{?suse_version}
|
%if 0%{?suse_version}
|
||||||
BuildRequires: systemd-rpm-macros
|
BuildRequires: systemd-rpm-macros
|
||||||
%endif
|
%endif
|
||||||
BuildRequires: pkgconfig(libosmoabis) >= 1.5.0
|
BuildRequires: pkgconfig(libosmoabis) >= 0.6.0
|
||||||
BuildRequires: pkgconfig(libosmocore) >= 1.9.0
|
BuildRequires: pkgconfig(libosmocore) >= 1.2.0
|
||||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.9.0
|
BuildRequires: pkgconfig(libosmoctrl) >= 1.2.0
|
||||||
BuildRequires: pkgconfig(libosmogsm) >= 1.9.0
|
BuildRequires: pkgconfig(libosmogsm) >= 1.2.0
|
||||||
BuildRequires: pkgconfig(libosmovty) >= 1.9.0
|
BuildRequires: pkgconfig(libosmovty) >= 1.2.0
|
||||||
BuildRequires: pkgconfig(sqlite3)
|
BuildRequires: pkgconfig(sqlite3)
|
||||||
BuildRequires: pkgconfig(talloc) >= 2.0.1
|
BuildRequires: pkgconfig(talloc) >= 2.0.1
|
||||||
# only needed for populate_hlr_db.pl
|
# only needed for populate_hlr_db.pl
|
||||||
@@ -75,19 +75,19 @@ and External USSD Entities (EUSEs) using this library to implement clients.
|
|||||||
This subpackage contains libraries and header files for developing
|
This subpackage contains libraries and header files for developing
|
||||||
applications that want to make use of libosmo-gsup-client.
|
applications that want to make use of libosmo-gsup-client.
|
||||||
|
|
||||||
%package -n libosmo-mslookup1
|
%package -n libosmo-mslookup0
|
||||||
Summary: Osmocom MS lookup library
|
Summary: Osmocom MS lookup library
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
Group: System/Libraries
|
Group: System/Libraries
|
||||||
|
|
||||||
%description -n libosmo-mslookup1
|
%description -n libosmo-mslookup0
|
||||||
This shared library contains routines for looking up mobile subscribers.
|
This shared library contains routines for looking up mobile subscribers.
|
||||||
|
|
||||||
%package -n libosmo-mslookup-devel
|
%package -n libosmo-mslookup-devel
|
||||||
Summary: Development files for the Osmocom MS lookup library
|
Summary: Development files for the Osmocom MS lookup library
|
||||||
License: GPL-2.0-or-later
|
License: GPL-2.0-or-later
|
||||||
Group: Development/Libraries/C and C++
|
Group: Development/Libraries/C and C++
|
||||||
Requires: libosmo-mslookup1 = %{version}
|
Requires: libosmo-mslookup0 = %{version}
|
||||||
|
|
||||||
%description -n libosmo-mslookup-devel
|
%description -n libosmo-mslookup-devel
|
||||||
This shared library contains routines for looking up mobile subscribers.
|
This shared library contains routines for looking up mobile subscribers.
|
||||||
@@ -136,18 +136,15 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
|
|||||||
|
|
||||||
%pre
|
%pre
|
||||||
%service_add_pre %{name}.service
|
%service_add_pre %{name}.service
|
||||||
%endif
|
|
||||||
|
|
||||||
%post
|
%post
|
||||||
%if 0%{?suse_version}
|
|
||||||
%service_add_post %{name}.service
|
%service_add_post %{name}.service
|
||||||
%endif
|
%endif
|
||||||
/usr/share/osmocom/osmo-hlr-post-upgrade.sh
|
|
||||||
|
|
||||||
%post -n libosmo-gsup-client0 -p /sbin/ldconfig
|
%post -n libosmo-gsup-client0 -p /sbin/ldconfig
|
||||||
%postun -n libosmo-gsup-client0 -p /sbin/ldconfig
|
%postun -n libosmo-gsup-client0 -p /sbin/ldconfig
|
||||||
%post -n libosmo-mslookup1 -p /sbin/ldconfig
|
%post -n libosmo-mslookup0 -p /sbin/ldconfig
|
||||||
%postun -n libosmo-mslookup1 -p /sbin/ldconfig
|
%postun -n libosmo-mslookup0 -p /sbin/ldconfig
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%license COPYING
|
%license COPYING
|
||||||
@@ -165,8 +162,6 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
|
|||||||
%dir %{_sysconfdir}/osmocom
|
%dir %{_sysconfdir}/osmocom
|
||||||
%config %{_sysconfdir}/osmocom/osmo-hlr.cfg
|
%config %{_sysconfdir}/osmocom/osmo-hlr.cfg
|
||||||
%{_unitdir}/osmo-hlr.service
|
%{_unitdir}/osmo-hlr.service
|
||||||
%dir %{_datadir}/osmocom
|
|
||||||
%{_datadir}/osmocom/osmo-hlr-post-upgrade.sh
|
|
||||||
|
|
||||||
%files -n libosmo-gsup-client0
|
%files -n libosmo-gsup-client0
|
||||||
%{_libdir}/libosmo-gsup-client.so.0*
|
%{_libdir}/libosmo-gsup-client.so.0*
|
||||||
@@ -179,8 +174,8 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
|
|||||||
%{_libdir}/libosmo-gsup-client.so
|
%{_libdir}/libosmo-gsup-client.so
|
||||||
%{_libdir}/pkgconfig/libosmo-gsup-client.pc
|
%{_libdir}/pkgconfig/libosmo-gsup-client.pc
|
||||||
|
|
||||||
%files -n libosmo-mslookup1
|
%files -n libosmo-mslookup0
|
||||||
%{_libdir}/libosmo-mslookup.so.1*
|
%{_libdir}/libosmo-mslookup.so.0*
|
||||||
|
|
||||||
%files -n libosmo-mslookup-devel
|
%files -n libosmo-mslookup-devel
|
||||||
%dir %{_includedir}/osmocom
|
%dir %{_includedir}/osmocom
|
||||||
|
|||||||
@@ -1,17 +1,12 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Osmocom Home Location Register (OsmoHLR)
|
Description=Osmocom Home Location Register (OsmoHLR)
|
||||||
Documentation=https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR
|
Documentation=https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR
|
||||||
After=network-online.target
|
|
||||||
Wants=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
Restart=always
|
Restart=always
|
||||||
StateDirectory=osmocom
|
|
||||||
WorkingDirectory=%S/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
|
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
222
debian/changelog
vendored
222
debian/changelog
vendored
@@ -1,225 +1,3 @@
|
|||||||
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
|
|
||||||
|
|
||||||
[ Pau Espin Pedrol ]
|
|
||||||
* mslookup: Call osmo_fd_unregister() before closing and changing bfd->fd
|
|
||||||
|
|
||||||
[ Vadim Yanitskiy ]
|
|
||||||
* 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 ]
|
|
||||||
* hlr: use talloc for memory allocation in osmo_gsup_create_insert_subscriber_data_msg
|
|
||||||
* Add support for multiple APN profiles for subscriber data
|
|
||||||
|
|
||||||
[ Harald Welte ]
|
|
||||||
* 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
|
|
||||||
|
|
||||||
[ Vadim Yanitskiy ]
|
|
||||||
* db_auc: hexparse_stmt(): check value returned by osmo_hexparse()
|
|
||||||
|
|
||||||
[ Max ]
|
|
||||||
* Set working directory in systemd service file
|
|
||||||
* Ignore .deb build byproducts
|
|
||||||
* Debian: bump copyright year to match current
|
|
||||||
* Debian: reformat package description
|
|
||||||
* systemd: enable basic hardening
|
|
||||||
* Debian: install osmo-hlr-dgsm.cfg as example config
|
|
||||||
* hlr_vty.c: fix typo
|
|
||||||
* ctrl: take both address and port from vty config
|
|
||||||
|
|
||||||
[ Harald Welte ]
|
|
||||||
* Support building with -Werror=strict-prototypes / -Werror=old-style-definition
|
|
||||||
* Add -Werror=implicit-int -Werror=int-conversion -Werror=old-style-definition
|
|
||||||
|
|
||||||
[ arehbein ]
|
|
||||||
* osmo-hlr: Transition to use of 'telnet_init_default'
|
|
||||||
|
|
||||||
[ Oliver Smith ]
|
|
||||||
* osmo_mdns_rfc_record_decode: check ret of talloc
|
|
||||||
* osmo_mdns_rfc_record_decode: proper free on err
|
|
||||||
* mslookup: use apn functions from libosmocore
|
|
||||||
* osmo_mdns_rfc_record/question_encode: remove ctx
|
|
||||||
|
|
||||||
[ Keith ]
|
|
||||||
* Vty: Fixup config shown/written from vty
|
|
||||||
|
|
||||||
[ Neels Hofmeyr ]
|
|
||||||
* fix memleak of proxy_subscr_listentry
|
|
||||||
|
|
||||||
[ Alexander Couzens ]
|
|
||||||
* Add vty `reject-cause` to set the reject cause
|
|
||||||
|
|
||||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 07 Feb 2023 16:49:14 +0100
|
|
||||||
|
|
||||||
osmo-hlr (1.5.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
[ Oliver Smith ]
|
|
||||||
* treewide: remove FSF address
|
|
||||||
|
|
||||||
[ Vadim Yanitskiy ]
|
|
||||||
* fixup: debian: remove unneeded dependency libdbd-sqlite3
|
|
||||||
* debian: add new 'osmo-mslookup-utils' package
|
|
||||||
* tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS'
|
|
||||||
|
|
||||||
[ Pau Espin Pedrol ]
|
|
||||||
* ctrl: Mark function as static
|
|
||||||
* tests: Allow specyfing specific ctrl test to run
|
|
||||||
* tests/ctrl: Move ERROR test scenario to proper file
|
|
||||||
* Fix db_subscr_create() not returning -EEXIST expected by VTY subscriber create cmd
|
|
||||||
* ctrl: Introduce cmd SET subscriber.create <imsi>
|
|
||||||
* ctrl: Introduce CTRL command subscriber.by-*.msisdn
|
|
||||||
* cosmetic: hlr_vty_subscr.c: Fix trailing whitespace
|
|
||||||
* ctrl: Introduce cmd SET subscriber.delete <imsi>
|
|
||||||
* ctrl: Introduce CTRL command subscriber.by-*.aud2g <algo[,ki]>
|
|
||||||
* ctrl: Introduce CTRL command subscriber.by-*.aud3g <algo[,KI,(op|opc),OP_C[,ind_bitlen]]>
|
|
||||||
* doc: Document new subscriber CTRL commands
|
|
||||||
|
|
||||||
[ Harald Welte ]
|
|
||||||
* update git URLs (git -> https; gitea)
|
|
||||||
|
|
||||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 28 Jun 2022 18:38:31 +0200
|
|
||||||
|
|
||||||
osmo-hlr (1.4.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
[ Keith ]
|
|
||||||
* Correct configuration written from vty
|
|
||||||
* vty: enable show subscribers filtered by IMEI
|
|
||||||
|
|
||||||
[ Harald Welte ]
|
|
||||||
* add README.md file as customary for cgit, github, gitlab, etc.
|
|
||||||
|
|
||||||
[ Oliver Smith ]
|
|
||||||
* Add post-upgrade script for automatic db upgrade
|
|
||||||
* debian/control: remove dh-systemd build-depend
|
|
||||||
|
|
||||||
[ Pau Espin Pedrol ]
|
|
||||||
* db: Avoid use uninitialized rc if running 0 statements
|
|
||||||
|
|
||||||
[ Neels Hofmeyr ]
|
|
||||||
* db v6: determine 3G AUC IND from VLR name
|
|
||||||
|
|
||||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 16 Nov 2021 14:56:41 +0100
|
|
||||||
|
|
||||||
osmo-hlr (1.3.0) unstable; urgency=medium
|
|
||||||
|
|
||||||
[ Alexander Couzens ]
|
|
||||||
* hlr: respect the num_auth_vectors requested
|
|
||||||
* hlr: remove unused internal USSD list
|
|
||||||
|
|
||||||
[ Oliver Smith ]
|
|
||||||
* add libosmo-mslookup abstract client
|
|
||||||
* add mDNS lookup method to libosmo-mslookup
|
|
||||||
* Makefile.am: fix pkgconfig_DATA
|
|
||||||
* add mDNS lookup method to libosmo-mslookup (#2)
|
|
||||||
* contrib/dgsm/ add example esme and dialplan
|
|
||||||
* mslookup_client.c: fix dereferencing null pointer
|
|
||||||
* mdns_msg.c: always call va_end
|
|
||||||
* mslookup_client_mdns.c: fix dereferencing null
|
|
||||||
* osmo-mslookup-client.c: fix dereferencing null
|
|
||||||
* osmo-mslookup-client: fix dereferencing null
|
|
||||||
* mdns_sock.c: fix resource leak of sock
|
|
||||||
* mdns_rfc.c: fix possible access of uninit. mem
|
|
||||||
* mslookup_client_mdns_test: disable by default
|
|
||||||
* mslookup_client_mdns_test: no automatic skip
|
|
||||||
* Cosmetic: mention OS#4491 in location cancel code
|
|
||||||
* hlr_vty_subscr: prettier output for last LU seen
|
|
||||||
* contrib: import RPM spec
|
|
||||||
* contrib: integrate RPM spec
|
|
||||||
* Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
|
|
||||||
* contrib/jenkins: don't build osmo-gsm-manuals
|
|
||||||
* configure.ac: set -std=gnu11
|
|
||||||
|
|
||||||
[ Neels Hofmeyr ]
|
|
||||||
* add osmo-mslookup-client program
|
|
||||||
* add osmo-mslookup-client program (#2)
|
|
||||||
* fix missing braces in LOGP_GSUP_FWD
|
|
||||||
* gsup_client.c: fix deprecation for client create func
|
|
||||||
* 1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name
|
|
||||||
* 2/2: wrap ipa_name in osmo_cni_peer_id with type enum and union
|
|
||||||
* gsup client: add up_down_cb(), add osmo_gsup_client_create3()
|
|
||||||
* db v5: prep for D-GSM: add vlr_via_proxy and sgsn_via_proxy
|
|
||||||
* enlarge the GSUP message headroom
|
|
||||||
* test_nodes.vty: remove cruft
|
|
||||||
* D-GSM 1/n: add mslookup server in osmo-hlr
|
|
||||||
* D-GSM 2/n: implement mDNS method of mslookup server
|
|
||||||
* D-GSM 3/n: implement roaming by mslookup in osmo-hlr
|
|
||||||
* gsup_server: send routing error back to the correct peer
|
|
||||||
* adoc: add D-GSM chapter to osmohlr-usermanual
|
|
||||||
* drop error log for when a subscriber does not exist
|
|
||||||
* vty: show subscriber: change format of 'last LU seen'
|
|
||||||
* vty: show subscriber: show lu d,h,m,s ago, not just seconds
|
|
||||||
* auc3g: officially wrap IND around IND_bitlen space
|
|
||||||
* make osmo_cni_peer_id_cmp() NULL safe
|
|
||||||
* osmo_gsup_req_new(): require from_peer != NULL
|
|
||||||
* gsup_server.c: properly handle negative rc from osmo_gsup_conn_ccm_get()
|
|
||||||
* osmo_mslookup_server_mdns_rx(): handle read() rc == 0
|
|
||||||
* hlr_subscr_nam(): fix condition to fix nam=false notifications
|
|
||||||
* esme_dgsm.py: add --always-fail option for debugging SMPP
|
|
||||||
* osmo-mslookup-client: fix segfault for respond_error() caller
|
|
||||||
* manual: describe subscriber import by SQL
|
|
||||||
|
|
||||||
[ Harald Welte ]
|
|
||||||
* Revert "add osmo-mslookup-client program"
|
|
||||||
* Revert "add mDNS lookup method to libosmo-mslookup"
|
|
||||||
* Use OSMO_FD_* instead of deprecated BSC_FD_*
|
|
||||||
* support the XOR algorithm for UMTS AKA
|
|
||||||
* auc_test.c: Add some comments on what the test cases actually do
|
|
||||||
* main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
|
|
||||||
* manuals: generate vty reference xml at build time
|
|
||||||
|
|
||||||
[ Vadim Yanitskiy ]
|
|
||||||
* db: fix possible SQLite3 allocated memory leak in db_open()
|
|
||||||
* gsup_server: fix typo: s/omso_gsup_message/osmo_gsup_message/
|
|
||||||
* debian/control: change maintainer to the Osmocom team / mailing list
|
|
||||||
* cosmetic: fix spelling in logging message: existAnt -> existEnt
|
|
||||||
* doc/manuals: fix s/There/The/ in 'USSD Configuration'
|
|
||||||
* doc/manuals: re-organize description of internal USSD handlers
|
|
||||||
* USSD: fix handle_ussd(): do not free() unconditionally
|
|
||||||
* USSD: add special 'idle' handler to IUSE for testing
|
|
||||||
|
|
||||||
[ Eric ]
|
|
||||||
* configure.ac: fix libtool issue with clang and sanitizer
|
|
||||||
|
|
||||||
[ Philipp Maier ]
|
|
||||||
* doc: do not use loglevel info for log category ss
|
|
||||||
|
|
||||||
[ Pau Espin Pedrol ]
|
|
||||||
* configure.ac: Fix trailing whitespace
|
|
||||||
* doc: Update VTY reference xml file
|
|
||||||
* Support setting rt-prio and cpu-affinity mask through VTY
|
|
||||||
* Set TCP NODELAY sockopt to GSUP cli and srv connections
|
|
||||||
* contrib/jenkins: Enable parallel make in make distcheck
|
|
||||||
* .gitignore: Ignore new autofoo tmp files
|
|
||||||
* tests: Replace deprecated API log_set_print_filename
|
|
||||||
|
|
||||||
[ Keith ]
|
|
||||||
* osmo-hlr-db-tool: Make import from osmo-nitb less "lossy"
|
|
||||||
* Correct vty inline help for show subscriber
|
|
||||||
* Add vty command to show summary of all or filtered subscribers
|
|
||||||
* Fix Coverity Warnings
|
|
||||||
|
|
||||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 23 Feb 2021 18:13:53 +0100
|
|
||||||
|
|
||||||
osmo-hlr (1.2.0) unstable; urgency=medium
|
osmo-hlr (1.2.0) unstable; urgency=medium
|
||||||
|
|
||||||
[ Ruben Undheim ]
|
[ Ruben Undheim ]
|
||||||
|
|||||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
|||||||
10
|
9
|
||||||
|
|||||||
36
debian/control
vendored
36
debian/control
vendored
@@ -2,29 +2,29 @@ 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,
|
||||||
|
dh-systemd (>= 1.5),
|
||||||
autotools-dev,
|
autotools-dev,
|
||||||
python3-minimal,
|
python3-minimal,
|
||||||
libosmocore-dev (>= 1.9.0),
|
libosmocore-dev (>= 1.4.0),
|
||||||
libosmo-abis-dev (>= 1.5.0),
|
libosmo-abis-dev,
|
||||||
libosmo-netif-dev (>= 1.4.0),
|
libosmo-netif-dev,
|
||||||
libsqlite3-dev,
|
libsqlite3-dev,
|
||||||
sqlite3,
|
sqlite3,
|
||||||
osmo-gsm-manuals-dev (>= 1.5.0)
|
osmo-gsm-manuals-dev
|
||||||
Standards-Version: 3.9.6
|
Standards-Version: 3.9.6
|
||||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
|
Vcs-Browser: http://cgit.osmocom.org/osmo-hlr
|
||||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
|
Vcs-Git: git://git.osmocom.org/osmo-hlr
|
||||||
Homepage: https://projects.osmocom.org/projects/osmo-hlr
|
Homepage: https://projects.osmocom.org/projects/osmo-hlr
|
||||||
|
|
||||||
Package: osmo-hlr
|
Package: osmo-hlr
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
Depends: ${shlibs:Depends}, ${misc:Depends}, libdbd-sqlite3
|
||||||
Description: Osmocom Home Location Register
|
Description: Osmocom Home Location Register
|
||||||
OsmoHLR is a Osmocom implementation of HLR (Home Location Registrar) which
|
OsmoHLR is a Osmocom implementation of HLR (Home Location Registrar) which works over GSUP
|
||||||
works over GSUP protocol. The subscribers are store in sqlite DB.
|
protocol. The subscribers are store in sqlite DB. It supports both 2G and 3G authentication.
|
||||||
It supports both 2G and 3G authentication.
|
|
||||||
|
|
||||||
Package: osmo-hlr-dbg
|
Package: osmo-hlr-dbg
|
||||||
Architecture: any
|
Architecture: any
|
||||||
@@ -59,7 +59,7 @@ Description: Development headers of Osmocom GSUP client library
|
|||||||
.
|
.
|
||||||
This package contains the development headers.
|
This package contains the development headers.
|
||||||
|
|
||||||
Package: libosmo-mslookup1
|
Package: libosmo-mslookup0
|
||||||
Section: libs
|
Section: libs
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Multi-Arch: same
|
Multi-Arch: same
|
||||||
@@ -73,7 +73,7 @@ Package: libosmo-mslookup-dev
|
|||||||
Architecture: any
|
Architecture: any
|
||||||
Multi-Arch: same
|
Multi-Arch: same
|
||||||
Depends: ${misc:Depends},
|
Depends: ${misc:Depends},
|
||||||
libosmo-mslookup1 (= ${binary:Version}),
|
libosmo-mslookup0 (= ${binary:Version}),
|
||||||
libosmocore-dev
|
libosmocore-dev
|
||||||
Pre-Depends: ${misc:Pre-Depends}
|
Pre-Depends: ${misc:Pre-Depends}
|
||||||
Description: Development headers of Osmocom MS lookup library
|
Description: Development headers of Osmocom MS lookup library
|
||||||
@@ -81,16 +81,6 @@ Description: Development headers of Osmocom MS lookup library
|
|||||||
.
|
.
|
||||||
This package contains the development headers.
|
This package contains the development headers.
|
||||||
|
|
||||||
Package: osmo-mslookup-utils
|
|
||||||
Architecture: any
|
|
||||||
Section: utils
|
|
||||||
Depends: ${shlibs:Depends},
|
|
||||||
libosmo-mslookup1 (= ${binary:Version}),
|
|
||||||
${misc:Depends}
|
|
||||||
Multi-Arch: same
|
|
||||||
Description: Utilities for Osmocom MS lookup
|
|
||||||
This package contains a simple MS lookup client utility.
|
|
||||||
|
|
||||||
Package: osmo-hlr-doc
|
Package: osmo-hlr-doc
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Section: doc
|
Section: doc
|
||||||
|
|||||||
2
debian/copyright
vendored
2
debian/copyright
vendored
@@ -3,7 +3,7 @@ Upstream-Name: OsmoHLR
|
|||||||
Source: http://cgit.osmocom.org/osmo-hlr/
|
Source: http://cgit.osmocom.org/osmo-hlr/
|
||||||
|
|
||||||
Files: *
|
Files: *
|
||||||
Copyright: 2016-2022 Sysmocom s. f. m. c. GmbH <info@sysmocom.de>
|
Copyright: 2016-2017 Sysmocom s. f. m. c. GmbH <info@sysmocom.de>
|
||||||
License: AGPL-3+
|
License: AGPL-3+
|
||||||
|
|
||||||
License: AGPL-3+
|
License: AGPL-3+
|
||||||
|
|||||||
3
debian/osmo-hlr.install
vendored
3
debian/osmo-hlr.install
vendored
@@ -5,5 +5,4 @@
|
|||||||
/usr/share/doc/osmo-hlr/sql/hlr.sql
|
/usr/share/doc/osmo-hlr/sql/hlr.sql
|
||||||
/usr/share/doc/osmo-hlr/sql/hlr_data.sql
|
/usr/share/doc/osmo-hlr/sql/hlr_data.sql
|
||||||
/usr/share/doc/osmo-hlr/examples/osmo-hlr.cfg
|
/usr/share/doc/osmo-hlr/examples/osmo-hlr.cfg
|
||||||
/usr/share/doc/osmo-hlr/examples/osmo-hlr-dgsm.cfg
|
/var/lib/osmocom
|
||||||
/usr/share/osmocom/osmo-hlr-post-upgrade.sh
|
|
||||||
|
|||||||
1
debian/osmo-mslookup-utils.install
vendored
1
debian/osmo-mslookup-utils.install
vendored
@@ -1 +0,0 @@
|
|||||||
usr/bin/osmo-mslookup-client
|
|
||||||
5
debian/postinst
vendored
5
debian/postinst
vendored
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/sh -e
|
|
||||||
# Debian's postinst script is called on both installation and upgrade. Call the
|
|
||||||
# post-upgrade script in both cases, it won't do anything if there is nothing
|
|
||||||
# to do.
|
|
||||||
/usr/share/osmocom/osmo-hlr-post-upgrade.sh
|
|
||||||
@@ -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 *
|
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
EXTRA_DIST = \
|
EXTRA_DIST = example_subscriber_add_update_delete.vty \
|
||||||
example_subscriber_add_update_delete.vty \
|
|
||||||
example_subscriber_aud2g.ctrl \
|
|
||||||
example_subscriber_aud3g.ctrl \
|
|
||||||
example_subscriber_cs_ps_enabled.ctrl \
|
example_subscriber_cs_ps_enabled.ctrl \
|
||||||
example_subscriber_info.ctrl \
|
example_subscriber_info.ctrl \
|
||||||
example_subscriber_msisdn.ctrl \
|
|
||||||
osmohlr-usermanual.adoc \
|
osmohlr-usermanual.adoc \
|
||||||
osmohlr-usermanual-docinfo.xml \
|
osmohlr-usermanual-docinfo.xml \
|
||||||
osmohlr-vty-reference.xml \
|
osmohlr-vty-reference.xml \
|
||||||
@@ -18,12 +14,6 @@ if BUILD_MANUALS
|
|||||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
|
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
|
||||||
|
|
||||||
VTY_REFERENCE = osmohlr-vty-reference.xml
|
VTY_REFERENCE = osmohlr-vty-reference.xml
|
||||||
|
|
||||||
BUILT_REFERENCE_XML = $(builddir)/vty/hlr_vty_reference.xml
|
|
||||||
$(builddir)/vty/hlr_vty_reference.xml: $(top_builddir)/src/osmo-hlr
|
|
||||||
mkdir -p $(builddir)/vty
|
|
||||||
$(top_builddir)/src/osmo-hlr --vty-ref-xml > $@
|
|
||||||
|
|
||||||
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
|
include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
|
||||||
|
|
||||||
OSMO_REPOSITORY = osmo-hlr
|
OSMO_REPOSITORY = osmo-hlr
|
||||||
|
|||||||
@@ -5,16 +5,6 @@ The actual protocol is described in <<common-control-if>>, the variables common
|
|||||||
to all programs using it are described in <<ctrl_common_vars>>. This section
|
to all programs using it are described in <<ctrl_common_vars>>. This section
|
||||||
describes the CTRL interface variables specific to OsmoHLR.
|
describes the CTRL interface variables specific to OsmoHLR.
|
||||||
|
|
||||||
Subscribers can be created and deleted using the following SET commands:
|
|
||||||
|
|
||||||
.Subscriber management commands available on OsmoHLR's Control interface
|
|
||||||
[options="header",width="100%",cols="35%,65%"]
|
|
||||||
|===
|
|
||||||
|Command|Comment
|
|
||||||
|subscriber.create '123456'|Create a new subscriber with IMSI "123456" to the database. Returns database ID of the subscriber being created.
|
|
||||||
|subscriber.delete '123456'|Delete subscriber with IMSI "123456" from database. Returns database ID of the subscriber being deleted.
|
|
||||||
|===
|
|
||||||
|
|
||||||
All subscriber variables are available by different selectors, which are freely
|
All subscriber variables are available by different selectors, which are freely
|
||||||
interchangeable:
|
interchangeable:
|
||||||
|
|
||||||
@@ -38,9 +28,6 @@ Each of the above selectors feature all of these control variables:
|
|||||||
|subscriber.by-\*.*info-all*|R|No||List both 'info' and 'info-aud' in one
|
|subscriber.by-\*.*info-all*|R|No||List both 'info' and 'info-aud' in one
|
||||||
|subscriber.by-\*.*cs-enabled*|RW|No|'1' or '0'|Enable/disable circuit-switched access
|
|subscriber.by-\*.*cs-enabled*|RW|No|'1' or '0'|Enable/disable circuit-switched access
|
||||||
|subscriber.by-\*.*ps-enabled*|RW|No|'1' or '0'|Enable/disable packet-switched access
|
|subscriber.by-\*.*ps-enabled*|RW|No|'1' or '0'|Enable/disable packet-switched access
|
||||||
|subscriber.by-\*.*msisdn*|RW|No|valid MSISDN string|Get/Set assigned MSISDN
|
|
||||||
|subscriber.by-\*.*aud2g*|RW|No|'algo[,KI]'|Get/Set 2g Authentication Data
|
|
||||||
|subscriber.by-\*.*aud2g*|RW|No|'algo[,KI,("op"|"opc"),OP_C[,ind_bitlen]]'|Get/Set 3g Authentication Data
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
=== subscriber.by-*.info, info-aud, info-all
|
=== subscriber.by-*.info, info-aud, info-all
|
||||||
@@ -117,63 +104,3 @@ commands:
|
|||||||
----
|
----
|
||||||
include::../example_subscriber_cs_ps_enabled.ctrl[]
|
include::../example_subscriber_cs_ps_enabled.ctrl[]
|
||||||
----
|
----
|
||||||
|
|
||||||
=== subscriber.by-*.msisdn
|
|
||||||
|
|
||||||
Get or set the MSISDN currently assigned to a subscriber.
|
|
||||||
|
|
||||||
|
|
||||||
This is an example transcript that illustrates use of this command:
|
|
||||||
|
|
||||||
----
|
|
||||||
include::../example_subscriber_msisdn.ctrl[]
|
|
||||||
----
|
|
||||||
|
|
||||||
=== subscriber.by-*.aud2g
|
|
||||||
|
|
||||||
Get or set the 2G Authentication data of a subscriber.
|
|
||||||
|
|
||||||
The information is stored/retrieved as a comma separated list of fields:
|
|
||||||
|
|
||||||
----
|
|
||||||
algo[,KI]
|
|
||||||
----
|
|
||||||
|
|
||||||
Where::
|
|
||||||
* *KI* is the KI as a hexadecimal string.
|
|
||||||
* *algo* is one of the following algorithms: _none, xor, comp128v1, comp128v2,
|
|
||||||
comp128v3_.
|
|
||||||
|
|
||||||
All values are case insensitive.
|
|
||||||
|
|
||||||
This is an example transcript that illustrates use of this command:
|
|
||||||
|
|
||||||
----
|
|
||||||
include::../example_subscriber_aud2g.ctrl[]
|
|
||||||
----
|
|
||||||
|
|
||||||
=== subscriber.by-*.aud3g
|
|
||||||
|
|
||||||
Get or set the 3G Authentication data of a subscriber.
|
|
||||||
|
|
||||||
The information is stored/retrieved as a comma separated list of fields:
|
|
||||||
|
|
||||||
----
|
|
||||||
algo[,KI,("op"|"opc"),OP_C[,ind_bitlen]]
|
|
||||||
----
|
|
||||||
|
|
||||||
Where:
|
|
||||||
* *KI* is the KI as a hexadecimal string.
|
|
||||||
* *algo* is one of the following algorithms: _none, xor, milenage_.
|
|
||||||
* "op" or "opc" indicates whether next field is an OP or OPC value.
|
|
||||||
* *OP_C* contains an OP or OPC values as hexadecimal string, based on what the
|
|
||||||
previous field specifies.
|
|
||||||
* *ind_bitlen* is set to 5 by default if not provided.
|
|
||||||
|
|
||||||
All values are case insensitive.
|
|
||||||
|
|
||||||
This is an example transcript that illustrates use of this command:
|
|
||||||
|
|
||||||
----
|
|
||||||
include::../example_subscriber_aud3g.ctrl[]
|
|
||||||
----
|
|
||||||
|
|||||||
@@ -50,29 +50,15 @@ prefix route to the named EUSE. All USSD short codes starting with *123 will be
|
|||||||
routed to the named EUSE.
|
routed to the named EUSE.
|
||||||
|
|
||||||
`ussd route prefix *#100# internal own-msisdn` installs a prefix route
|
`ussd route prefix *#100# internal own-msisdn` installs a prefix route
|
||||||
to the named internal USSD handler. The above command will restore
|
to the named internal USSD handler. There above command will restore
|
||||||
the old behavior, in which *#100# will return a text message containing
|
the old behavior, in which *#100# will return a text message containing
|
||||||
the subscribers own phone number. More information on internal USSD
|
the subscribers own phone number. There is one other handler called
|
||||||
handlers can be found in <<iuse_handlers>>.
|
`own-imsi` which will return the IMSI instead of the MSISDN.
|
||||||
|
|
||||||
`ussd default-route external foobar-00-00-00-00-00-00` installs a
|
`ussd default-route external foobar-00-00-00-00-00-00` installs a
|
||||||
default route to the named EUSE. This means that all USSD codes for
|
default route to the named EUSE. This means that all USSD codes for
|
||||||
which no more specific route exists will be routed to the named EUSE.
|
which no more specific route exists will be routed to the named EUSE.
|
||||||
|
|
||||||
[[iuse_handlers]]
|
|
||||||
=== Built-in USSD handlers
|
|
||||||
|
|
||||||
OsmoHLR has an Internal USSD Entity (IUSE) that allows to handle some
|
|
||||||
USSD requests internally. It features a set of simple handlers, which
|
|
||||||
can be assigned to one or more USSD request prefixes:
|
|
||||||
|
|
||||||
* `own-msisdn` returns subscriber's MSISDN (if assigned);
|
|
||||||
* `own-imsi` returns subscriber's IMSI;
|
|
||||||
* `test-idle` keeps the session idle until the MS terminates it, or
|
|
||||||
the guard timer expires (may be useful for testing).
|
|
||||||
|
|
||||||
Additional handlers can be added on request.
|
|
||||||
|
|
||||||
=== Example EUSE program
|
=== Example EUSE program
|
||||||
|
|
||||||
We have provided an example EUSE developed in C language using existing
|
We have provided an example EUSE developed in C language using existing
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
GET 1 subscriber.by-imsi-901991234567891.aud2g
|
|
||||||
GET_REPLY 1 subscriber.by-imsi-901991234567891.aud2g none
|
|
||||||
|
|
||||||
SET 2 subscriber.by-imsi-901991234567891.aud2g xor,c01ffedc1cadaeac1d1f1edacac1ab0a
|
|
||||||
SET_REPLY 2 subscriber.by-imsi-901991234567891.aud2g OK
|
|
||||||
|
|
||||||
GET 3 subscriber.by-imsi-901991234567891.aud2g
|
|
||||||
GET_REPLY 3 subscriber.by-imsi-901991234567891.aud2g XOR,c01ffedc1cadaeac1d1f1edacac1ab0a
|
|
||||||
|
|
||||||
SET 4 subscriber.by-imsi-901991234567891.aud2g none
|
|
||||||
SET_REPLY 4 subscriber.by-imsi-901991234567891.aud2g OK
|
|
||||||
|
|
||||||
GET 5 subscriber.by-imsi-901991234567891.aud2g
|
|
||||||
GET_REPLY 5 subscriber.by-imsi-901991234567891.aud2g none
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
GET 117 subscriber.by-imsi-901991234567891.aud3g
|
|
||||||
GET_REPLY 117 subscriber.by-imsi-901991234567891.aud3g none
|
|
||||||
|
|
||||||
SET 118 subscriber.by-imsi-901991234567891.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OP,FB2A3D1B360F599ABAB99DB8669F8308
|
|
||||||
SET_REPLY 118 subscriber.by-imsi-901991234567891.aud3g OK
|
|
||||||
|
|
||||||
GET 119 subscriber.by-imsi-901991234567891.aud3g
|
|
||||||
GET_REPLY 119 subscriber.by-imsi-901991234567891.aud3g MILENAGE,c01ffedc1cadaeac1d1f1edacac1ab0a,OP,fb2a3d1b360f599abab99db8669f8308,5
|
|
||||||
|
|
||||||
SET 120 subscriber.by-imsi-901991234567891.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,FB2A3D1B360F599ABAB99DB8669F8308,7
|
|
||||||
SET_REPLY 120 subscriber.by-imsi-901991234567891.aud3g OK
|
|
||||||
|
|
||||||
GET 121 subscriber.by-imsi-901991234567891.aud3g
|
|
||||||
GET_REPLY 121 subscriber.by-imsi-901991234567891.aud3g MILENAGE,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,7
|
|
||||||
|
|
||||||
SET 122 subscriber.by-imsi-901991234567891.aud3g none
|
|
||||||
SET_REPLY 122 subscriber.by-imsi-901991234567891.aud3g OK
|
|
||||||
|
|
||||||
GET 123 subscriber.by-imsi-901991234567891.aud3g
|
|
||||||
GET_REPLY 123 subscriber.by-imsi-901991234567891.aud3g none
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
GET 1 subscriber.by-imsi-901991234567891.msisdn
|
|
||||||
GET_REPLY 1 subscriber.by-imsi-901991234567891.msisdn none
|
|
||||||
|
|
||||||
SET 2 subscriber.by-imsi-901991234567891.msisdn 555666
|
|
||||||
SET_REPLY 2 subscriber.by-imsi-901991234567891.msisdn OK
|
|
||||||
|
|
||||||
GET 3 subscriber.by-imsi-901991234567891.msisdn
|
|
||||||
GET_REPLY 3 subscriber.by-imsi-901991234567891.msisdn 555666
|
|
||||||
1777
doc/manuals/vty/hlr_vty_reference.xml
Normal file
1777
doc/manuals/vty/hlr_vty_reference.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||||
|
|||||||
@@ -30,4 +30,5 @@ enum hlr_ctrl_node {
|
|||||||
_LAST_CTRL_NODE_HLR
|
_LAST_CTRL_NODE_HLR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int hlr_ctrl_cmds_install();
|
||||||
struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr);
|
struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr);
|
||||||
|
|||||||
@@ -4,18 +4,10 @@
|
|||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
||||||
#include <osmocom/gsupclient/cni_peer_id.h>
|
#include <osmocom/gsupclient/cni_peer_id.h>
|
||||||
#include <osmocom/gsm/gsup.h>
|
|
||||||
|
|
||||||
struct hlr;
|
struct hlr;
|
||||||
|
|
||||||
enum stmt_idx {
|
enum stmt_idx {
|
||||||
DB_STMT_SEL_ALL,
|
|
||||||
DB_STMT_SEL_ALL_ORDER_LAST_SEEN,
|
|
||||||
DB_STMT_SEL_FILTER_MSISDN,
|
|
||||||
DB_STMT_SEL_FILTER_IMSI,
|
|
||||||
DB_STMT_SEL_FILTER_IMEI,
|
|
||||||
DB_STMT_SEL_FILTER_CS,
|
|
||||||
DB_STMT_SEL_FILTER_PS,
|
|
||||||
DB_STMT_SEL_BY_IMSI,
|
DB_STMT_SEL_BY_IMSI,
|
||||||
DB_STMT_SEL_BY_MSISDN,
|
DB_STMT_SEL_BY_MSISDN,
|
||||||
DB_STMT_SEL_BY_ID,
|
DB_STMT_SEL_BY_ID,
|
||||||
@@ -41,9 +33,6 @@ enum stmt_idx {
|
|||||||
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_BY_MSISDN,
|
DB_STMT_EXISTS_BY_MSISDN,
|
||||||
DB_STMT_IND_ADD,
|
|
||||||
DB_STMT_IND_SELECT,
|
|
||||||
DB_STMT_IND_DEL,
|
|
||||||
_NUM_DB_STMT
|
_NUM_DB_STMT
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,8 +59,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,
|
||||||
@@ -121,7 +110,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,9 +148,6 @@ int db_subscr_update_imei_by_imsi(struct db_context *dbc, const char* imsi, cons
|
|||||||
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_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,
|
|
||||||
void (*get_cb)(struct hlr_subscriber *subscr, void *data), void *data,
|
|
||||||
int *count, const char **err);
|
|
||||||
int db_subscr_get_by_imsi(struct db_context *dbc, const char *imsi,
|
int db_subscr_get_by_imsi(struct db_context *dbc, const char *imsi,
|
||||||
struct hlr_subscriber *subscr);
|
struct hlr_subscriber *subscr);
|
||||||
int db_subscr_get_by_msisdn(struct db_context *dbc, const char *msisdn,
|
int db_subscr_get_by_msisdn(struct db_context *dbc, const char *msisdn,
|
||||||
@@ -177,9 +163,6 @@ int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
|
|||||||
int db_subscr_purge(struct db_context *dbc, const char *by_imsi,
|
int db_subscr_purge(struct db_context *dbc, const char *by_imsi,
|
||||||
bool purge_val, bool is_ps);
|
bool purge_val, bool is_ps);
|
||||||
|
|
||||||
int db_ind(struct db_context *dbc, const struct osmo_cni_peer_id *vlr, unsigned int *ind);
|
|
||||||
int db_ind_del(struct db_context *dbc, const struct osmo_cni_peer_id *vlr);
|
|
||||||
|
|
||||||
/*! Call sqlite3_column_text() and copy result to a char[].
|
/*! Call sqlite3_column_text() and copy result to a char[].
|
||||||
* \param[out] buf A char[] used as sizeof() arg(!) and osmo_strlcpy() target.
|
* \param[out] buf A char[] used as sizeof() arg(!) and osmo_strlcpy() target.
|
||||||
* \param[in] stmt An sqlite3_stmt*.
|
* \param[in] stmt An sqlite3_stmt*.
|
||||||
|
|||||||
@@ -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_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)
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ struct osmo_gsup_conn {
|
|||||||
//struct oap_state oap_state;
|
//struct oap_state oap_state;
|
||||||
struct tlv_parsed ccm;
|
struct tlv_parsed ccm;
|
||||||
|
|
||||||
|
unsigned int auc_3g_ind; /*!< IND index used for UMTS AKA SQN */
|
||||||
|
|
||||||
/* Set when Location Update is received: */
|
/* Set when Location Update is received: */
|
||||||
bool supports_cs; /* client supports OSMO_GSUP_CN_DOMAIN_CS */
|
bool supports_cs; /* client supports OSMO_GSUP_CN_DOMAIN_CS */
|
||||||
bool supports_ps; /* client supports OSMO_GSUP_CN_DOMAIN_PS */
|
bool supports_ps; /* client supports OSMO_GSUP_CN_DOMAIN_PS */
|
||||||
@@ -69,6 +71,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);
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
|
||||||
#include <osmocom/core/linuxlist.h>
|
#include <osmocom/core/linuxlist.h>
|
||||||
#include <osmocom/gsm/ipa.h>
|
#include <osmocom/gsm/ipa.h>
|
||||||
#include <osmocom/core/tdef.h>
|
#include <osmocom/core/tdef.h>
|
||||||
@@ -49,6 +48,7 @@ struct hlr {
|
|||||||
|
|
||||||
/* Control Interface */
|
/* Control Interface */
|
||||||
struct ctrl_handle *ctrl;
|
struct ctrl_handle *ctrl;
|
||||||
|
const char *ctrl_bind_addr;
|
||||||
|
|
||||||
/* Local bind addr */
|
/* Local bind addr */
|
||||||
char *gsup_bind_addr;
|
char *gsup_bind_addr;
|
||||||
@@ -56,16 +56,6 @@ 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;
|
|
||||||
enum gsm48_gmm_cause 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;
|
||||||
|
|||||||
@@ -35,19 +35,9 @@ enum hlr_vty_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_MAX_KEY_LEN 16
|
|
||||||
#define A38_XOR2G_KEY_LEN 16
|
|
||||||
#define A38_COMP128_KEY_LEN 16
|
|
||||||
#define MILENAGE_KEY_LEN 16
|
|
||||||
|
|
||||||
int hlr_vty_is_config_node(struct vty *vty, int node);
|
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);
|
||||||
void dgsm_vty_init(void);
|
void dgsm_vty_init(void);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ enum {
|
|||||||
DMSLOOKUP,
|
DMSLOOKUP,
|
||||||
DLU,
|
DLU,
|
||||||
DDGSM,
|
DDGSM,
|
||||||
DCTRL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct log_info hlr_log_info;
|
extern const struct log_info hlr_log_info;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ struct osmo_mdns_rfc_header {
|
|||||||
uint16_t nscount; /* Number of authority records */
|
uint16_t nscount; /* Number of authority records */
|
||||||
uint16_t arcount; /* Number of additional records */
|
uint16_t arcount; /* Number of additional records */
|
||||||
#elif OSMO_IS_BIG_ENDIAN
|
#elif OSMO_IS_BIG_ENDIAN
|
||||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
|
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
uint8_t qr:1, opcode:4, aa:1, tc:1, rd:1;
|
uint8_t qr:1, opcode:4, aa:1, tc:1, rd:1;
|
||||||
uint8_t ra:1, z:3, rcode:4;
|
uint8_t ra:1, z:3, rcode:4;
|
||||||
@@ -99,12 +99,15 @@ struct osmo_mdns_rfc_record {
|
|||||||
uint8_t *rdata;
|
uint8_t *rdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char *osmo_mdns_rfc_qname_encode(void *ctx, const char *domain);
|
||||||
|
char *osmo_mdns_rfc_qname_decode(void *ctx, const char *qname, size_t qname_len);
|
||||||
|
|
||||||
void osmo_mdns_rfc_header_encode(struct msgb *msg, const struct osmo_mdns_rfc_header *hdr);
|
void osmo_mdns_rfc_header_encode(struct msgb *msg, const struct osmo_mdns_rfc_header *hdr);
|
||||||
int osmo_mdns_rfc_header_decode(const uint8_t *data, size_t data_len, struct osmo_mdns_rfc_header *hdr);
|
int osmo_mdns_rfc_header_decode(const uint8_t *data, size_t data_len, struct osmo_mdns_rfc_header *hdr);
|
||||||
|
|
||||||
int osmo_mdns_rfc_question_encode(struct msgb *msg, const struct osmo_mdns_rfc_question *qst);
|
int osmo_mdns_rfc_question_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_question *qst);
|
||||||
struct osmo_mdns_rfc_question *osmo_mdns_rfc_question_decode(void *ctx, const uint8_t *data, size_t data_len);
|
struct osmo_mdns_rfc_question *osmo_mdns_rfc_question_decode(void *ctx, const uint8_t *data, size_t data_len);
|
||||||
|
|
||||||
int osmo_mdns_rfc_record_encode(struct msgb *msg, const struct osmo_mdns_rfc_record *rec);
|
int osmo_mdns_rfc_record_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_record *rec);
|
||||||
struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_t *data, size_t data_len,
|
struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_t *data, size_t data_len,
|
||||||
size_t *record_len);
|
size_t *record_len);
|
||||||
|
|||||||
16
sql/hlr.sql
16
sql/hlr.sql
@@ -71,24 +71,16 @@ 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
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE ind (
|
|
||||||
-- 3G auth IND pool to be used for this VLR
|
|
||||||
ind INTEGER PRIMARY KEY,
|
|
||||||
-- VLR identification, usually the GSUP source_name
|
|
||||||
vlr TEXT NOT NULL,
|
|
||||||
UNIQUE (vlr)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi);
|
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 = 5;
|
||||||
|
|||||||
@@ -111,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" \
|
||||||
>> "$@"
|
>> "$@"
|
||||||
|
|||||||
21
src/auc.c
21
src/auc.c
@@ -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);
|
||||||
|
|||||||
420
src/ctrl.c
420
src/ctrl.c
@@ -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>
|
||||||
@@ -31,16 +31,12 @@
|
|||||||
#include <osmocom/hlr/hlr.h>
|
#include <osmocom/hlr/hlr.h>
|
||||||
#include <osmocom/hlr/ctrl.h>
|
#include <osmocom/hlr/ctrl.h>
|
||||||
#include <osmocom/hlr/db.h>
|
#include <osmocom/hlr/db.h>
|
||||||
#include <osmocom/hlr/hlr_vty.h>
|
|
||||||
|
|
||||||
#define SEL_BY "by-"
|
#define SEL_BY "by-"
|
||||||
#define SEL_BY_IMSI SEL_BY "imsi-"
|
#define SEL_BY_IMSI SEL_BY "imsi-"
|
||||||
#define SEL_BY_MSISDN SEL_BY "msisdn-"
|
#define SEL_BY_MSISDN SEL_BY "msisdn-"
|
||||||
#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,
|
|
||||||
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc);
|
|
||||||
|
|
||||||
#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
|
#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
|
||||||
|
|
||||||
static bool startswith(const char *str, const char *start)
|
static bool startswith(const char *str, const char *start)
|
||||||
@@ -166,7 +162,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 +174,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 +183,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,82 +192,11 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTRL_CMD_DEFINE_WO_NOVRF(subscr_create, "create");
|
|
||||||
static int set_subscr_create(struct ctrl_cmd *cmd, void *data)
|
|
||||||
{
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
struct hlr *hlr = data;
|
|
||||||
const char *imsi = cmd->value;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (!osmo_imsi_str_valid(imsi)) {
|
|
||||||
cmd->reply = "Invalid IMSI value.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the subscriber in the DB */
|
|
||||||
rc = db_subscr_create(g_hlr->dbc, imsi, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS);
|
|
||||||
if (rc) {
|
|
||||||
if (rc == -EEXIST)
|
|
||||||
cmd->reply = "Subscriber already exists.";
|
|
||||||
else
|
|
||||||
cmd->reply = "Cannot create subscriber.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGP(DCTRL, LOGL_INFO, "Created subscriber IMSI='%s'\n",
|
|
||||||
imsi);
|
|
||||||
|
|
||||||
/* Retrieve data of newly created subscriber: */
|
|
||||||
rc = db_subscr_get_by_imsi(hlr->dbc, imsi, &subscr);
|
|
||||||
if (rc < 0) {
|
|
||||||
cmd->reply = "Failed retrieving ID of newly created subscriber.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->reply = talloc_asprintf(cmd, "%" PRIu64, subscr.id);
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTRL_CMD_DEFINE_WO_NOVRF(subscr_delete, "delete");
|
|
||||||
static int set_subscr_delete(struct ctrl_cmd *cmd, void *data)
|
|
||||||
{
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
struct hlr *hlr = data;
|
|
||||||
const char *imsi = cmd->value;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (!osmo_imsi_str_valid(imsi)) {
|
|
||||||
cmd->reply = "Invalid IMSI value.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve data of newly created subscriber: */
|
|
||||||
rc = db_subscr_get_by_imsi(hlr->dbc, imsi, &subscr);
|
|
||||||
if (rc < 0) {
|
|
||||||
cmd->reply = "Subscriber doesn't exist.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the subscriber in the DB */
|
|
||||||
rc = db_subscr_delete_by_id(g_hlr->dbc, subscr.id);
|
|
||||||
if (rc) {
|
|
||||||
cmd->reply = "Cannot delete subscriber.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGP(DCTRL, LOGL_INFO, "Deleted subscriber IMSI='%s'\n",
|
|
||||||
imsi);
|
|
||||||
|
|
||||||
cmd->reply = talloc_asprintf(cmd, "%" PRIu64, subscr.id);
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTRL_CMD_DEFINE_RO(subscr_info, "info");
|
CTRL_CMD_DEFINE_RO(subscr_info, "info");
|
||||||
static int get_subscr_info(struct ctrl_cmd *cmd, void *data)
|
static int get_subscr_info(struct ctrl_cmd *cmd, void *data)
|
||||||
{
|
{
|
||||||
@@ -291,8 +216,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 +252,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,302 +351,17 @@ 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(subscr_msisdn, "msisdn");
|
int hlr_ctrl_cmds_install()
|
||||||
static int verify_subscr_msisdn(struct ctrl_cmd *cmd, const char *value, void *data)
|
|
||||||
{
|
{
|
||||||
struct hlr_subscriber subscr;
|
int rc = 0;
|
||||||
if (!value)
|
|
||||||
return 1;
|
|
||||||
if (strlen(value) > sizeof(subscr.msisdn) - 1)
|
|
||||||
return 1;
|
|
||||||
if (strcmp(value, "none") != 0 && !osmo_msisdn_str_valid(value))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static int get_subscr_msisdn(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))
|
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info);
|
||||||
return CTRL_CMD_ERROR;
|
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_aud);
|
||||||
|
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_cs_enabled);
|
||||||
|
|
||||||
if (strlen(subscr.msisdn) == 0)
|
return rc;
|
||||||
snprintf(subscr.msisdn, sizeof(subscr.msisdn), "none");
|
|
||||||
|
|
||||||
cmd->reply = talloc_asprintf(cmd, "%s", subscr.msisdn);
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
static int set_subscr_msisdn(struct ctrl_cmd *cmd, void *data)
|
|
||||||
{
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
struct hlr *hlr = data;
|
|
||||||
const char *by_selector = cmd->node;
|
|
||||||
const char *msisdn;
|
|
||||||
|
|
||||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
|
|
||||||
if (strcmp(cmd->value, "none") == 0)
|
|
||||||
msisdn = NULL;
|
|
||||||
else
|
|
||||||
msisdn = cmd->value;
|
|
||||||
|
|
||||||
if (db_subscr_update_msisdn_by_imsi(g_hlr->dbc, subscr.imsi, msisdn)) {
|
|
||||||
cmd->reply = "Update MSISDN failed";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->reply = "OK";
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* value format: <algo[,KI]> */
|
|
||||||
CTRL_CMD_DEFINE(subscr_aud2g, "aud2g");
|
|
||||||
static int verify_subscr_aud2g(struct ctrl_cmd *cmd, const char *value, void *data)
|
|
||||||
{
|
|
||||||
if (!value)
|
|
||||||
return 1;
|
|
||||||
if (strcasecmp(value, "none") != 0 && !strchr(value, ','))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static int get_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
|
|
||||||
{
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
struct hlr *hlr = data;
|
|
||||||
const char *by_selector = cmd->node;
|
|
||||||
struct osmo_sub_auth_data2 aud2g;
|
|
||||||
struct osmo_sub_auth_data2 aud3g_unused;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
|
|
||||||
rc = db_get_auth_data(hlr->dbc, subscr.imsi, &aud2g, &aud3g_unused, NULL);
|
|
||||||
switch (rc) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case -ENOENT:
|
|
||||||
case -ENOKEY:
|
|
||||||
aud2g.algo = OSMO_AUTH_ALG_NONE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cmd->reply = "Error retrieving data from database.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aud2g.algo == OSMO_AUTH_ALG_NONE) {
|
|
||||||
cmd->reply = "none";
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->reply = talloc_asprintf(cmd, "%s,%s", osmo_auth_alg_name(aud2g.algo),
|
|
||||||
hexdump_buf(aud2g.u.gsm.ki));
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
static int set_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
|
|
||||||
{
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
struct hlr *hlr = data;
|
|
||||||
const char *by_selector = cmd->node;
|
|
||||||
char *tmp = NULL, *tok, *saveptr;
|
|
||||||
int minlen = 0;
|
|
||||||
int maxlen = 0;
|
|
||||||
struct sub_auth_data_str aud2g = {
|
|
||||||
.type = OSMO_AUTH_TYPE_GSM
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
|
|
||||||
tmp = talloc_strdup(cmd, cmd->value);
|
|
||||||
if (!tmp) {
|
|
||||||
cmd->reply = "OOM";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse alg_type: */
|
|
||||||
tok = strtok_r(tmp, ",", &saveptr);
|
|
||||||
if (!tok) {
|
|
||||||
cmd->reply = "Invalid format";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
if (strcmp(tok, "none") == 0) {
|
|
||||||
aud2g.algo = OSMO_AUTH_ALG_NONE;
|
|
||||||
} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
|
|
||||||
cmd->reply = "Unknown auth algorithm.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aud2g.algo != OSMO_AUTH_ALG_NONE) {
|
|
||||||
tok = strtok_r(NULL, "\0", &saveptr);
|
|
||||||
if (!tok) {
|
|
||||||
cmd->reply = "Invalid format.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
aud2g.u.gsm.ki = tok;
|
|
||||||
if (!osmo_is_hexstr(aud2g.u.gsm.ki, minlen * 2, maxlen * 2, true)) {
|
|
||||||
cmd->reply = "Invalid KI.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud2g)) {
|
|
||||||
cmd->reply = "Update aud2g failed.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->reply = "OK";
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* value format: <algo[,KI,(op|opc),OP_C[,ind_bitlen]]> */
|
|
||||||
CTRL_CMD_DEFINE(subscr_aud3g, "aud3g");
|
|
||||||
static int verify_subscr_aud3g(struct ctrl_cmd *cmd, const char *value, void *data)
|
|
||||||
{
|
|
||||||
if (!value)
|
|
||||||
return 1;
|
|
||||||
if (strcasecmp(value, "none") != 0 && !strchr(value, ','))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
|
||||||
{
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
struct hlr *hlr = data;
|
|
||||||
const char *by_selector = cmd->node;
|
|
||||||
struct osmo_sub_auth_data2 aud2g_unused;
|
|
||||||
struct osmo_sub_auth_data2 aud3g;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
|
|
||||||
rc = db_get_auth_data(hlr->dbc, subscr.imsi, &aud2g_unused, &aud3g, NULL);
|
|
||||||
switch (rc) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case -ENOENT:
|
|
||||||
case -ENOKEY:
|
|
||||||
aud3g.algo = OSMO_AUTH_ALG_NONE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cmd->reply = "Error retrieving data from database.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aud3g.algo == OSMO_AUTH_ALG_NONE) {
|
|
||||||
cmd->reply = "none";
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
aud3g.u.umts.opc_is_op ? "OP" : "OPC",
|
|
||||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, aud3g.u.umts.opc_len),
|
|
||||||
aud3g.u.umts.ind_bitlen);
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
|
||||||
static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
|
||||||
{
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
struct hlr *hlr = data;
|
|
||||||
const char *by_selector = cmd->node;
|
|
||||||
char *tmp = NULL, *tok, *saveptr;
|
|
||||||
int minlen = 0, minlen_opc = 0;
|
|
||||||
int maxlen = 0, maxlen_opc = 0;
|
|
||||||
struct sub_auth_data_str aud3g = {
|
|
||||||
.type = OSMO_AUTH_TYPE_UMTS,
|
|
||||||
.u.umts = {
|
|
||||||
.ind_bitlen = 5,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
bool ind_bitlen_present;
|
|
||||||
|
|
||||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
|
|
||||||
tmp = talloc_strdup(cmd, cmd->value);
|
|
||||||
if (!tmp) {
|
|
||||||
cmd->reply = "OOM";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse alg_type: */
|
|
||||||
tok = strtok_r(tmp, ",", &saveptr);
|
|
||||||
if (!tok) {
|
|
||||||
cmd->reply = "Invalid format.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
if (strcmp(tok, "none") == 0) {
|
|
||||||
aud3g.algo = OSMO_AUTH_ALG_NONE;
|
|
||||||
} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
|
|
||||||
cmd->reply = "Unknown auth algorithm.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aud3g.algo != OSMO_AUTH_ALG_NONE) {
|
|
||||||
/* Parse K */
|
|
||||||
tok = strtok_r(NULL, ",", &saveptr);
|
|
||||||
if (!tok) {
|
|
||||||
cmd->reply = "Invalid format.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
aud3g.u.umts.k = tok;
|
|
||||||
if (!osmo_is_hexstr(aud3g.u.umts.k, minlen * 2, maxlen * 2, true)) {
|
|
||||||
cmd->reply = "Invalid KI.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse OP/OPC choice */
|
|
||||||
tok = strtok_r(NULL, ",", &saveptr);
|
|
||||||
if (!tok) {
|
|
||||||
cmd->reply = "Invalid format.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
if (strcasecmp(tok, "op") == 0) {
|
|
||||||
aud3g.u.umts.opc_is_op = true;
|
|
||||||
} else if (strcasecmp(tok, "opc") == 0) {
|
|
||||||
aud3g.u.umts.opc_is_op = false;
|
|
||||||
} else {
|
|
||||||
cmd->reply = "Invalid format.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse OP/OPC value */
|
|
||||||
ind_bitlen_present = !!strchr(saveptr, ',');
|
|
||||||
tok = strtok_r(NULL, ind_bitlen_present ? "," : "\0", &saveptr);
|
|
||||||
if (!tok) {
|
|
||||||
cmd->reply = "Invalid format.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
aud3g.u.umts.opc = tok;
|
|
||||||
if (!osmo_is_hexstr(aud3g.u.umts.opc, minlen_opc * 2, maxlen_opc * 2, true)) {
|
|
||||||
cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC.");
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ind_bitlen_present) {
|
|
||||||
/* Parse bitlen_ind */
|
|
||||||
tok = strtok_r(NULL, "\0", &saveptr);
|
|
||||||
if (!tok || tok[0] == '\0') {
|
|
||||||
cmd->reply = "Invalid format.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
aud3g.u.umts.ind_bitlen = atoi(tok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud3g)) {
|
|
||||||
cmd->reply = "Update aud3g failed.";
|
|
||||||
return CTRL_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->reply = "OK";
|
|
||||||
return CTRL_CMD_REPLY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hlr_ctrl_node_lookup(void *data, vector vline, int *node_type,
|
static int hlr_ctrl_node_lookup(void *data, vector vline, int *node_type,
|
||||||
@@ -749,30 +389,14 @@ static int hlr_ctrl_node_lookup(void *data, vector vline, int *node_type,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hlr_ctrl_cmds_install(void)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR, &cmd_subscr_create);
|
|
||||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR, &cmd_subscr_delete);
|
|
||||||
|
|
||||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info);
|
|
||||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_aud);
|
|
||||||
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_cs_enabled);
|
|
||||||
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_aud3g);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr)
|
struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct ctrl_handle *hdl = ctrl_interface_setup2(hlr, OSMO_CTRL_PORT_HLR, hlr_ctrl_node_lookup,
|
struct ctrl_handle *hdl = ctrl_interface_setup_dynip2(hlr,
|
||||||
_LAST_CTRL_NODE_HLR);
|
hlr->ctrl_bind_addr,
|
||||||
|
OSMO_CTRL_PORT_HLR,
|
||||||
|
hlr_ctrl_node_lookup,
|
||||||
|
_LAST_CTRL_NODE_HLR);
|
||||||
if (!hdl)
|
if (!hdl)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|||||||
94
src/db.c
94
src/db.c
@@ -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 5
|
||||||
|
|
||||||
#define SEL_COLUMNS \
|
#define SEL_COLUMNS \
|
||||||
"id," \
|
"id," \
|
||||||
@@ -51,14 +51,6 @@
|
|||||||
"sgsn_via_proxy"
|
"sgsn_via_proxy"
|
||||||
|
|
||||||
static const char *stmt_sql[] = {
|
static const char *stmt_sql[] = {
|
||||||
[DB_STMT_SEL_ALL] = "SELECT " SEL_COLUMNS " FROM subscriber;",
|
|
||||||
[DB_STMT_SEL_ALL_ORDER_LAST_SEEN] = "SELECT " SEL_COLUMNS " FROM subscriber "
|
|
||||||
"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_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_CS] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE nam_cs = $search ORDER BY last_lu_seen",
|
|
||||||
[DB_STMT_SEL_FILTER_PS] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE nam_ps = $search ORDER BY last_lu_seen",
|
|
||||||
[DB_STMT_SEL_BY_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi = ?",
|
[DB_STMT_SEL_BY_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi = ?",
|
||||||
[DB_STMT_SEL_BY_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn = ?",
|
[DB_STMT_SEL_BY_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn = ?",
|
||||||
[DB_STMT_SEL_BY_ID] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE id = ?",
|
[DB_STMT_SEL_BY_ID] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE id = ?",
|
||||||
@@ -93,9 +85,6 @@ static const char *stmt_sql[] = {
|
|||||||
[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_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_SELECT] = "SELECT ind FROM ind WHERE vlr = $vlr",
|
|
||||||
[DB_STMT_IND_DEL] = "DELETE FROM ind WHERE vlr = $vlr",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sql3_error_log_cb(void *arg, int err_code, const char *msg)
|
static void sql3_error_log_cb(void *arg, int err_code, const char *msg)
|
||||||
@@ -235,9 +224,9 @@ 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;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < statements_count; i++) {
|
for (i = 0; i < statements_count; i++) {
|
||||||
const char *stmt_str = statements[i];
|
const char *stmt_str = statements[i];
|
||||||
@@ -308,7 +297,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",
|
||||||
};
|
};
|
||||||
@@ -324,7 +313,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",
|
||||||
};
|
};
|
||||||
@@ -437,7 +426,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",
|
||||||
@@ -460,7 +449,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",
|
||||||
};
|
};
|
||||||
@@ -476,7 +465,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",
|
||||||
@@ -490,69 +479,6 @@ static int db_upgrade_v5(struct db_context *dbc)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int db_upgrade_v6(struct db_context *dbc)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
const char * const statements[] = {
|
|
||||||
"CREATE TABLE ind (\n"
|
|
||||||
" -- 3G auth IND pool to be used for this VLR\n"
|
|
||||||
" ind INTEGER PRIMARY KEY,\n"
|
|
||||||
" -- VLR identification, usually the GSUP source_name\n"
|
|
||||||
" vlr TEXT NOT NULL,\n"
|
|
||||||
" UNIQUE (vlr)\n"
|
|
||||||
")"
|
|
||||||
,
|
|
||||||
"PRAGMA user_version = 6",
|
|
||||||
};
|
|
||||||
|
|
||||||
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 6\n");
|
|
||||||
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,
|
||||||
@@ -560,8 +486,6 @@ static db_upgrade_func_t db_upgrade_path[] = {
|
|||||||
db_upgrade_v3,
|
db_upgrade_v3,
|
||||||
db_upgrade_v4,
|
db_upgrade_v4,
|
||||||
db_upgrade_v5,
|
db_upgrade_v5,
|
||||||
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)
|
||||||
|
|||||||
48
src/db_auc.c
48
src/db_auc.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,11 +95,8 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, s
|
|||||||
LOGAUC(imsi, LOGL_ERROR, "Error reading %s\n", col_name);
|
LOGAUC(imsi, LOGL_ERROR, "Error reading %s\n", col_name);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
osmo_hexparse((void *)text, dst, dst_len);
|
||||||
if (osmo_hexparse((void *)text, dst, dst_len_max) != col_len)
|
return 0;
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
return col_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* obtain the authentication data for a given imsi
|
/* obtain the authentication data for a given imsi
|
||||||
@@ -113,8 +104,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 +139,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 +148,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 +191,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;
|
||||||
|
|||||||
208
src/db_hlr.c
208
src/db_hlr.c
@@ -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
|
||||||
*
|
*
|
||||||
@@ -45,8 +45,7 @@
|
|||||||
* \param[in,out] dbc database context.
|
* \param[in,out] dbc database context.
|
||||||
* \param[in] imsi ASCII string of IMSI digits, is validated.
|
* \param[in] imsi ASCII string of IMSI digits, is validated.
|
||||||
* \param[in] flags Bitmask of DB_SUBSCR_FLAG_*.
|
* \param[in] flags Bitmask of DB_SUBSCR_FLAG_*.
|
||||||
* \returns 0 on success, -EINVAL on invalid IMSI, -EEXIST if subscriber with
|
* \returns 0 on success, -EINVAL on invalid IMSI, -EIO on database error.
|
||||||
* provided imsi already exists, -EIO on other database errors.
|
|
||||||
*/
|
*/
|
||||||
int db_subscr_create(struct db_context *dbc, const char *imsi, uint8_t flags)
|
int db_subscr_create(struct db_context *dbc, const char *imsi, uint8_t flags)
|
||||||
{
|
{
|
||||||
@@ -74,8 +73,6 @@ int db_subscr_create(struct db_context *dbc, const char *imsi, uint8_t flags)
|
|||||||
if (rc != SQLITE_DONE) {
|
if (rc != SQLITE_DONE) {
|
||||||
LOGHLR(imsi, LOGL_ERROR, "Cannot create subscriber: SQL error: (%d) %s\n",
|
LOGHLR(imsi, LOGL_ERROR, "Cannot create subscriber: SQL error: (%d) %s\n",
|
||||||
rc, sqlite3_errmsg(dbc->db));
|
rc, sqlite3_errmsg(dbc->db));
|
||||||
if (rc == SQLITE_CONSTRAINT_UNIQUE)
|
|
||||||
return -EEXIST;
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,9 +235,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 +264,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:
|
|
||||||
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:
|
case OSMO_AUTH_ALG_XOR:
|
||||||
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 +281,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;
|
||||||
@@ -630,94 +625,6 @@ int db_subscr_get_by_msisdn(struct db_context *dbc, const char *msisdn,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Retrieve subscriber data from the HLR database.
|
|
||||||
* \param[in,out] dbc database context.
|
|
||||||
* \param[in] filter_type ASCII string of identifier type to search.
|
|
||||||
* \param[in] filter ASCII string to search.
|
|
||||||
* \param[in] get_cb pointer to call back function for data.
|
|
||||||
* \param[in,out] data pointer to pass to callback function.
|
|
||||||
* \param[in,out] count counter for number of matched subscribers.
|
|
||||||
* \param[in,our] err
|
|
||||||
* \returns 0 on success, -ENOENT if no subscriber was found, -EIO on
|
|
||||||
* database error.
|
|
||||||
*/
|
|
||||||
int db_subscrs_get(struct db_context *dbc, const char *filter_type, const char *filter,
|
|
||||||
void (*get_cb)(struct hlr_subscriber *subscr, void *data), void *data,
|
|
||||||
int *count, const char **err)
|
|
||||||
{
|
|
||||||
sqlite3_stmt *stmt;
|
|
||||||
char search[256];
|
|
||||||
int rc;
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
bool show_ls = false;
|
|
||||||
|
|
||||||
if (!filter_type) {
|
|
||||||
stmt = dbc->stmt[DB_STMT_SEL_ALL];
|
|
||||||
} else if (strcmp(filter_type, "imei") == 0) {
|
|
||||||
stmt = dbc->stmt[DB_STMT_SEL_FILTER_IMEI];
|
|
||||||
} else if (strcmp(filter_type, "imsi") == 0) {
|
|
||||||
stmt = dbc->stmt[DB_STMT_SEL_FILTER_IMSI];
|
|
||||||
} else if (strcmp(filter_type, "msisdn") == 0) {
|
|
||||||
stmt = dbc->stmt[DB_STMT_SEL_FILTER_MSISDN];
|
|
||||||
} else if (strcmp(filter_type, "cs") == 0) {
|
|
||||||
stmt = dbc->stmt[DB_STMT_SEL_FILTER_CS];
|
|
||||||
} else if (strcmp(filter_type, "ps") == 0) {
|
|
||||||
stmt = dbc->stmt[DB_STMT_SEL_FILTER_PS];
|
|
||||||
} else if (strcmp(filter_type, "last_lu_seen") == 0) {
|
|
||||||
show_ls = true;
|
|
||||||
stmt = dbc->stmt[DB_STMT_SEL_ALL_ORDER_LAST_SEEN];
|
|
||||||
} else {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter_type && filter && strcmp(filter_type, "last_lu_seen") != 0) {
|
|
||||||
if (strcmp(filter, "on") == 0) {
|
|
||||||
sprintf(search, "%s", "1");
|
|
||||||
} else if (strcmp(filter, "off") == 0) {
|
|
||||||
sprintf(search, "%s", "0");
|
|
||||||
} else {
|
|
||||||
sprintf(search, "%%%s%%", filter);
|
|
||||||
}
|
|
||||||
if (!db_bind_text(stmt, "$search", search)) {
|
|
||||||
*err = sqlite3_errmsg(dbc->db);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = sqlite3_step(stmt);
|
|
||||||
|
|
||||||
if (rc == SQLITE_DONE) {
|
|
||||||
db_remove_reset(stmt);
|
|
||||||
*err = "No matching subscriber(s)";
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (rc == SQLITE_ROW) {
|
|
||||||
subscr = (struct hlr_subscriber){
|
|
||||||
.id = sqlite3_column_int64(stmt, 0),};
|
|
||||||
copy_sqlite3_text_to_buf(subscr.imsi, stmt, 1);
|
|
||||||
copy_sqlite3_text_to_buf(subscr.msisdn, stmt, 2);
|
|
||||||
copy_sqlite3_text_to_buf(subscr.imei, stmt, 3);
|
|
||||||
subscr.nam_cs = sqlite3_column_int(stmt, 9);
|
|
||||||
subscr.nam_ps = sqlite3_column_int(stmt, 10);
|
|
||||||
if (show_ls)
|
|
||||||
parse_last_lu_seen(&subscr.last_lu_seen, (const char *)sqlite3_column_text(stmt, 14),
|
|
||||||
subscr.imsi, "CS");
|
|
||||||
get_cb(&subscr, data);
|
|
||||||
rc = sqlite3_step(stmt);
|
|
||||||
(*count)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
db_remove_reset(stmt);
|
|
||||||
if (rc != SQLITE_DONE) {
|
|
||||||
*err = sqlite3_errmsg(dbc->db);
|
|
||||||
LOGP(DAUC, LOGL_ERROR, "Cannot read subscribers from db:: %s\n", *err);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
*err = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! 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] id ID of the subscriber in the HLR db.
|
* \param[in] id ID of the subscriber in the HLR db.
|
||||||
@@ -977,106 +884,3 @@ out:
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _db_ind_run(struct db_context *dbc, sqlite3_stmt *stmt, const char *vlr, bool reset)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (!db_bind_text(stmt, "$vlr", vlr))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
/* execute the statement */
|
|
||||||
rc = sqlite3_step(stmt);
|
|
||||||
if (reset)
|
|
||||||
db_remove_reset(stmt);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _db_ind_add(struct db_context *dbc, const char *vlr)
|
|
||||||
{
|
|
||||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_IND_ADD];
|
|
||||||
if (_db_ind_run(dbc, stmt, vlr, true) != SQLITE_DONE) {
|
|
||||||
LOGP(DDB, LOGL_ERROR, "Cannot create IND entry for %s\n", osmo_quote_str_c(OTC_SELECT, vlr, -1));
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _db_ind_del(struct db_context *dbc, const char *vlr)
|
|
||||||
{
|
|
||||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_IND_DEL];
|
|
||||||
_db_ind_run(dbc, stmt, vlr, true);
|
|
||||||
/* We don't really care about the result. If it didn't exist, then that was the goal anyway. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _db_ind_get(struct db_context *dbc, const char *vlr, unsigned int *ind)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_IND_SELECT];
|
|
||||||
int rc = _db_ind_run(dbc, stmt, vlr, false);
|
|
||||||
if (rc == SQLITE_DONE) {
|
|
||||||
/* Does not exist yet */
|
|
||||||
ret = -ENOENT;
|
|
||||||
goto out;
|
|
||||||
} else if (rc != SQLITE_ROW) {
|
|
||||||
LOGP(DDB, LOGL_ERROR, "Error executing SQL: %d\n", rc);
|
|
||||||
ret = -EIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSMO_ASSERT(ind);
|
|
||||||
*ind = sqlite3_column_int64(stmt, 0);
|
|
||||||
out:
|
|
||||||
db_remove_reset(stmt);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _db_ind(struct db_context *dbc, const struct osmo_cni_peer_id *vlr,
|
|
||||||
unsigned int *ind, bool del)
|
|
||||||
{
|
|
||||||
const char *vlr_name = NULL;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
switch (vlr->type) {
|
|
||||||
case OSMO_CNI_PEER_ID_IPA_NAME:
|
|
||||||
if (vlr->ipa_name.len < 2 || vlr->ipa_name.val[vlr->ipa_name.len - 1] != '\0') {
|
|
||||||
LOGP(DDB, LOGL_ERROR, "Expecting VLR ipa_name to be zero terminated; found %s\n",
|
|
||||||
osmo_ipa_name_to_str(&vlr->ipa_name));
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
vlr_name = (const char*)vlr->ipa_name.val;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOGP(DDB, LOGL_ERROR, "Unsupported osmo_cni_peer_id type: %s\n",
|
|
||||||
osmo_cni_peer_id_type_name(vlr->type));
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (del)
|
|
||||||
return _db_ind_del(dbc, vlr_name);
|
|
||||||
|
|
||||||
rc = _db_ind_get(dbc, vlr_name, ind);
|
|
||||||
if (!rc)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Does not exist yet, create. */
|
|
||||||
rc = _db_ind_add(dbc, vlr_name);
|
|
||||||
if (rc) {
|
|
||||||
LOGP(DDB, LOGL_ERROR, "Error creating IND entry for %s\n", osmo_quote_str_c(OTC_SELECT, vlr_name, -1));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* To be sure, query again from scratch. */
|
|
||||||
return _db_ind_get(dbc, vlr_name, ind);
|
|
||||||
}
|
|
||||||
|
|
||||||
int db_ind(struct db_context *dbc, const struct osmo_cni_peer_id *vlr, unsigned int *ind)
|
|
||||||
{
|
|
||||||
return _db_ind(dbc, vlr, ind, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int db_ind_del(struct db_context *dbc, const struct osmo_cni_peer_id *vlr)
|
|
||||||
{
|
|
||||||
return _db_ind(dbc, vlr, NULL, true);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* Lesser General Public License for more details.
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
* $Id: dbd_helper.c,v 1.44 2011/08/09 11:14:14 mhoenicka Exp $
|
* $Id: dbd_helper.c,v 1.44 2011/08/09 11:14:14 mhoenicka Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ void dgsm_init(void *ctx)
|
|||||||
|
|
||||||
g_hlr->mslookup.server.local_attach_max_age = 60 * 60;
|
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 = 2000;
|
||||||
|
|
||||||
g_hlr->gsup_unit_name.unit_name = "HLR";
|
g_hlr->gsup_unit_name.unit_name = "HLR";
|
||||||
g_hlr->gsup_unit_name.serno = "unnamed-HLR";
|
g_hlr->gsup_unit_name.serno = "unnamed-HLR";
|
||||||
@@ -191,7 +191,7 @@ void dgsm_start(void *ctx)
|
|||||||
dgsm_mdns_client_config_apply();
|
dgsm_mdns_client_config_apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dgsm_stop(void)
|
void dgsm_stop()
|
||||||
{
|
{
|
||||||
g_hlr->mslookup.allow_startup = false;
|
g_hlr->mslookup.allow_startup = false;
|
||||||
mslookup_server_mdns_config_apply();
|
mslookup_server_mdns_config_apply();
|
||||||
|
|||||||
@@ -442,13 +442,13 @@ int config_write_mslookup(struct vty *vty)
|
|||||||
|
|
||||||
msc = mslookup_server_msc_get(&mslookup_server_msc_wildcard, false);
|
msc = mslookup_server_msc_get(&mslookup_server_msc_wildcard, false);
|
||||||
if (msc)
|
if (msc)
|
||||||
config_write_msc_services(vty, " ", msc);
|
config_write_msc_services(vty, " ", msc);
|
||||||
|
|
||||||
llist_for_each_entry(msc, &g_hlr->mslookup.server.local_site_services, entry) {
|
llist_for_each_entry(msc, &g_hlr->mslookup.server.local_site_services, entry) {
|
||||||
if (!osmo_ipa_name_cmp(&mslookup_server_msc_wildcard, &msc->name))
|
if (!osmo_ipa_name_cmp(&mslookup_server_msc_wildcard, &msc->name))
|
||||||
continue;
|
continue;
|
||||||
vty_out(vty, " msc ipa-name %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE);
|
vty_out(vty, " msc %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE);
|
||||||
config_write_msc_services(vty, " ", msc);
|
config_write_msc_services(vty, " ", msc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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. */
|
||||||
@@ -475,10 +475,6 @@ int config_write_mslookup(struct vty *vty)
|
|||||||
vty_out(vty, " mdns domain-suffix %s%s",
|
vty_out(vty, " mdns domain-suffix %s%s",
|
||||||
g_hlr->mslookup.client.mdns.domain_suffix,
|
g_hlr->mslookup.client.mdns.domain_suffix,
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
if (g_hlr->mslookup.client.result_timeout_milliseconds != OSMO_DGSM_DEFAULT_RESULT_TIMEOUT_MS)
|
|
||||||
vty_out(vty, " timeout %u%s",
|
|
||||||
g_hlr->mslookup.client.result_timeout_milliseconds,
|
|
||||||
VTY_NEWLINE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
#include <osmocom/core/msgb.h>
|
#include <osmocom/core/msgb.h>
|
||||||
#include <osmocom/core/logging.h>
|
#include <osmocom/core/logging.h>
|
||||||
@@ -32,7 +30,6 @@
|
|||||||
|
|
||||||
#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, \
|
||||||
@@ -180,9 +177,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,17 +315,41 @@ static int osmo_gsup_server_closed_cb(struct ipa_server_conn *conn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_fd_settings(int fd)
|
/* Add conn to the clients list in a way that conn->auc_3g_ind takes the lowest
|
||||||
|
* unused integer and the list of clients remains sorted by auc_3g_ind.
|
||||||
|
* Keep this function non-static to allow linking in a unit test. */
|
||||||
|
void osmo_gsup_server_add_conn(struct llist_head *clients,
|
||||||
|
struct osmo_gsup_conn *conn)
|
||||||
{
|
{
|
||||||
int ret;
|
struct osmo_gsup_conn *c;
|
||||||
int val;
|
struct osmo_gsup_conn *prev_conn;
|
||||||
|
|
||||||
/*TODO: Set keepalive settings here. See OS#4312 */
|
c = llist_first_entry_or_null(clients, struct osmo_gsup_conn, list);
|
||||||
|
|
||||||
val = 1;
|
/* Is the first index, 0, unused? */
|
||||||
ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
|
if (!c || c->auc_3g_ind > 0) {
|
||||||
if (ret < 0)
|
conn->auc_3g_ind = 0;
|
||||||
LOGP(DLGSUP, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
|
llist_add(&conn->list, clients);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for a gap later on */
|
||||||
|
prev_conn = NULL;
|
||||||
|
llist_for_each_entry(c, clients, list) {
|
||||||
|
/* skip first item, we know it has auc_3g_ind == 0. */
|
||||||
|
if (!prev_conn) {
|
||||||
|
prev_conn = c;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c->auc_3g_ind > prev_conn->auc_3g_ind + 1)
|
||||||
|
break;
|
||||||
|
prev_conn = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSMO_ASSERT(prev_conn);
|
||||||
|
|
||||||
|
conn->auc_3g_ind = prev_conn->auc_3g_ind + 1;
|
||||||
|
llist_add(&conn->list, &prev_conn->list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a client has connected to the server socket and we have accept()ed it */
|
/* a client has connected to the server socket and we have accept()ed it */
|
||||||
@@ -348,11 +371,10 @@ static int osmo_gsup_server_accept_cb(struct ipa_server_link *link, int fd)
|
|||||||
|
|
||||||
/* link data structure with server structure */
|
/* link data structure with server structure */
|
||||||
conn->server = gsups;
|
conn->server = gsups;
|
||||||
llist_add_tail(&conn->list, &gsups->clients);
|
osmo_gsup_server_add_conn(&gsups->clients, conn);
|
||||||
|
|
||||||
LOGP(DLGSUP, LOGL_INFO, "New GSUP client %s:%d\n", conn->conn->addr, conn->conn->port);
|
LOGP(DLGSUP, LOGL_INFO, "New GSUP client %s:%d (IND=%u)\n",
|
||||||
|
conn->conn->addr, conn->conn->port, conn->auc_3g_ind);
|
||||||
update_fd_settings(fd);
|
|
||||||
|
|
||||||
/* request the identity of the client */
|
/* request the identity of the client */
|
||||||
rc = ipa_ccm_send_id_req(fd);
|
rc = ipa_ccm_send_id_req(fd);
|
||||||
@@ -445,16 +467,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){
|
||||||
@@ -463,29 +488,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;
|
||||||
|
|||||||
@@ -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:0:1
|
LIBVERSION=0:0:0
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -31,8 +31,6 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
|
|
||||||
static void start_test_procedure(struct osmo_gsup_client *gsupc);
|
static void start_test_procedure(struct osmo_gsup_client *gsupc);
|
||||||
|
|
||||||
@@ -131,19 +129,6 @@ static void gsup_client_oap_register(struct osmo_gsup_client *gsupc)
|
|||||||
client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx);
|
client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_fd_settings(int fd)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
int val;
|
|
||||||
|
|
||||||
/*TODO: Set keepalive settings here. See OS#4312 */
|
|
||||||
|
|
||||||
val = 1;
|
|
||||||
ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
|
|
||||||
if (ret < 0)
|
|
||||||
LOGP(DLGSUP, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gsup_client_updown_cb(struct ipa_client_conn *link, int up)
|
static void gsup_client_updown_cb(struct ipa_client_conn *link, int up)
|
||||||
{
|
{
|
||||||
struct osmo_gsup_client *gsupc = link->data;
|
struct osmo_gsup_client *gsupc = link->data;
|
||||||
@@ -154,7 +139,6 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up)
|
|||||||
gsupc->is_connected = up;
|
gsupc->is_connected = up;
|
||||||
|
|
||||||
if (up) {
|
if (up) {
|
||||||
update_fd_settings(link->ofd->fd);
|
|
||||||
start_test_procedure(gsupc);
|
start_test_procedure(gsupc);
|
||||||
|
|
||||||
if (gsupc->oap_state.state == OSMO_OAP_INITIALIZED)
|
if (gsupc->oap_state.state == OSMO_OAP_INITIALIZED)
|
||||||
|
|||||||
72
src/hlr.c
72
src/hlr.c
@@ -85,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;
|
||||||
@@ -129,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,
|
||||||
@@ -278,14 +281,13 @@ int hlr_subscr_nam(struct hlr *hlr, struct hlr_subscriber *subscr, bool nam_val,
|
|||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
|
|
||||||
/* process an incoming SAI request */
|
/* process an incoming SAI request */
|
||||||
static int rx_send_auth_info(struct osmo_gsup_req *req)
|
static int rx_send_auth_info(unsigned int auc_3g_ind, struct osmo_gsup_req *req)
|
||||||
{
|
{
|
||||||
struct osmo_gsup_message gsup_out = {
|
struct osmo_gsup_message gsup_out = {
|
||||||
.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT,
|
.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT,
|
||||||
};
|
};
|
||||||
bool separation_bit = false;
|
bool separation_bit = false;
|
||||||
int num_auth_vectors = OSMO_GSUP_MAX_NUM_AUTH_INFO;
|
int num_auth_vectors = OSMO_GSUP_MAX_NUM_AUTH_INFO;
|
||||||
unsigned int auc_3g_ind;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
subscr_create_on_demand(req->gsup.imsi);
|
subscr_create_on_demand(req->gsup.imsi);
|
||||||
@@ -296,14 +298,6 @@ static int rx_send_auth_info(struct osmo_gsup_req *req)
|
|||||||
if (req->gsup.num_auth_vectors > 0 &&
|
if (req->gsup.num_auth_vectors > 0 &&
|
||||||
req->gsup.num_auth_vectors <= OSMO_GSUP_MAX_NUM_AUTH_INFO)
|
req->gsup.num_auth_vectors <= OSMO_GSUP_MAX_NUM_AUTH_INFO)
|
||||||
num_auth_vectors = req->gsup.num_auth_vectors;
|
num_auth_vectors = req->gsup.num_auth_vectors;
|
||||||
rc = db_ind(g_hlr->dbc, &req->source_name, &auc_3g_ind);
|
|
||||||
if (rc) {
|
|
||||||
LOG_GSUP_REQ(req, LOGL_ERROR,
|
|
||||||
"Unable to determine 3G auth IND for source %s (rc=%d),"
|
|
||||||
" generating tuples with IND = 0\n",
|
|
||||||
osmo_cni_peer_id_to_str(&req->source_name), rc);
|
|
||||||
auc_3g_ind = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = db_get_auc(g_hlr->dbc, req->gsup.imsi, auc_3g_ind,
|
rc = db_get_auc(g_hlr->dbc, req->gsup.imsi, auc_3g_ind,
|
||||||
gsup_out.auth_vectors,
|
gsup_out.auth_vectors,
|
||||||
@@ -321,7 +315,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, g_hlr->reject_cause, "IMSI unknown");
|
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "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");
|
||||||
@@ -523,7 +517,7 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
|
|||||||
switch (req->gsup.message_type) {
|
switch (req->gsup.message_type) {
|
||||||
/* requests sent to us */
|
/* requests sent to us */
|
||||||
case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
|
case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
|
||||||
rx_send_auth_info(req);
|
rx_send_auth_info(conn->auc_3g_ind, req);
|
||||||
break;
|
break;
|
||||||
case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
|
case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
|
||||||
rx_upd_loc_req(conn, req);
|
rx_upd_loc_req(conn, req);
|
||||||
@@ -565,12 +559,12 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_usage(void)
|
static void print_usage()
|
||||||
{
|
{
|
||||||
printf("Usage: osmo-hlr\n");
|
printf("Usage: osmo-hlr\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_help(void)
|
static void print_help()
|
||||||
{
|
{
|
||||||
printf(" -h --help This text.\n");
|
printf(" -h --help This text.\n");
|
||||||
printf(" -c --config-file filename The config file to use.\n");
|
printf(" -c --config-file filename The config file to use.\n");
|
||||||
@@ -583,10 +577,6 @@ static void print_help(void)
|
|||||||
printf(" -U --db-upgrade Allow HLR database schema upgrades.\n");
|
printf(" -U --db-upgrade Allow HLR database schema upgrades.\n");
|
||||||
printf(" -C --db-check Quit after opening (and upgrading) the database.\n");
|
printf(" -C --db-check Quit after opening (and upgrading) the database.\n");
|
||||||
printf(" -V --version Print the version of OsmoHLR.\n");
|
printf(" -V --version Print the version of OsmoHLR.\n");
|
||||||
|
|
||||||
printf("\nVTY reference generation:\n");
|
|
||||||
printf(" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n");
|
|
||||||
printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
@@ -602,37 +592,10 @@ static struct {
|
|||||||
.db_upgrade = false,
|
.db_upgrade = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void handle_long_options(const char *prog_name, const int long_option)
|
|
||||||
{
|
|
||||||
static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
|
|
||||||
|
|
||||||
switch (long_option) {
|
|
||||||
case 1:
|
|
||||||
vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
|
|
||||||
if (vty_ref_mode < 0) {
|
|
||||||
fprintf(stderr, "%s: Unknown VTY reference generation "
|
|
||||||
"mode '%s'\n", prog_name, optarg);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n",
|
|
||||||
get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
|
|
||||||
get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
|
|
||||||
vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode);
|
|
||||||
exit(0);
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "%s: error parsing cmdline options\n", prog_name);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_options(int argc, char **argv)
|
static void handle_options(int argc, char **argv)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
int option_index = 0, c;
|
int option_index = 0, c;
|
||||||
static int long_option = 0;
|
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"help", 0, 0, 'h'},
|
{"help", 0, 0, 'h'},
|
||||||
{"config-file", 1, 0, 'c'},
|
{"config-file", 1, 0, 'c'},
|
||||||
@@ -645,8 +608,6 @@ static void handle_options(int argc, char **argv)
|
|||||||
{"db-upgrade", 0, 0, 'U' },
|
{"db-upgrade", 0, 0, 'U' },
|
||||||
{"db-check", 0, 0, 'C' },
|
{"db-check", 0, 0, 'C' },
|
||||||
{"version", 0, 0, 'V' },
|
{"version", 0, 0, 'V' },
|
||||||
{"vty-ref-mode", 1, &long_option, 1},
|
|
||||||
{"vty-ref-xml", 0, &long_option, 2},
|
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -656,9 +617,6 @@ static void handle_options(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
|
||||||
handle_long_options(argv[0], long_option);
|
|
||||||
break;
|
|
||||||
case 'h':
|
case 'h':
|
||||||
print_usage();
|
print_usage();
|
||||||
print_help();
|
print_help();
|
||||||
@@ -724,7 +682,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";
|
||||||
@@ -756,8 +714,6 @@ int main(int argc, char **argv)
|
|||||||
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 = GMM_CAUSE_IMSI_UNKNOWN;
|
|
||||||
g_hlr->no_proxy_reject_cause = GMM_CAUSE_IMSI_UNKNOWN;
|
|
||||||
|
|
||||||
/* 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;
|
||||||
@@ -774,10 +730,10 @@ int main(int argc, char **argv)
|
|||||||
osmo_stats_init(hlr_ctx);
|
osmo_stats_init(hlr_ctx);
|
||||||
vty_init(&vty_info);
|
vty_init(&vty_info);
|
||||||
ctrl_vty_init(hlr_ctx);
|
ctrl_vty_init(hlr_ctx);
|
||||||
hlr_vty_init(hlr_ctx);
|
handle_options(argc, argv);
|
||||||
|
hlr_vty_init();
|
||||||
dgsm_vty_init();
|
dgsm_vty_init();
|
||||||
osmo_cpu_sched_vty_init(hlr_ctx);
|
osmo_cpu_sched_vty_init(hlr_ctx);
|
||||||
handle_options(argc, argv);
|
|
||||||
|
|
||||||
rc = vty_read_config_file(cmdline_opts.config_file, NULL);
|
rc = vty_read_config_file(cmdline_opts.config_file, NULL);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
@@ -815,7 +771,8 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* start telnet after reading config for vty_get_bind_addr() */
|
/* start telnet after reading config for vty_get_bind_addr() */
|
||||||
rc = telnet_init_default(hlr_ctx, NULL, OSMO_VTY_PORT_HLR);
|
rc = telnet_init_dynif(hlr_ctx, NULL, vty_get_bind_addr(),
|
||||||
|
OSMO_VTY_PORT_HLR);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@@ -828,6 +785,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
proxy_init(g_hlr->gs);
|
proxy_init(g_hlr->gs);
|
||||||
|
|
||||||
|
g_hlr->ctrl_bind_addr = ctrl_vty_get_bind_addr();
|
||||||
g_hlr->ctrl = hlr_controlif_setup(g_hlr);
|
g_hlr->ctrl = hlr_controlif_setup(g_hlr);
|
||||||
|
|
||||||
dgsm_start(hlr_ctx);
|
dgsm_start(hlr_ctx);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ static struct {
|
|||||||
.db_upgrade = false,
|
.db_upgrade = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void print_help(void)
|
static void print_help()
|
||||||
{
|
{
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Usage: osmo-hlr-db-tool [-l <hlr.db>] [create|import-nitb-db <nitb.db>]\n");
|
printf("Usage: osmo-hlr-db-tool [-l <hlr.db>] [create|import-nitb-db <nitb.db>]\n");
|
||||||
@@ -216,7 +216,7 @@ static const char *nitb_stmt_sql[] = {
|
|||||||
[NITB_SELECT_SUBSCR] =
|
[NITB_SELECT_SUBSCR] =
|
||||||
"SELECT s.imsi, s.id, s.extension, s.authorized,"
|
"SELECT s.imsi, s.id, s.extension, s.authorized,"
|
||||||
" SUBSTR(e.imei,0,15), STRFTIME('%s', s.expire_lu)"
|
" SUBSTR(e.imei,0,15), STRFTIME('%s', s.expire_lu)"
|
||||||
" FROM Subscriber s LEFT JOIN"
|
" FROM Subscriber s INNER JOIN"
|
||||||
" (SELECT imei, subscriber_id, MAX(Equipment.updated) AS updated"
|
" (SELECT imei, subscriber_id, MAX(Equipment.updated) AS updated"
|
||||||
" FROM Equipment,EquipmentWatch"
|
" FROM Equipment,EquipmentWatch"
|
||||||
" WHERE Equipment.id = EquipmentWatch.equipment_id"
|
" WHERE Equipment.id = EquipmentWatch.equipment_id"
|
||||||
@@ -388,9 +388,7 @@ void import_nitb_subscr(sqlite3 *nitb_db, sqlite3_stmt *stmt)
|
|||||||
last_lu_int = sqlite3_column_int(stmt, 5) - 3660;
|
last_lu_int = sqlite3_column_int(stmt, 5) - 3660;
|
||||||
|
|
||||||
db_subscr_update_msisdn_by_imsi(dbc, imsi_str, subscr.msisdn);
|
db_subscr_update_msisdn_by_imsi(dbc, imsi_str, subscr.msisdn);
|
||||||
/* In case the subscriber was somehow never seen, invent an IMEI */
|
db_subscr_update_imei_by_imsi(dbc, imsi_str, subscr.imei);
|
||||||
if (strlen(subscr.imei) == 14)
|
|
||||||
db_subscr_update_imei_by_imsi(dbc, imsi_str, subscr.imei);
|
|
||||||
db_subscr_update_lu_by_imsi(dbc, imsi_str, last_lu_int);
|
db_subscr_update_lu_by_imsi(dbc, imsi_str, last_lu_int);
|
||||||
|
|
||||||
db_subscr_nam(dbc, imsi_str, authorized, true);
|
db_subscr_nam(dbc, imsi_str, authorized, true);
|
||||||
@@ -474,7 +472,6 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int (*main_action)(void);
|
int (*main_action)(void);
|
||||||
int i;
|
|
||||||
main_action = NULL;
|
main_action = NULL;
|
||||||
|
|
||||||
g_hlr_db_tool_ctx = talloc_zero(NULL, struct hlr_db_tool_ctx);
|
g_hlr_db_tool_ctx = talloc_zero(NULL, struct hlr_db_tool_ctx);
|
||||||
@@ -518,11 +515,6 @@ int main(int argc, char **argv)
|
|||||||
if (main_action)
|
if (main_action)
|
||||||
rc = (*main_action)();
|
rc = (*main_action)();
|
||||||
|
|
||||||
/* db_close will only finalize statments in g_hlr_db_tool_ctx->dbc->stmt
|
|
||||||
* it is ok to call finalize on NULL */
|
|
||||||
for (i = 0; i < ARRAY_SIZE(hlr_db_stmt); i++) {
|
|
||||||
sqlite3_finalize(hlr_db_stmt[i]);
|
|
||||||
}
|
|
||||||
db_close(g_hlr_db_tool_ctx->dbc);
|
db_close(g_hlr_db_tool_ctx->dbc);
|
||||||
log_fini();
|
log_fini();
|
||||||
exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
|
exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
|
|||||||
@@ -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 "
|
||||||
@@ -310,20 +279,19 @@ static int ss_gsup_send_to_ms(struct ss_session *ss, struct osmo_gsup_server *gs
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ss_tx_to_ms(struct ss_session *ss, enum osmo_gsup_message_type gsup_msg_type,
|
static int ss_tx_to_ms(struct ss_session *ss, enum osmo_gsup_message_type gsup_msg_type,
|
||||||
struct msgb *ss_msg)
|
bool final, struct msgb *ss_msg)
|
||||||
|
|
||||||
{
|
{
|
||||||
struct osmo_gsup_message resp;
|
struct osmo_gsup_message resp = {0};
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
resp = (struct osmo_gsup_message) {
|
resp.message_type = gsup_msg_type;
|
||||||
.message_type = gsup_msg_type,
|
|
||||||
.session_id = ss->session_id,
|
|
||||||
.session_state = ss->state,
|
|
||||||
};
|
|
||||||
|
|
||||||
OSMO_STRLCPY_ARRAY(resp.imsi, ss->imsi);
|
OSMO_STRLCPY_ARRAY(resp.imsi, ss->imsi);
|
||||||
|
if (final)
|
||||||
|
resp.session_state = OSMO_GSUP_SESSION_STATE_END;
|
||||||
|
else
|
||||||
|
resp.session_state = OSMO_GSUP_SESSION_STATE_CONTINUE;
|
||||||
|
resp.session_id = ss->session_id;
|
||||||
if (ss_msg) {
|
if (ss_msg) {
|
||||||
resp.ss_info = msgb_data(ss_msg);
|
resp.ss_info = msgb_data(ss_msg);
|
||||||
resp.ss_info_len = msgb_length(ss_msg);
|
resp.ss_info_len = msgb_length(ss_msg);
|
||||||
@@ -343,8 +311,7 @@ static int ss_tx_reject(struct ss_session *ss, int invoke_id, uint8_t problem_ta
|
|||||||
LOGPSS(ss, LOGL_NOTICE, "Tx Reject(%u, 0x%02x, 0x%02x)\n", invoke_id,
|
LOGPSS(ss, LOGL_NOTICE, "Tx Reject(%u, 0x%02x, 0x%02x)\n", invoke_id,
|
||||||
problem_tag, problem_code);
|
problem_tag, problem_code);
|
||||||
OSMO_ASSERT(msg);
|
OSMO_ASSERT(msg);
|
||||||
ss->state = OSMO_GSUP_SESSION_STATE_END;
|
return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, true, msg);
|
||||||
return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, msg);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -353,16 +320,15 @@ static int ss_tx_to_ms_error(struct ss_session *ss, uint8_t invoke_id, uint8_t e
|
|||||||
struct msgb *msg = gsm0480_gen_return_error(invoke_id, error_code);
|
struct msgb *msg = gsm0480_gen_return_error(invoke_id, error_code);
|
||||||
LOGPSS(ss, LOGL_NOTICE, "Tx ReturnError(%u, 0x%02x)\n", invoke_id, error_code);
|
LOGPSS(ss, LOGL_NOTICE, "Tx ReturnError(%u, 0x%02x)\n", invoke_id, error_code);
|
||||||
OSMO_ASSERT(msg);
|
OSMO_ASSERT(msg);
|
||||||
ss->state = OSMO_GSUP_SESSION_STATE_END;
|
return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, true, msg);
|
||||||
return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ss_tx_to_ms_ussd_7bit(struct ss_session *ss, uint8_t invoke_id, const char *text)
|
static int ss_tx_to_ms_ussd_7bit(struct ss_session *ss, bool final, uint8_t invoke_id, const char *text)
|
||||||
{
|
{
|
||||||
struct msgb *msg = gsm0480_gen_ussd_resp_7bit(invoke_id, text);
|
struct msgb *msg = gsm0480_gen_ussd_resp_7bit(invoke_id, text);
|
||||||
LOGPSS(ss, LOGL_INFO, "Tx USSD '%s'\n", text);
|
LOGPSS(ss, LOGL_INFO, "Tx USSD '%s'\n", text);
|
||||||
OSMO_ASSERT(msg);
|
OSMO_ASSERT(msg);
|
||||||
return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, msg);
|
return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, final, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@@ -378,8 +344,6 @@ static int handle_ussd_own_msisdn(struct ss_session *ss,
|
|||||||
char buf[GSM0480_USSD_7BIT_STRING_LEN+1];
|
char buf[GSM0480_USSD_7BIT_STRING_LEN+1];
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ss->state = OSMO_GSUP_SESSION_STATE_END;
|
|
||||||
|
|
||||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
rc = db_subscr_get_by_imsi(g_hlr->dbc, ss->imsi, &subscr);
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -387,7 +351,7 @@ static int handle_ussd_own_msisdn(struct ss_session *ss,
|
|||||||
snprintf(buf, sizeof(buf), "You have no MSISDN!");
|
snprintf(buf, sizeof(buf), "You have no MSISDN!");
|
||||||
else
|
else
|
||||||
snprintf(buf, sizeof(buf), "Your extension is %s", subscr.msisdn);
|
snprintf(buf, sizeof(buf), "Your extension is %s", subscr.msisdn);
|
||||||
ss_tx_to_ms_ussd_7bit(ss, req->invoke_id, buf);
|
ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id, buf);
|
||||||
break;
|
break;
|
||||||
case -ENOENT:
|
case -ENOENT:
|
||||||
ss_tx_to_ms_error(ss, req->invoke_id, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
ss_tx_to_ms_error(ss, req->invoke_id, GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER);
|
||||||
@@ -405,21 +369,7 @@ static int handle_ussd_own_imsi(struct ss_session *ss,
|
|||||||
{
|
{
|
||||||
char buf[GSM0480_USSD_7BIT_STRING_LEN+1];
|
char buf[GSM0480_USSD_7BIT_STRING_LEN+1];
|
||||||
snprintf(buf, sizeof(buf), "Your IMSI is %s", ss->imsi);
|
snprintf(buf, sizeof(buf), "Your IMSI is %s", ss->imsi);
|
||||||
ss->state = OSMO_GSUP_SESSION_STATE_END;
|
ss_tx_to_ms_ussd_7bit(ss, true, req->invoke_id, buf);
|
||||||
ss_tx_to_ms_ussd_7bit(ss, req->invoke_id, buf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This handler just keeps the session idle unless the guard timer expires. */
|
|
||||||
static int handle_ussd_test_idle(struct ss_session *ss,
|
|
||||||
const struct osmo_gsup_message *gsup,
|
|
||||||
const struct ss_request *req)
|
|
||||||
{
|
|
||||||
char buf[GSM0480_USSD_7BIT_STRING_LEN + 1];
|
|
||||||
snprintf(buf, sizeof(buf), "Keeping your session idle, it will expire "
|
|
||||||
"at most in %u seconds.", g_hlr->ncss_guard_timeout);
|
|
||||||
ss->state = OSMO_GSUP_SESSION_STATE_CONTINUE;
|
|
||||||
ss_tx_to_ms_ussd_7bit(ss, req->invoke_id, buf);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,10 +383,6 @@ static const struct hlr_iuse hlr_iuses[] = {
|
|||||||
.name = "own-imsi",
|
.name = "own-imsi",
|
||||||
.handle_ussd = handle_ussd_own_imsi,
|
.handle_ussd = handle_ussd_own_imsi,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.name = "test-idle",
|
|
||||||
.handle_ussd = handle_ussd_test_idle,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct hlr_iuse *iuse_find(const char *name)
|
const struct hlr_iuse *iuse_find(const char *name)
|
||||||
@@ -550,9 +496,8 @@ static int handle_ussd(struct ss_session *ss, bool is_euse_originated, const str
|
|||||||
} else {
|
} else {
|
||||||
/* Handle internally */
|
/* Handle internally */
|
||||||
ss->u.iuse->handle_ussd(ss, gsup, req);
|
ss->u.iuse->handle_ussd(ss, gsup, req);
|
||||||
/* Release session if the handler has changed its state to END */
|
/* Release session immediately */
|
||||||
if (ss->state == OSMO_GSUP_SESSION_STATE_END)
|
ss_session_free(ss);
|
||||||
ss_session_free(ss);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,7 +579,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 +607,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 +628,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 +658,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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
313
src/hlr_vty.c
313
src/hlr_vty.c
@@ -25,13 +25,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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/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>
|
||||||
@@ -46,36 +40,6 @@
|
|||||||
#include <osmocom/hlr/hlr_ussd.h>
|
#include <osmocom/hlr/hlr_ussd.h>
|
||||||
#include <osmocom/hlr/gsup_server.h>
|
#include <osmocom/hlr/gsup_server.h>
|
||||||
|
|
||||||
static const struct value_string gsm48_gmm_cause_vty_names[] = {
|
|
||||||
{ GMM_CAUSE_IMSI_UNKNOWN, "imsi-unknown" },
|
|
||||||
{ GMM_CAUSE_ILLEGAL_MS, "illegal-ms" },
|
|
||||||
{ GMM_CAUSE_PLMN_NOTALLOWED, "plmn-not-allowed" },
|
|
||||||
{ GMM_CAUSE_LA_NOTALLOWED, "la-not-allowed" },
|
|
||||||
{ GMM_CAUSE_ROAMING_NOTALLOWED, "roaming-not-allowed" },
|
|
||||||
{ GMM_CAUSE_NO_SUIT_CELL_IN_LA, "no-suitable-cell-in-la" },
|
|
||||||
{ GMM_CAUSE_NET_FAIL, "net-fail" },
|
|
||||||
{ GMM_CAUSE_CONGESTION, "congestion" },
|
|
||||||
{ GMM_CAUSE_GSM_AUTH_UNACCEPT, "auth-unacceptable" },
|
|
||||||
{ GMM_CAUSE_PROTO_ERR_UNSPEC, "proto-error-unspec" },
|
|
||||||
{ 0, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
/* TS 24.008 4.4.4.7 */
|
|
||||||
static const struct value_string gsm48_gmm_cause_vty_descs[] = {
|
|
||||||
{ GMM_CAUSE_IMSI_UNKNOWN, " #02: (IMSI unknown in HLR)" },
|
|
||||||
{ GMM_CAUSE_ILLEGAL_MS, " #03 (Illegal MS)" },
|
|
||||||
{ GMM_CAUSE_PLMN_NOTALLOWED, " #11: (PLMN not allowed)" },
|
|
||||||
{ GMM_CAUSE_LA_NOTALLOWED, " #12: (Location Area not allowed)" },
|
|
||||||
{ GMM_CAUSE_ROAMING_NOTALLOWED, " #13: (Roaming not allowed in this location area)" },
|
|
||||||
{ GMM_CAUSE_NO_SUIT_CELL_IN_LA, " #15: (No Suitable Cells In Location Area [continue search in PLMN])." },
|
|
||||||
{ GMM_CAUSE_NET_FAIL, " #17: (Network Failure)" },
|
|
||||||
{ GMM_CAUSE_CONGESTION, " #22: (Congestion)" },
|
|
||||||
{ GMM_CAUSE_GSM_AUTH_UNACCEPT, " #23: (GSM authentication unacceptable [UMTS])" },
|
|
||||||
{ GMM_CAUSE_PROTO_ERR_UNSPEC, "#111: (Protocol error, unspecified)" },
|
|
||||||
{ 0, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct cmd_node hlr_node = {
|
struct cmd_node hlr_node = {
|
||||||
HLR_NODE,
|
HLR_NODE,
|
||||||
"%s(config-hlr)# ",
|
"%s(config-hlr)# ",
|
||||||
@@ -106,194 +70,9 @@ DEFUN(cfg_gsup,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd_node ps_node = {
|
|
||||||
PS_NODE,
|
|
||||||
"%s(config-hlr-ps)# ",
|
|
||||||
1,
|
|
||||||
};
|
|
||||||
|
|
||||||
DEFUN(cfg_ps,
|
|
||||||
cfg_ps_cmd,
|
|
||||||
"ps",
|
|
||||||
"Configure the PS options")
|
|
||||||
{
|
|
||||||
vty->node = PS_NODE;
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct cmd_node ps_pdp_profiles_node = {
|
|
||||||
PS_PDP_PROFILES_NODE,
|
|
||||||
"%s(config-hlr-ps-pdp-profiles)# ",
|
|
||||||
1,
|
|
||||||
};
|
|
||||||
|
|
||||||
DEFUN(cfg_ps_pdp_profiles,
|
|
||||||
cfg_ps_pdp_profiles_cmd,
|
|
||||||
"pdp-profiles default",
|
|
||||||
"Define a PDP profile set.\n"
|
|
||||||
"Define the global default profile.\n")
|
|
||||||
{
|
|
||||||
g_hlr->ps.pdp_profile.enabled = true;
|
|
||||||
|
|
||||||
vty->node = PS_PDP_PROFILES_NODE;
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 int config_write_hlr(struct vty *vty)
|
static int config_write_hlr(struct vty *vty)
|
||||||
{
|
{
|
||||||
vty_out(vty, "hlr%s", VTY_NEWLINE);
|
vty_out(vty, "hlr%s", VTY_NEWLINE);
|
||||||
|
|
||||||
if (g_hlr->reject_cause != GMM_CAUSE_IMSI_UNKNOWN)
|
|
||||||
vty_out(vty, " reject-cause not-found %s%s",
|
|
||||||
get_value_string_or_null(gsm48_gmm_cause_vty_names,
|
|
||||||
(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",
|
|
||||||
get_value_string_or_null(gsm48_gmm_cause_vty_names,
|
|
||||||
(uint32_t) g_hlr->no_proxy_reject_cause), VTY_NEWLINE);
|
|
||||||
if (g_hlr->store_imei)
|
if (g_hlr->store_imei)
|
||||||
vty_out(vty, " store-imei%s", VTY_NEWLINE);
|
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))
|
if (g_hlr->db_file_path && strcmp(g_hlr->db_file_path, HLR_DEFAULT_DB_FILE_PATH))
|
||||||
@@ -323,39 +102,6 @@ static int config_write_hlr_gsup(struct vty *vty)
|
|||||||
vty_out(vty, " gsup%s", VTY_NEWLINE);
|
vty_out(vty, " gsup%s", VTY_NEWLINE);
|
||||||
if (g_hlr->gsup_bind_addr)
|
if (g_hlr->gsup_bind_addr)
|
||||||
vty_out(vty, " bind ip %s%s", g_hlr->gsup_bind_addr, VTY_NEWLINE);
|
vty_out(vty, " bind ip %s%s", g_hlr->gsup_bind_addr, VTY_NEWLINE);
|
||||||
if (g_hlr->gsup_unit_name.serno)
|
|
||||||
vty_out(vty, " ipa-name %s%s", g_hlr->gsup_unit_name.serno, VTY_NEWLINE);
|
|
||||||
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;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,8 +114,8 @@ static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn)
|
|||||||
rc = osmo_gsup_conn_ccm_get(conn, (uint8_t **) &name, IPAC_IDTAG_SERNR);
|
rc = osmo_gsup_conn_ccm_get(conn, (uint8_t **) &name, IPAC_IDTAG_SERNR);
|
||||||
OSMO_ASSERT(rc);
|
OSMO_ASSERT(rc);
|
||||||
|
|
||||||
vty_out(vty, " '%s' from %s:%5u, CS=%u, PS=%u%s",
|
vty_out(vty, " '%s' from %s:%5u, CS=%u, PS=%u, 3G_IND=%u%s",
|
||||||
name, isc->addr, isc->port, conn->supports_cs, conn->supports_ps,
|
name, isc->addr, isc->port, conn->supports_cs, conn->supports_ps, conn->auc_3g_ind,
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +156,7 @@ DEFUN(cfg_hlr_gsup_ipa_name,
|
|||||||
{
|
{
|
||||||
if (vty->type != VTY_FILE) {
|
if (vty->type != VTY_FILE) {
|
||||||
vty_out(vty, "gsup/ipa-name: The GSUP IPA name cannot be changed at run-time; "
|
vty_out(vty, "gsup/ipa-name: The GSUP IPA name cannot be changed at run-time; "
|
||||||
"It can only be set in the configuration file.%s", VTY_NEWLINE);
|
"It can only be set in the configuraton file.%s", VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,11 +174,10 @@ DEFUN(cfg_hlr_gsup_ipa_name,
|
|||||||
#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"
|
||||||
|
|
||||||
#define INT_CHOICE "(own-msisdn|own-imsi|test-idle)"
|
#define INT_CHOICE "(own-msisdn|own-imsi)"
|
||||||
#define INT_STR "Internal USSD Handler\n" \
|
#define INT_STR "Internal USSD Handler\n" \
|
||||||
"Respond with subscribers' own MSISDN\n" \
|
"Respond with subscribers' own MSISDN\n" \
|
||||||
"Respond with subscribers' own IMSI\n" \
|
"Respond with subscribers' own IMSI\n"
|
||||||
"Keep the session idle (useful for testing)\n"
|
|
||||||
|
|
||||||
#define EXT_STR "External USSD Handler\n" \
|
#define EXT_STR "External USSD Handler\n" \
|
||||||
"Name of External USSD Handler (IPA CCM ID)\n"
|
"Name of External USSD Handler (IPA CCM ID)\n"
|
||||||
@@ -560,7 +305,7 @@ DEFUN(cfg_no_euse, cfg_no_euse_cmd,
|
|||||||
{
|
{
|
||||||
struct hlr_euse *euse = euse_find(g_hlr, argv[0]);
|
struct hlr_euse *euse = euse_find(g_hlr, argv[0]);
|
||||||
if (!euse) {
|
if (!euse) {
|
||||||
vty_out(vty, "%% Cannot remove non-existent EUSE %s%s", argv[0], VTY_NEWLINE);
|
vty_out(vty, "%% Cannot remove non-existant EUSE %s%s", argv[0], VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
if (g_hlr->euse_default == euse) {
|
if (g_hlr->euse_default == euse) {
|
||||||
@@ -610,21 +355,6 @@ DEFUN(cfg_ncss_guard_timeout, cfg_ncss_guard_timeout_cmd,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEFUN(cfg_reject_cause, cfg_reject_cause_cmd,
|
|
||||||
"reject-cause TYPE CAUSE", "") /* Dynamically Generated */
|
|
||||||
{
|
|
||||||
int cause_code = get_string_value(gsm48_gmm_cause_vty_names, argv[1]);
|
|
||||||
OSMO_ASSERT(cause_code >= 0);
|
|
||||||
|
|
||||||
if (strcmp(argv[0], "not-found") == 0)
|
|
||||||
g_hlr->reject_cause = (enum gsm48_gmm_cause) cause_code;
|
|
||||||
if (strcmp(argv[0], "no-proxy") == 0)
|
|
||||||
g_hlr->no_proxy_reject_cause = (enum gsm48_gmm_cause) cause_code;
|
|
||||||
|
|
||||||
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"
|
||||||
@@ -717,22 +447,8 @@ int hlr_vty_is_config_node(struct vty *vty, int node)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hlr_vty_init(void *hlr_ctx)
|
void hlr_vty_init(void)
|
||||||
{
|
{
|
||||||
cfg_reject_cause_cmd.string =
|
|
||||||
vty_cmd_string_from_valstr(hlr_ctx,
|
|
||||||
gsm48_gmm_cause_vty_names,
|
|
||||||
"reject-cause (not-found|no-proxy) (", "|", ")",
|
|
||||||
VTY_DO_LOWER);
|
|
||||||
|
|
||||||
cfg_reject_cause_cmd.doc =
|
|
||||||
vty_cmd_string_from_valstr(hlr_ctx,
|
|
||||||
gsm48_gmm_cause_vty_descs,
|
|
||||||
"GSUP/GMM cause to be sent\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",
|
|
||||||
"\n", "", 0);
|
|
||||||
|
|
||||||
logging_vty_add_cmds();
|
logging_vty_add_cmds();
|
||||||
osmo_talloc_vty_add_cmds();
|
osmo_talloc_vty_add_cmds();
|
||||||
osmo_stats_vty_add_cmds();
|
osmo_stats_vty_add_cmds();
|
||||||
@@ -748,20 +464,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);
|
||||||
@@ -773,7 +475,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_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);
|
||||||
install_element(HLR_NODE, &cfg_subscr_create_on_demand_cmd);
|
install_element(HLR_NODE, &cfg_subscr_create_on_demand_cmd);
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -31,7 +31,6 @@
|
|||||||
#include <osmocom/hlr/hlr.h>
|
#include <osmocom/hlr/hlr.h>
|
||||||
#include <osmocom/hlr/db.h>
|
#include <osmocom/hlr/db.h>
|
||||||
#include <osmocom/hlr/timestamp.h>
|
#include <osmocom/hlr/timestamp.h>
|
||||||
#include <osmocom/hlr/hlr_vty.h>
|
|
||||||
|
|
||||||
struct vty;
|
struct vty;
|
||||||
|
|
||||||
@@ -45,14 +44,13 @@ static char *get_datestr(const time_t *t, char *buf, size_t bufsize)
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen, bool only_age)
|
static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen)
|
||||||
{
|
{
|
||||||
uint32_t age;
|
uint32_t age;
|
||||||
char datebuf[32];
|
char datebuf[32];
|
||||||
if (!last_lu_seen)
|
if (!last_lu_seen)
|
||||||
return;
|
return;
|
||||||
if (!only_age)
|
vty_out(vty, " last LU seen on %s: %s", domain_label, get_datestr(&last_lu_seen, datebuf, sizeof(datebuf)));
|
||||||
vty_out(vty, " last LU seen on %s: %s", domain_label, get_datestr(&last_lu_seen, datebuf, sizeof(datebuf)));
|
|
||||||
if (!timestamp_age(&last_lu_seen, &age))
|
if (!timestamp_age(&last_lu_seen, &age))
|
||||||
vty_out(vty, " (invalid timestamp)%s", VTY_NEWLINE);
|
vty_out(vty, " (invalid timestamp)%s", VTY_NEWLINE);
|
||||||
else {
|
else {
|
||||||
@@ -66,10 +64,7 @@ static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t
|
|||||||
UNIT_AGO("h", 60*60);
|
UNIT_AGO("h", 60*60);
|
||||||
UNIT_AGO("m", 60);
|
UNIT_AGO("m", 60);
|
||||||
UNIT_AGO("s", 1);
|
UNIT_AGO("s", 1);
|
||||||
if (!only_age)
|
vty_out(vty, " ago)%s", VTY_NEWLINE);
|
||||||
vty_out(vty, " ago)%s", VTY_NEWLINE);
|
|
||||||
else
|
|
||||||
vty_out(vty, " ago)");
|
|
||||||
#undef UNIT_AGO
|
#undef UNIT_AGO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,8 +72,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);
|
||||||
|
|
||||||
@@ -113,8 +108,8 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
|||||||
vty_out(vty, " PS disabled%s", VTY_NEWLINE);
|
vty_out(vty, " PS disabled%s", VTY_NEWLINE);
|
||||||
if (subscr->ms_purged_ps)
|
if (subscr->ms_purged_ps)
|
||||||
vty_out(vty, " PS purged%s", VTY_NEWLINE);
|
vty_out(vty, " PS purged%s", VTY_NEWLINE);
|
||||||
dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, false);
|
dump_last_lu_seen(vty, "CS", subscr->last_lu_seen);
|
||||||
dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps, false);
|
dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps);
|
||||||
|
|
||||||
if (!*subscr->imsi)
|
if (!*subscr->imsi)
|
||||||
return;
|
return;
|
||||||
@@ -137,12 +132,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 +149,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);
|
||||||
@@ -165,28 +159,6 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subscr_dump_summary_vty(struct hlr_subscriber *subscr, void *data)
|
|
||||||
{
|
|
||||||
struct vty *vty = data;
|
|
||||||
vty_out(vty, "%-5"PRIu64" %-12s %-16s", subscr->id,
|
|
||||||
*subscr->msisdn ? subscr->msisdn : "none",
|
|
||||||
*subscr->imsi ? subscr->imsi : "none");
|
|
||||||
|
|
||||||
if (*subscr->imei) {
|
|
||||||
char checksum = osmo_luhn(subscr->imei, 14);
|
|
||||||
if (checksum == -EINVAL)
|
|
||||||
vty_out(vty, " %-14s (INVALID LENGTH!)", subscr->imei);
|
|
||||||
else
|
|
||||||
vty_out(vty, " %-14s%c", subscr->imei, checksum);
|
|
||||||
} else {
|
|
||||||
vty_out(vty," ------------- ");
|
|
||||||
}
|
|
||||||
vty_out(vty, " %-2s%-2s ", subscr->nam_cs ? "CS" : "", subscr->nam_ps ? "PS" : "");
|
|
||||||
if (subscr->last_lu_seen)
|
|
||||||
dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, true);
|
|
||||||
vty_out_newline(vty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_subscr_by_argv(struct vty *vty, const char *type, const char *id, struct hlr_subscriber *subscr)
|
static int get_subscr_by_argv(struct vty *vty, const char *type, const char *id, struct hlr_subscriber *subscr)
|
||||||
{
|
{
|
||||||
char imei_buf[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1];
|
char imei_buf[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1];
|
||||||
@@ -214,52 +186,10 @@ static int get_subscr_by_argv(struct vty *vty, const char *type, const char *id,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_summary_table_vty(struct vty *vty, bool header, bool show_ls)
|
|
||||||
{
|
|
||||||
const char *texts = "ID MSISDN IMSI IMEI NAM";
|
|
||||||
const char *lines = "----- ------------ ---------------- ---------------- -----";
|
|
||||||
const char *ls_text = " LAST SEEN";
|
|
||||||
const char *ls_line = " ------------";
|
|
||||||
if (header) {
|
|
||||||
if (!show_ls)
|
|
||||||
vty_out(vty, "%s%s%s%s", texts, VTY_NEWLINE, lines, VTY_NEWLINE);
|
|
||||||
else
|
|
||||||
vty_out(vty, "%s%s%s%s%s%s", texts, ls_text, VTY_NEWLINE, lines, ls_line, VTY_NEWLINE);
|
|
||||||
} else {
|
|
||||||
if (!show_ls)
|
|
||||||
vty_out(vty, "%s%s%s%s", lines, VTY_NEWLINE, texts, VTY_NEWLINE);
|
|
||||||
else
|
|
||||||
vty_out(vty, "%s%s%s%s%s%s", lines, ls_line, VTY_NEWLINE, texts, ls_text, VTY_NEWLINE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_subscrs(struct vty *vty, const char *filter_type, const char *filter)
|
|
||||||
{
|
|
||||||
int rc = -1;
|
|
||||||
int count = 0;
|
|
||||||
const char *err;
|
|
||||||
bool show_ls = (filter_type && strcmp(filter_type, "last_lu_seen") == 0);
|
|
||||||
dump_summary_table_vty(vty, true, show_ls);
|
|
||||||
rc = db_subscrs_get(g_hlr->dbc, filter_type, filter, subscr_dump_summary_vty, vty, &count, &err);
|
|
||||||
if (count > 40) {
|
|
||||||
dump_summary_table_vty(vty, false, show_ls);
|
|
||||||
}
|
|
||||||
if (count > 0)
|
|
||||||
vty_out(vty, " Subscribers Shown: %d%s", count, VTY_NEWLINE);
|
|
||||||
if (rc)
|
|
||||||
vty_out(vty, "%% %s%s", err, VTY_NEWLINE);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define SUBSCR_CMD "subscriber "
|
#define SUBSCR_CMD "subscriber "
|
||||||
#define SUBSCR_CMD_HELP "Subscriber management commands\n"
|
#define SUBSCR_CMD_HELP "Subscriber management commands\n"
|
||||||
#define SUBSCR_SHOW_HELP "Show subscriber information\n"
|
|
||||||
#define SUBSCRS_SHOW_HELP "Show all subscribers (with filter possibility)\n"
|
|
||||||
|
|
||||||
#define SUBSCR_ID "(imsi|msisdn|id|imei) IDENT"
|
#define SUBSCR_ID "(imsi|msisdn|id|imei) IDENT"
|
||||||
#define SUBSCR_FILTER "(imei|imsi|msisdn) FILTER"
|
|
||||||
|
|
||||||
#define SUBSCR_ID_HELP \
|
#define SUBSCR_ID_HELP \
|
||||||
"Identify subscriber by IMSI\n" \
|
"Identify subscriber by IMSI\n" \
|
||||||
"Identify subscriber by MSISDN (phone number)\n" \
|
"Identify subscriber by MSISDN (phone number)\n" \
|
||||||
@@ -277,7 +207,7 @@ static int get_subscrs(struct vty *vty, const char *filter_type, const char *fil
|
|||||||
DEFUN(subscriber_show,
|
DEFUN(subscriber_show,
|
||||||
subscriber_show_cmd,
|
subscriber_show_cmd,
|
||||||
SUBSCR "show",
|
SUBSCR "show",
|
||||||
SUBSCR_HELP SUBSCR_SHOW_HELP)
|
SUBSCR_HELP "Show subscriber information\n")
|
||||||
{
|
{
|
||||||
struct hlr_subscriber subscr;
|
struct hlr_subscriber subscr;
|
||||||
const char *id_type = argv[0];
|
const char *id_type = argv[0];
|
||||||
@@ -292,50 +222,7 @@ DEFUN(subscriber_show,
|
|||||||
|
|
||||||
ALIAS(subscriber_show, show_subscriber_cmd,
|
ALIAS(subscriber_show, show_subscriber_cmd,
|
||||||
"show " SUBSCR_CMD SUBSCR_ID,
|
"show " SUBSCR_CMD SUBSCR_ID,
|
||||||
SHOW_STR SUBSCR_SHOW_HELP SUBSCR_ID_HELP);
|
SHOW_STR SUBSCR_CMD_HELP SUBSCR_ID_HELP);
|
||||||
|
|
||||||
DEFUN(show_subscriber_all,
|
|
||||||
show_subscriber_all_cmd,
|
|
||||||
"show subscribers all",
|
|
||||||
SHOW_STR SUBSCRS_SHOW_HELP "Show summary of all subscribers\n")
|
|
||||||
{
|
|
||||||
if (get_subscrs(vty, NULL, NULL))
|
|
||||||
return CMD_WARNING;
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFUN(show_subscriber_filtered,
|
|
||||||
show_subscriber_filtered_cmd,
|
|
||||||
"show subscribers " SUBSCR_FILTER,
|
|
||||||
SHOW_STR SUBSCRS_SHOW_HELP
|
|
||||||
"Filter Subscribers by IMEI\n" "Filter Subscribers by IMSI\n" "Filter Subscribers by MSISDN\n"
|
|
||||||
"String to match in imei, imsi or msisdn\n")
|
|
||||||
{
|
|
||||||
const char *filter_type = argv[0];
|
|
||||||
const char *filter = argv[1];
|
|
||||||
|
|
||||||
if (get_subscrs(vty, filter_type, filter))
|
|
||||||
return CMD_WARNING;
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALIAS(show_subscriber_filtered, show_subscriber_filtered_cmd2,
|
|
||||||
"show subscribers (cs|ps) (on|off)",
|
|
||||||
SHOW_STR SUBSCR_SHOW_HELP
|
|
||||||
"Filter Subscribers by CS Network Access Mode\n" "Filter Subscribers by PS Network Access Mode\n"
|
|
||||||
"Authorised\n" "Not Authorised\n");
|
|
||||||
|
|
||||||
DEFUN(show_subscriber_order_last_seen, show_subscriber_order_last_seen_cmd,
|
|
||||||
"show subscribers last-seen",
|
|
||||||
SHOW_STR SUBSCR_SHOW_HELP "Show Subscribers Ordered by Last Seen Time\n")
|
|
||||||
{
|
|
||||||
if (get_subscrs(vty, "last_lu_seen", NULL))
|
|
||||||
return CMD_WARNING;
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFUN(subscriber_create,
|
DEFUN(subscriber_create,
|
||||||
subscriber_create_cmd,
|
subscriber_create_cmd,
|
||||||
@@ -348,7 +235,7 @@ DEFUN(subscriber_create,
|
|||||||
int rc;
|
int rc;
|
||||||
struct hlr_subscriber subscr;
|
struct hlr_subscriber subscr;
|
||||||
const char *imsi = argv[0];
|
const char *imsi = argv[0];
|
||||||
|
|
||||||
if (!osmo_imsi_str_valid(imsi)) {
|
if (!osmo_imsi_str_valid(imsi)) {
|
||||||
vty_out(vty, "%% Not a valid IMSI: %s%s", imsi, VTY_NEWLINE);
|
vty_out(vty, "%% Not a valid IMSI: %s%s", imsi, VTY_NEWLINE);
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
@@ -461,27 +348,26 @@ 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,
|
#define A38_XOR_MIN_KEY_LEN 12
|
||||||
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc)
|
#define A38_XOR_MAX_KEY_LEN 16
|
||||||
|
#define A38_COMP128_KEY_LEN 16
|
||||||
|
|
||||||
|
#define MILENAGE_KEY_LEN 16
|
||||||
|
|
||||||
|
static bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
|
||||||
|
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;
|
||||||
@@ -494,28 +380,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;
|
||||||
@@ -571,7 +442,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;
|
||||||
}
|
}
|
||||||
@@ -630,21 +501,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 = {
|
||||||
@@ -654,8 +525,8 @@ DEFUN(subscriber_aud3g,
|
|||||||
.ind_bitlen = ind_bitlen,
|
.ind_bitlen = ind_bitlen,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@@ -663,56 +534,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,
|
||||||
return CMD_WARNING;
|
MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
|
||||||
|
|
||||||
if (get_subscr_by_argv(vty, id_type, id, &subscr))
|
|
||||||
return CMD_WARNING;
|
|
||||||
|
|
||||||
rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud3g);
|
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
vty_out(vty, "%% Error: cannot set 3G auth data for IMSI='%s'%s",
|
|
||||||
subscr.imsi, VTY_NEWLINE);
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFUN(subscriber_aud3g_xor,
|
|
||||||
subscriber_aud3g_xor_cmd,
|
|
||||||
SUBSCR_UPDATE "aud3g xor-3g k K"
|
|
||||||
" [ind-bitlen] [<0-28>]",
|
|
||||||
SUBSCR_UPDATE_HELP
|
|
||||||
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
|
|
||||||
"Use XOR-3G algorithm\n"
|
|
||||||
"Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
|
|
||||||
"Set IND bit length\n" "IND bit length value (default: 5)\n")
|
|
||||||
{
|
|
||||||
struct hlr_subscriber subscr;
|
|
||||||
int minlen = 0;
|
|
||||||
int maxlen = 0;
|
|
||||||
int rc;
|
|
||||||
const char *id_type = argv[0];
|
|
||||||
const char *id = argv[1];
|
|
||||||
const char *k = argv[2];
|
|
||||||
int ind_bitlen = argc > 4? atoi(argv[4]) : 5;
|
|
||||||
struct sub_auth_data_str aud3g = {
|
|
||||||
.type = OSMO_AUTH_TYPE_UMTS,
|
|
||||||
.u.umts = {
|
|
||||||
.k = k,
|
|
||||||
.opc_is_op = 0,
|
|
||||||
.opc = "00000000000000000000000000000000",
|
|
||||||
.ind_bitlen = ind_bitlen,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen, NULL, NULL)) {
|
|
||||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor-3g", VTY_NEWLINE);
|
|
||||||
return CMD_WARNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
|
|
||||||
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))
|
||||||
@@ -805,10 +628,6 @@ DEFUN(subscriber_nam,
|
|||||||
|
|
||||||
void hlr_vty_subscriber_init(void)
|
void hlr_vty_subscriber_init(void)
|
||||||
{
|
{
|
||||||
install_element_ve(&show_subscriber_all_cmd);
|
|
||||||
install_element_ve(&show_subscriber_filtered_cmd);
|
|
||||||
install_element_ve(&show_subscriber_filtered_cmd2);
|
|
||||||
install_element_ve(&show_subscriber_order_last_seen_cmd);
|
|
||||||
install_element_ve(&subscriber_show_cmd);
|
install_element_ve(&subscriber_show_cmd);
|
||||||
install_element_ve(&show_subscriber_cmd);
|
install_element_ve(&show_subscriber_cmd);
|
||||||
install_element(ENABLE_NODE, &subscriber_create_cmd);
|
install_element(ENABLE_NODE, &subscriber_create_cmd);
|
||||||
@@ -818,7 +637,6 @@ void hlr_vty_subscriber_init(void)
|
|||||||
install_element(ENABLE_NODE, &subscriber_aud2g_cmd);
|
install_element(ENABLE_NODE, &subscriber_aud2g_cmd);
|
||||||
install_element(ENABLE_NODE, &subscriber_no_aud3g_cmd);
|
install_element(ENABLE_NODE, &subscriber_no_aud3g_cmd);
|
||||||
install_element(ENABLE_NODE, &subscriber_aud3g_cmd);
|
install_element(ENABLE_NODE, &subscriber_aud3g_cmd);
|
||||||
install_element(ENABLE_NODE, &subscriber_aud3g_xor_cmd);
|
|
||||||
install_element(ENABLE_NODE, &subscriber_imei_cmd);
|
install_element(ENABLE_NODE, &subscriber_imei_cmd);
|
||||||
install_element(ENABLE_NODE, &subscriber_nam_cmd);
|
install_element(ENABLE_NODE, &subscriber_nam_cmd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,12 +43,6 @@ const struct log_info_cat hlr_log_info_cat[] = {
|
|||||||
.color = "\033[1;35m",
|
.color = "\033[1;35m",
|
||||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||||
},
|
},
|
||||||
[DCTRL] = {
|
|
||||||
.name = "DCTRL",
|
|
||||||
.description = "Osmocom CTRL interface",
|
|
||||||
.color = "\033[1;30m",
|
|
||||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct log_info hlr_log_info = {
|
const struct log_info hlr_log_info = {
|
||||||
|
|||||||
13
src/lu_fsm.c
13
src/lu_fsm.c
@@ -136,7 +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, g_hlr->reject_cause, "Subscriber does not exist");
|
lu_failure(lu, GMM_CAUSE_IMSI_UNKNOWN, "Subscriber does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,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;
|
||||||
}
|
}
|
||||||
@@ -275,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:
|
||||||
@@ -313,7 +314,7 @@ static struct osmo_fsm lu_fsm = {
|
|||||||
.cleanup = lu_fsm_cleanup,
|
.cleanup = lu_fsm_cleanup,
|
||||||
};
|
};
|
||||||
|
|
||||||
static __attribute__((constructor)) void lu_fsm_init(void)
|
static __attribute__((constructor)) void lu_fsm_init()
|
||||||
{
|
{
|
||||||
OSMO_ASSERT(osmo_fsm_register(&lu_fsm) == 0);
|
OSMO_ASSERT(osmo_fsm_register(&lu_fsm) == 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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=0: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)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ int osmo_mdns_msg_request_encode(void *ctx, struct msgb *msg, const struct osmo_
|
|||||||
qst.domain = req->domain;
|
qst.domain = req->domain;
|
||||||
qst.qtype = req->type;
|
qst.qtype = req->type;
|
||||||
qst.qclass = OSMO_MDNS_RFC_CLASS_IN;
|
qst.qclass = OSMO_MDNS_RFC_CLASS_IN;
|
||||||
if (osmo_mdns_rfc_question_encode(msg, &qst) != 0)
|
if (osmo_mdns_rfc_question_encode(ctx, msg, &qst) != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -106,7 +106,7 @@ int osmo_mdns_msg_answer_encode(void *ctx, struct msgb *msg, const struct osmo_m
|
|||||||
rec.rdlength = ans_record->length;
|
rec.rdlength = ans_record->length;
|
||||||
rec.rdata = ans_record->data;
|
rec.rdata = ans_record->data;
|
||||||
|
|
||||||
if (osmo_mdns_rfc_record_encode(msg, &rec) != 0)
|
if (osmo_mdns_rfc_record_encode(ctx, msg, &rec) != 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,91 @@
|
|||||||
#include <osmocom/core/msgb.h>
|
#include <osmocom/core/msgb.h>
|
||||||
#include <osmocom/core/bitvec.h>
|
#include <osmocom/core/bitvec.h>
|
||||||
#include <osmocom/core/logging.h>
|
#include <osmocom/core/logging.h>
|
||||||
#include <osmocom/gsm/apn.h>
|
|
||||||
#include <osmocom/mslookup/mdns_rfc.h>
|
#include <osmocom/mslookup/mdns_rfc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encode/decode IEs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! Encode a domain string as qname (RFC 1035 4.1.2).
|
||||||
|
* \param[in] domain multiple labels separated by dots, e.g. "sip.voice.1234.msisdn".
|
||||||
|
* \returns allocated buffer with length-value pairs for each label (e.g. 0x03 "sip" 0x05 "voice" ...), NULL on error.
|
||||||
|
*/
|
||||||
|
char *osmo_mdns_rfc_qname_encode(void *ctx, const char *domain)
|
||||||
|
{
|
||||||
|
char *domain_dup;
|
||||||
|
char *domain_iter;
|
||||||
|
char buf[OSMO_MDNS_RFC_MAX_NAME_LEN + 2] = ""; /* len(qname) is len(domain) +1 */
|
||||||
|
struct osmo_strbuf sb = { .buf = buf, .len = sizeof(buf) };
|
||||||
|
char *label;
|
||||||
|
|
||||||
|
if (strlen(domain) > OSMO_MDNS_RFC_MAX_NAME_LEN)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
domain_iter = domain_dup = talloc_strdup(ctx, domain);
|
||||||
|
while ((label = strsep(&domain_iter, "."))) {
|
||||||
|
size_t len = strlen(label);
|
||||||
|
|
||||||
|
/* Empty domain, dot at start, two dots in a row, or ending with a dot */
|
||||||
|
if (!len)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
OSMO_STRBUF_PRINTF(sb, "%c%s", (char)len, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
talloc_free(domain_dup);
|
||||||
|
return talloc_strdup(ctx, buf);
|
||||||
|
|
||||||
|
error:
|
||||||
|
talloc_free(domain_dup);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Decode a domain string from a qname (RFC 1035 4.1.2).
|
||||||
|
* \param[in] qname buffer with length-value pairs for each label (e.g. 0x03 "sip" 0x05 "voice" ...)
|
||||||
|
* \param[in] qname_max_len amount of bytes that can be read at most from the memory location that qname points to.
|
||||||
|
* \returns allocated buffer with domain string, multiple labels separated by dots (e.g. "sip.voice.1234.msisdn"),
|
||||||
|
* NULL on error.
|
||||||
|
*/
|
||||||
|
char *osmo_mdns_rfc_qname_decode(void *ctx, const char *qname, size_t qname_max_len)
|
||||||
|
{
|
||||||
|
const char *next_label, *qname_end = qname + qname_max_len;
|
||||||
|
char buf[OSMO_MDNS_RFC_MAX_NAME_LEN + 1];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (qname_max_len < 1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (*qname) {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (i >= qname_max_len)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = *qname;
|
||||||
|
next_label = qname + len + 1;
|
||||||
|
|
||||||
|
if (next_label >= qname_end || i + len > OSMO_MDNS_RFC_MAX_NAME_LEN)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (i) {
|
||||||
|
/* Two dots in a row is not allowed */
|
||||||
|
if (buf[i - 1] == '.')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
buf[i] = '.';
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf + i, qname + 1, len);
|
||||||
|
i += len;
|
||||||
|
qname = next_label;
|
||||||
|
}
|
||||||
|
buf[i] = '\0';
|
||||||
|
|
||||||
|
return talloc_strdup(ctx, buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Encode/decode message sections
|
* Encode/decode message sections
|
||||||
*/
|
*/
|
||||||
@@ -69,17 +151,20 @@ int osmo_mdns_rfc_header_decode(const uint8_t *data, size_t data_len, struct osm
|
|||||||
/*! Encode question section (RFC 1035 4.1.2).
|
/*! Encode question section (RFC 1035 4.1.2).
|
||||||
* \param[in] msgb mesage buffer to which the encoded data will be appended.
|
* \param[in] msgb mesage buffer to which the encoded data will be appended.
|
||||||
*/
|
*/
|
||||||
int osmo_mdns_rfc_question_encode(struct msgb *msg, const struct osmo_mdns_rfc_question *qst)
|
int osmo_mdns_rfc_question_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_question *qst)
|
||||||
{
|
{
|
||||||
uint8_t *buf;
|
char *qname;
|
||||||
size_t buf_len;
|
size_t qname_len;
|
||||||
|
uint8_t *qname_buf;
|
||||||
|
|
||||||
/* qname */
|
/* qname */
|
||||||
buf_len = strlen(qst->domain) + 1;
|
qname = osmo_mdns_rfc_qname_encode(ctx, qst->domain);
|
||||||
buf = msgb_put(msg, buf_len);
|
if (!qname)
|
||||||
if (osmo_apn_from_str(buf, buf_len, qst->domain) < 0)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
msgb_put_u8(msg, 0x00);
|
qname_len = strlen(qname) + 1;
|
||||||
|
qname_buf = msgb_put(msg, qname_len);
|
||||||
|
memcpy(qname_buf, qname, qname_len);
|
||||||
|
talloc_free(qname);
|
||||||
|
|
||||||
/* qtype and qclass */
|
/* qtype and qclass */
|
||||||
msgb_put_u16(msg, qst->qtype);
|
msgb_put_u16(msg, qst->qtype);
|
||||||
@@ -97,25 +182,21 @@ struct osmo_mdns_rfc_question *osmo_mdns_rfc_question_decode(void *ctx, const ui
|
|||||||
if (data_len < 6)
|
if (data_len < 6)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* qname */
|
||||||
ret = talloc_zero(ctx, struct osmo_mdns_rfc_question);
|
ret = talloc_zero(ctx, struct osmo_mdns_rfc_question);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
ret->domain = osmo_mdns_rfc_qname_decode(ret, (const char *)data, qname_len);
|
||||||
/* qname */
|
if (!ret->domain) {
|
||||||
ret->domain = talloc_size(ret, qname_len - 1);
|
talloc_free(ret);
|
||||||
if (!ret->domain)
|
return NULL;
|
||||||
goto error;
|
}
|
||||||
if (!osmo_apn_to_str(ret->domain, data, qname_len - 1))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* qtype and qclass */
|
/* qtype and qclass */
|
||||||
ret->qtype = osmo_load16be(data + qname_len);
|
ret->qtype = osmo_load16be(data + qname_len);
|
||||||
ret->qclass = osmo_load16be(data + qname_len + 2);
|
ret->qclass = osmo_load16be(data + qname_len + 2);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
error:
|
|
||||||
talloc_free(ret);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -125,17 +206,20 @@ error:
|
|||||||
/*! Encode one resource record (RFC 1035 4.1.3).
|
/*! Encode one resource record (RFC 1035 4.1.3).
|
||||||
* \param[in] msgb mesage buffer to which the encoded data will be appended.
|
* \param[in] msgb mesage buffer to which the encoded data will be appended.
|
||||||
*/
|
*/
|
||||||
int osmo_mdns_rfc_record_encode(struct msgb *msg, const struct osmo_mdns_rfc_record *rec)
|
int osmo_mdns_rfc_record_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_record *rec)
|
||||||
{
|
{
|
||||||
|
char *name;
|
||||||
|
size_t name_len;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
size_t buf_len;
|
|
||||||
|
|
||||||
/* name */
|
/* name */
|
||||||
buf_len = strlen(rec->domain) + 1;
|
name = osmo_mdns_rfc_qname_encode(ctx, rec->domain);
|
||||||
buf = msgb_put(msg, buf_len);
|
if (!name)
|
||||||
if (osmo_apn_from_str(buf, buf_len, rec->domain) < 0)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
msgb_put_u8(msg, 0x00);
|
name_len = strlen(name) + 1;
|
||||||
|
buf = msgb_put(msg, name_len);
|
||||||
|
memcpy(buf, name, name_len);
|
||||||
|
talloc_free(name);
|
||||||
|
|
||||||
/* type, class, ttl, rdlength */
|
/* type, class, ttl, rdlength */
|
||||||
msgb_put_u16(msg, rec->type);
|
msgb_put_u16(msg, rec->type);
|
||||||
@@ -153,26 +237,15 @@ int osmo_mdns_rfc_record_encode(struct msgb *msg, const struct osmo_mdns_rfc_rec
|
|||||||
struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_t *data, size_t data_len,
|
struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_t *data, size_t data_len,
|
||||||
size_t *record_len)
|
size_t *record_len)
|
||||||
{
|
{
|
||||||
struct osmo_mdns_rfc_record *ret;
|
struct osmo_mdns_rfc_record *ret = talloc_zero(ctx, struct osmo_mdns_rfc_record);
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
|
|
||||||
/* name length: represented as a series of labels, and terminated by a
|
/* name */
|
||||||
* label with zero length (RFC 1035 3.3). A label with zero length is a
|
ret->domain = osmo_mdns_rfc_qname_decode(ret, (const char *)data, data_len - 10);
|
||||||
* NUL byte. */
|
|
||||||
name_len = strnlen((const char *)data, data_len - 10) + 1;
|
|
||||||
if (data[name_len])
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* allocate ret + ret->domain */
|
|
||||||
ret = talloc_zero(ctx, struct osmo_mdns_rfc_record);
|
|
||||||
if (!ret)
|
|
||||||
return NULL;
|
|
||||||
ret->domain = talloc_size(ctx, name_len - 1);
|
|
||||||
if (!ret->domain)
|
if (!ret->domain)
|
||||||
goto error;
|
goto error;
|
||||||
|
name_len = strlen(ret->domain) + 2;
|
||||||
/* name */
|
if (name_len + 10 > data_len)
|
||||||
if (!osmo_apn_to_str(ret->domain, data, name_len - 1))
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* type, class, ttl, rdlength */
|
/* type, class, ttl, rdlength */
|
||||||
@@ -186,7 +259,7 @@ struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_
|
|||||||
/* rdata */
|
/* rdata */
|
||||||
ret->rdata = talloc_memdup(ret, data + name_len + 10, ret->rdlength);
|
ret->rdata = talloc_memdup(ret, data + name_len + 10, ret->rdlength);
|
||||||
if (!ret->rdata)
|
if (!ret->rdata)
|
||||||
goto error;
|
return NULL;
|
||||||
|
|
||||||
*record_len = name_len + 10 + ret->rdlength;
|
*record_len = name_len + 10 + ret->rdlength;
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static void print_version(void)
|
|||||||
"\n");
|
"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_help(void)
|
static void print_help()
|
||||||
{
|
{
|
||||||
print_version();
|
print_version();
|
||||||
printf(
|
printf(
|
||||||
@@ -419,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);
|
||||||
@@ -487,7 +487,7 @@ static int socket_cb(struct osmo_fd *ofd, unsigned int flags)
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (flags & OSMO_FD_READ)
|
if (flags & BSC_FD_READ)
|
||||||
rc = socket_read_cb(ofd);
|
rc = socket_read_cb(ofd);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
@@ -512,7 +512,7 @@ int socket_accept(struct osmo_fd *ofd, unsigned int flags)
|
|||||||
c = talloc_zero(globals.ctx, struct socket_client);
|
c = talloc_zero(globals.ctx, struct socket_client);
|
||||||
OSMO_ASSERT(c);
|
OSMO_ASSERT(c);
|
||||||
c->ofd.fd = rc;
|
c->ofd.fd = rc;
|
||||||
c->ofd.when = OSMO_FD_READ;
|
c->ofd.when = BSC_FD_READ;
|
||||||
c->ofd.cb = socket_cb;
|
c->ofd.cb = socket_cb;
|
||||||
c->ofd.data = c;
|
c->ofd.data = c;
|
||||||
|
|
||||||
@@ -543,7 +543,7 @@ int socket_init(const char *sock_path)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ofd->when = OSMO_FD_READ;
|
ofd->when = BSC_FD_READ;
|
||||||
ofd->cb = socket_accept;
|
ofd->cb = socket_accept;
|
||||||
|
|
||||||
rc = osmo_fd_register(ofd);
|
rc = osmo_fd_register(ofd);
|
||||||
@@ -555,15 +555,15 @@ int socket_init(const char *sock_path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_close(void)
|
void socket_close()
|
||||||
{
|
{
|
||||||
struct socket_client *c, *n;
|
struct socket_client *c, *n;
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ static void set_result(struct osmo_mslookup_result *result,
|
|||||||
result->age = age;
|
result->age = age;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct mslookup_service_host *mslookup_server_get_local_gsup_addr(void)
|
const struct mslookup_service_host *mslookup_server_get_local_gsup_addr()
|
||||||
{
|
{
|
||||||
static struct mslookup_service_host gsup_bind = {};
|
static struct mslookup_service_host gsup_bind = {};
|
||||||
struct mslookup_service_host *host;
|
struct mslookup_service_host *host;
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ void osmo_mslookup_server_mdns_stop(struct osmo_mslookup_server_mdns *server)
|
|||||||
talloc_free(server);
|
talloc_free(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mslookup_server_mdns_config_apply(void)
|
void mslookup_server_mdns_config_apply()
|
||||||
{
|
{
|
||||||
/* Check whether to start/stop/restart mDNS server */
|
/* Check whether to start/stop/restart mDNS server */
|
||||||
bool should_run;
|
bool should_run;
|
||||||
|
|||||||
16
src/proxy.c
16
src/proxy.c
@@ -29,7 +29,6 @@
|
|||||||
#include <osmocom/gsupclient/gsup_client.h>
|
#include <osmocom/gsupclient/gsup_client.h>
|
||||||
#include <osmocom/gsupclient/gsup_req.h>
|
#include <osmocom/gsupclient/gsup_req.h>
|
||||||
|
|
||||||
#include <osmocom/hlr/hlr.h>
|
|
||||||
#include <osmocom/hlr/logging.h>
|
#include <osmocom/hlr/logging.h>
|
||||||
#include <osmocom/hlr/proxy.h>
|
#include <osmocom/hlr/proxy.h>
|
||||||
#include <osmocom/hlr/remote_hlr.h>
|
#include <osmocom/hlr/remote_hlr.h>
|
||||||
@@ -81,19 +80,7 @@ static void proxy_deferred_gsup_req_add(struct proxy *proxy, struct osmo_gsup_re
|
|||||||
static void proxy_pending_req_remote_hlr_connect_result(struct osmo_gsup_req *req, struct remote_hlr *remote_hlr)
|
static void proxy_pending_req_remote_hlr_connect_result(struct osmo_gsup_req *req, struct remote_hlr *remote_hlr)
|
||||||
{
|
{
|
||||||
if (!remote_hlr || !remote_hlr_is_up(remote_hlr)) {
|
if (!remote_hlr || !remote_hlr_is_up(remote_hlr)) {
|
||||||
/* Do not respond with an error to a CHECK_IMEI_REQUEST as osmo-msc will send a LU Reject Cause #6
|
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN, "Proxy: Failed to connect to home HLR");
|
||||||
* Just respond ACK and deal with the IMSI check that comes next. */
|
|
||||||
if (req->gsup.message_type == OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST) {
|
|
||||||
/* Accept all IMEIs */
|
|
||||||
struct osmo_gsup_message gsup_reply = (struct osmo_gsup_message){
|
|
||||||
.message_type = OSMO_GSUP_MSGT_CHECK_IMEI_RESULT,
|
|
||||||
.imei_result = OSMO_GSUP_IMEI_RESULT_ACK,
|
|
||||||
};
|
|
||||||
osmo_gsup_req_respond(req, &gsup_reply, false, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
osmo_gsup_req_respond_err(req, g_hlr->no_proxy_reject_cause,
|
|
||||||
"Proxy: Failed to connect to home HLR");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +190,6 @@ int proxy_subscr_create_or_update(struct proxy *proxy, const struct proxy_subscr
|
|||||||
int _proxy_subscr_del(struct proxy_subscr_listentry *e)
|
int _proxy_subscr_del(struct proxy_subscr_listentry *e)
|
||||||
{
|
{
|
||||||
llist_del(&e->entry);
|
llist_del(&e->entry);
|
||||||
talloc_free(e);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
auc \
|
auc \
|
||||||
|
gsup_server \
|
||||||
db \
|
db \
|
||||||
gsup \
|
gsup \
|
||||||
db_upgrade \
|
db_upgrade \
|
||||||
@@ -69,9 +70,6 @@ vty-test:
|
|||||||
|
|
||||||
CTRL_TEST_DB = hlr_ctrl_test.db
|
CTRL_TEST_DB = hlr_ctrl_test.db
|
||||||
|
|
||||||
# Run a specific test with: 'make ctrl-test CTRL_TEST=test_subscriber.ctrl'
|
|
||||||
CTRL_TEST ?= *.ctrl
|
|
||||||
|
|
||||||
# To update the CTRL script from current application behavior,
|
# To update the CTRL script from current application behavior,
|
||||||
# pass -u to ctrl_script_runner.py by doing:
|
# pass -u to ctrl_script_runner.py by doing:
|
||||||
# make ctrl-test U=-u
|
# make ctrl-test U=-u
|
||||||
@@ -82,7 +80,7 @@ ctrl-test:
|
|||||||
osmo_verify_transcript_ctrl.py -v \
|
osmo_verify_transcript_ctrl.py -v \
|
||||||
-p 4259 \
|
-p 4259 \
|
||||||
-r "$(top_builddir)/src/osmo-hlr -c $(top_srcdir)/doc/examples/osmo-hlr.cfg -l $(CTRL_TEST_DB)" \
|
-r "$(top_builddir)/src/osmo-hlr -c $(top_srcdir)/doc/examples/osmo-hlr.cfg -l $(CTRL_TEST_DB)" \
|
||||||
$(U) $(srcdir)/$(CTRL_TEST)
|
$(U) $(srcdir)/*.ctrl
|
||||||
-rm -f $(CTRL_TEST_DB)
|
-rm -f $(CTRL_TEST_DB)
|
||||||
-rm $(CTRL_TEST_DB)-*
|
-rm $(CTRL_TEST_DB)-*
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -23,15 +23,17 @@ EXTRA_DIST = \
|
|||||||
auc_ts_55_205_test_sets.err \
|
auc_ts_55_205_test_sets.err \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
check_PROGRAMS = auc_test auc_ts_55_205_test_sets
|
check_PROGRAMS = auc_ts_55_205_test_sets
|
||||||
|
|
||||||
|
noinst_PROGRAMS = auc_test
|
||||||
|
|
||||||
auc_test_SOURCES = \
|
auc_test_SOURCES = \
|
||||||
auc_test.c \
|
auc_test.c \
|
||||||
$(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 +43,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)
|
||||||
|
|||||||
@@ -113,17 +113,16 @@ int rand_get(uint8_t *rand, unsigned int len)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 +130,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);
|
||||||
|
|
||||||
@@ -175,18 +174,16 @@ static void test_gen_vectors_2g_only(void)
|
|||||||
comment_end();
|
comment_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subscriber with separate 2G (COMP128v1) and 3G (MILENAGE) authentication data,
|
|
||||||
* 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 +191,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -289,13 +284,10 @@ void _test_gen_vectors_3g_only__expect_vecs(struct osmo_auth_vector vecs[3])
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subscriber with only 3G (MILENAGE) authentication data,
|
|
||||||
* reflects the default configuration of sysmoISIM-SJA2. Resulting
|
|
||||||
* 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 +296,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,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -464,58 +454,7 @@ static void test_gen_vectors_3g_only(void)
|
|||||||
comment_end();
|
comment_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subscriber with only 3G (XOR) authentication data,
|
void test_gen_vectors_bad_args()
|
||||||
* reflects the default configuration of sysmoTSIM-SJAx as well
|
|
||||||
* as many "Test USIM" cards. Resulting tuples are suitable for both
|
|
||||||
* 2G and 3G authentication */
|
|
||||||
static void test_gen_vectors_3g_xor(void)
|
|
||||||
{
|
|
||||||
struct osmo_sub_auth_data2 aud2g;
|
|
||||||
struct osmo_sub_auth_data2 aud3g;
|
|
||||||
struct osmo_auth_vector vec;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
comment_start();
|
|
||||||
|
|
||||||
aud2g = (struct osmo_sub_auth_data2){ 0 };
|
|
||||||
|
|
||||||
aud3g = (struct osmo_sub_auth_data2){
|
|
||||||
.type = OSMO_AUTH_TYPE_UMTS,
|
|
||||||
.algo = OSMO_AUTH_ALG_XOR_3G,
|
|
||||||
.u.umts.k_len = 16,
|
|
||||||
.u.umts.opc_len = 16,
|
|
||||||
.u.umts.sqn = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
osmo_hexparse("000102030405060708090a0b0c0d0e0f",
|
|
||||||
aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
|
|
||||||
osmo_hexparse("00000000000000000000000000000000",
|
|
||||||
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
|
|
||||||
next_rand("b5039c57e4a75051551d1a390a71ce48", true);
|
|
||||||
|
|
||||||
vec = (struct osmo_auth_vector){ {0} };
|
|
||||||
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
|
|
||||||
rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
|
|
||||||
VERBOSE_ASSERT(rc, == 1, "%d");
|
|
||||||
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
|
|
||||||
|
|
||||||
VEC_IS(&vec,
|
|
||||||
" rand: b5039c57e4a75051551d1a390a71ce48\n"
|
|
||||||
" autn: 54e0a256565d0000b5029e54e0a25656\n"
|
|
||||||
" ck: 029e54e0a256565d141032067cc047b5\n"
|
|
||||||
" ik: 9e54e0a256565d141032067cc047b502\n"
|
|
||||||
" res: b5029e54e0a256565d141032067cc047\n"
|
|
||||||
" res_len: 10\n"
|
|
||||||
" kc: 98e880384887f9fe\n"
|
|
||||||
" sres: 0ec81877\n"
|
|
||||||
" auth_types: 03000000\n"
|
|
||||||
);
|
|
||||||
|
|
||||||
comment_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Test a variety of invalid authentication data combinations */
|
|
||||||
void test_gen_vectors_bad_args(void)
|
|
||||||
{
|
{
|
||||||
struct osmo_auth_vector vec;
|
struct osmo_auth_vector vec;
|
||||||
uint8_t auts[14];
|
uint8_t auts[14];
|
||||||
@@ -523,43 +462,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;
|
||||||
@@ -678,20 +613,15 @@ int main(int argc, char **argv)
|
|||||||
void *tall_ctx = talloc_named_const(NULL, 1, "auc_test");
|
void *tall_ctx = talloc_named_const(NULL, 1, "auc_test");
|
||||||
|
|
||||||
osmo_init_logging2(tall_ctx, &hlr_log_info);
|
osmo_init_logging2(tall_ctx, &hlr_log_info);
|
||||||
log_set_print_filename2(osmo_stderr_target,
|
log_set_print_filename(osmo_stderr_target, cmdline_opts.verbose);
|
||||||
cmdline_opts.verbose ?
|
|
||||||
LOG_FILENAME_BASENAME :
|
|
||||||
LOG_FILENAME_NONE);
|
|
||||||
log_set_print_timestamp(osmo_stderr_target, 0);
|
log_set_print_timestamp(osmo_stderr_target, 0);
|
||||||
log_set_use_color(osmo_stderr_target, 0);
|
log_set_use_color(osmo_stderr_target, 0);
|
||||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
|
||||||
log_set_print_category(osmo_stderr_target, 1);
|
log_set_print_category(osmo_stderr_target, 1);
|
||||||
log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
|
log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
|
||||||
|
|
||||||
test_gen_vectors_2g_only();
|
test_gen_vectors_2g_only();
|
||||||
test_gen_vectors_2g_plus_3g();
|
test_gen_vectors_2g_plus_3g();
|
||||||
test_gen_vectors_3g_only();
|
test_gen_vectors_3g_only();
|
||||||
test_gen_vectors_3g_xor();
|
|
||||||
test_gen_vectors_bad_args();
|
test_gen_vectors_bad_args();
|
||||||
|
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
|
|||||||
@@ -217,29 +217,6 @@ DAUC vector [2]: auth_types = 0x3
|
|||||||
===== test_gen_vectors_3g_only: SUCCESS
|
===== test_gen_vectors_3g_only: SUCCESS
|
||||||
|
|
||||||
|
|
||||||
===== test_gen_vectors_3g_xor
|
|
||||||
aud3g.u.umts.sqn == 0
|
|
||||||
DAUC Computing 1 auth vector: 3G only (2G derived from 3G keys)
|
|
||||||
DAUC 3G: k = 000102030405060708090a0b0c0d0e0f
|
|
||||||
DAUC 3G: opc = 00000000000000000000000000000000
|
|
||||||
DAUC 3G: for sqn ind 0, previous sqn was 0
|
|
||||||
DAUC vector [0]: rand = b5039c57e4a75051551d1a390a71ce48
|
|
||||||
DAUC vector [0]: sqn = 0
|
|
||||||
DAUC vector [0]: autn = 54e0a256565d0000b5029e54e0a25656
|
|
||||||
DAUC vector [0]: ck = 029e54e0a256565d141032067cc047b5
|
|
||||||
DAUC vector [0]: ik = 9e54e0a256565d141032067cc047b502
|
|
||||||
DAUC vector [0]: res = b5029e54e0a256565d141032067cc047
|
|
||||||
DAUC vector [0]: res_len = 16
|
|
||||||
DAUC vector [0]: deriving 2G from 3G
|
|
||||||
DAUC vector [0]: kc = 98e880384887f9fe
|
|
||||||
DAUC vector [0]: sres = 0ec81877
|
|
||||||
DAUC vector [0]: auth_types = 0x3
|
|
||||||
rc == 1
|
|
||||||
aud3g.u.umts.sqn == 0
|
|
||||||
vector matches expectations
|
|
||||||
===== test_gen_vectors_3g_xor: SUCCESS
|
|
||||||
|
|
||||||
|
|
||||||
===== test_gen_vectors_bad_args
|
===== test_gen_vectors_bad_args
|
||||||
|
|
||||||
- no auth data (a)
|
- no auth data (a)
|
||||||
|
|||||||
@@ -24,46 +24,43 @@
|
|||||||
|
|
||||||
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,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
osmo_hexparse("{Ki}",
|
osmo_hexparse("{Ki}",
|
||||||
aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
|
aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
|
||||||
osmo_hexparse("{OPc}",
|
osmo_hexparse("{OPc}",
|
||||||
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
|
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
|
||||||
|
|
||||||
osmo_hexparse("{RAND}",
|
osmo_hexparse("{RAND}",
|
||||||
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");
|
||||||
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
|
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
|
||||||
|
|
||||||
VEC_IS(&vec,
|
VEC_IS(&vec,
|
||||||
" rand: {RAND}\n"
|
" rand: {RAND}\n"
|
||||||
" ck: {MIL3G-CK}\n"
|
" ck: {MIL3G-CK}\n"
|
||||||
" ik: {MIL3G-IK}\n"
|
" ik: {MIL3G-IK}\n"
|
||||||
" res: {MIL3G-RES}0000000000000000\n"
|
" res: {MIL3G-RES}0000000000000000\n"
|
||||||
" kc: {Kc}\n"
|
" kc: {Kc}\n"
|
||||||
" sres: {SRES#1}\n"
|
" sres: {SRES#1}\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
comment_end();
|
comment_end();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ char *vec_str(const struct osmo_auth_vector *vec)
|
|||||||
if (pos >= end) \
|
if (pos >= end) \
|
||||||
return buf; \
|
return buf; \
|
||||||
pos += snprintf(pos, sizeof(buf) - (pos - buf), \
|
pos += snprintf(pos, sizeof(buf) - (pos - buf), \
|
||||||
" " #what ": %s\n", \
|
" " #what ": %s\n", \
|
||||||
osmo_hexdump_nospc((void*)&vec->what, sizeof(vec->what)))
|
osmo_hexdump_nospc((void*)&vec->what, sizeof(vec->what)))
|
||||||
|
|
||||||
append(rand);
|
append(rand);
|
||||||
@@ -71,7 +71,7 @@ char *vec_str(const struct osmo_auth_vector *vec)
|
|||||||
|
|
||||||
#define VEC_IS(vec, expect) do { \
|
#define VEC_IS(vec, expect) do { \
|
||||||
char *_is = vec_str(vec); \
|
char *_is = vec_str(vec); \
|
||||||
if (strcmp(_is, expect)) { \
|
if (strcmp(_is, expect)) { \
|
||||||
fprintf(stderr, "MISMATCH! expected ==\n%s\n", \
|
fprintf(stderr, "MISMATCH! expected ==\n%s\n", \
|
||||||
expect); \
|
expect); \
|
||||||
char *a = _is; \
|
char *a = _is; \
|
||||||
@@ -100,16 +100,15 @@ int rand_get(uint8_t *rand, unsigned int len)
|
|||||||
|
|
||||||
FUNCTIONS
|
FUNCTIONS
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main()
|
||||||
{
|
{
|
||||||
printf("3GPP TS 55.205 Test Sets\n");
|
printf("3GPP TS 55.205 Test Sets\n");
|
||||||
void *tall_ctx = talloc_named_const(NULL, 1, "test");
|
void *tall_ctx = talloc_named_const(NULL, 1, "test");
|
||||||
msgb_talloc_ctx_init(tall_ctx, 0);
|
msgb_talloc_ctx_init(tall_ctx, 0);
|
||||||
osmo_init_logging2(tall_ctx, &hlr_log_info);
|
osmo_init_logging2(tall_ctx, &hlr_log_info);
|
||||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
log_set_print_filename(osmo_stderr_target, 0);
|
||||||
log_set_print_timestamp(osmo_stderr_target, 0);
|
log_set_print_timestamp(osmo_stderr_target, 0);
|
||||||
log_set_use_color(osmo_stderr_target, 0);
|
log_set_use_color(osmo_stderr_target, 0);
|
||||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
|
||||||
log_set_print_category(osmo_stderr_target, 1);
|
log_set_print_category(osmo_stderr_target, 1);
|
||||||
log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
|
log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
|
||||||
|
|
||||||
|
|||||||
@@ -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) \
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -250,7 +246,7 @@ static int db_subscr_lu_str(struct db_context *dbc, int64_t subscr_id,
|
|||||||
return db_subscr_lu(dbc, subscr_id, &vlr_nr, is_ps, NULL);
|
return db_subscr_lu(dbc, subscr_id, &vlr_nr, is_ps, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_subscr_create_update_sel_delete(void)
|
static void test_subscr_create_update_sel_delete()
|
||||||
{
|
{
|
||||||
int64_t id0, id1, id2, id_short;
|
int64_t id0, id1, id2, id_short;
|
||||||
comment_start();
|
comment_start();
|
||||||
@@ -266,13 +262,13 @@ static void test_subscr_create_update_sel_delete(void)
|
|||||||
ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
|
ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), 0);
|
||||||
ASSERT_SEL(imsi, imsi2, 0);
|
ASSERT_SEL(imsi, imsi2, 0);
|
||||||
id2 = g_subscr.id;
|
id2 = g_subscr.id;
|
||||||
ASSERT_RC(db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
|
ASSERT_RC(db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EIO);
|
||||||
ASSERT_SEL(imsi, imsi0, 0);
|
ASSERT_SEL(imsi, imsi0, 0);
|
||||||
ASSERT_RC(db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
|
ASSERT_RC(db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EIO);
|
||||||
ASSERT_RC(db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
|
ASSERT_RC(db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EIO);
|
||||||
ASSERT_SEL(imsi, imsi1, 0);
|
ASSERT_SEL(imsi, imsi1, 0);
|
||||||
ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
|
ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EIO);
|
||||||
ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EEXIST);
|
ASSERT_RC(db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EIO);
|
||||||
ASSERT_SEL(imsi, imsi2, 0);
|
ASSERT_SEL(imsi, imsi2, 0);
|
||||||
|
|
||||||
ASSERT_RC(db_subscr_create(dbc, "123456789 000003", DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EINVAL);
|
ASSERT_RC(db_subscr_create(dbc, "123456789 000003", DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS), -EINVAL);
|
||||||
@@ -545,7 +541,7 @@ static const struct sub_auth_data_str *mk_aud_3g(enum osmo_auth_algo algo,
|
|||||||
return &aud;
|
return &aud;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_subscr_aud(void)
|
static void test_subscr_aud()
|
||||||
{
|
{
|
||||||
int64_t id;
|
int64_t id;
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|
||||||
@@ -787,7 +783,7 @@ static void test_subscr_aud(void)
|
|||||||
|
|
||||||
/* Make each key too short in this test. Note that we can't set them longer than the allowed size without changing the
|
/* Make each key too short in this test. Note that we can't set them longer than the allowed size without changing the
|
||||||
* table structure. */
|
* table structure. */
|
||||||
static void test_subscr_aud_invalid_len(void)
|
static void test_subscr_aud_invalid_len()
|
||||||
{
|
{
|
||||||
int64_t id;
|
int64_t id;
|
||||||
|
|
||||||
@@ -849,7 +845,7 @@ static void test_subscr_aud_invalid_len(void)
|
|||||||
comment_end();
|
comment_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_subscr_sqn(void)
|
static void test_subscr_sqn()
|
||||||
{
|
{
|
||||||
int64_t id;
|
int64_t id;
|
||||||
|
|
||||||
@@ -922,50 +918,6 @@ static void test_subscr_sqn(void)
|
|||||||
comment_end();
|
comment_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_ind(void)
|
|
||||||
{
|
|
||||||
comment_start();
|
|
||||||
|
|
||||||
#define ASSERT_IND(VLR, IND) do { \
|
|
||||||
unsigned int ind; \
|
|
||||||
struct osmo_cni_peer_id vlr; \
|
|
||||||
OSMO_ASSERT(!osmo_cni_peer_id_set_str(&vlr, OSMO_CNI_PEER_ID_IPA_NAME, VLR)); \
|
|
||||||
ASSERT_RC(db_ind(dbc, &vlr, &ind), 0); \
|
|
||||||
fprintf(stderr, "%s ind = %u\n\n", osmo_quote_str((char*)vlr.ipa_name.val, vlr.ipa_name.len), ind); \
|
|
||||||
if (ind != (IND)) \
|
|
||||||
fprintf(stderr, " ERROR: expected " #IND "\n"); \
|
|
||||||
} while (0)
|
|
||||||
#define IND_DEL(VLR) do { \
|
|
||||||
struct osmo_cni_peer_id vlr; \
|
|
||||||
OSMO_ASSERT(!osmo_cni_peer_id_set_str(&vlr, OSMO_CNI_PEER_ID_IPA_NAME, VLR)); \
|
|
||||||
ASSERT_RC(db_ind_del(dbc, &vlr), 0); \
|
|
||||||
fprintf(stderr, "%s ind deleted\n\n", osmo_quote_str((char*)vlr.ipa_name.val, vlr.ipa_name.len)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
ASSERT_IND("msc-23", 1);
|
|
||||||
ASSERT_IND("sgsn-11", 2);
|
|
||||||
ASSERT_IND("msc-42", 3);
|
|
||||||
ASSERT_IND("sgsn-22", 4);
|
|
||||||
ASSERT_IND("msc-0x17", 5);
|
|
||||||
ASSERT_IND("sgsn-0xaa", 6);
|
|
||||||
ASSERT_IND("msc-42", 3);
|
|
||||||
ASSERT_IND("sgsn-22", 4);
|
|
||||||
ASSERT_IND("msc-0x17", 5);
|
|
||||||
ASSERT_IND("sgsn-0xaa", 6);
|
|
||||||
ASSERT_IND("sgsn-0xbb", 7);
|
|
||||||
ASSERT_IND("msc-0x2a", 8);
|
|
||||||
ASSERT_IND("msc-42", 3);
|
|
||||||
ASSERT_IND("sgsn-22", 4);
|
|
||||||
ASSERT_IND("msc-23", 1);
|
|
||||||
ASSERT_IND("sgsn-11", 2);
|
|
||||||
|
|
||||||
IND_DEL("msc-0x17"); /* dropped IND == 5 */
|
|
||||||
ASSERT_IND("msc-0x2a", 8); /* known CS remains where it is */
|
|
||||||
ASSERT_IND("any-unknown", 9); /* new VLR takes a new IND from the end */
|
|
||||||
|
|
||||||
comment_end();
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
bool verbose;
|
bool verbose;
|
||||||
} cmdline_opts = {
|
} cmdline_opts = {
|
||||||
@@ -1028,13 +980,9 @@ int main(int argc, char **argv)
|
|||||||
handle_options(argc, argv);
|
handle_options(argc, argv);
|
||||||
|
|
||||||
osmo_init_logging2(ctx, &hlr_log_info);
|
osmo_init_logging2(ctx, &hlr_log_info);
|
||||||
log_set_print_filename2(osmo_stderr_target,
|
log_set_print_filename(osmo_stderr_target, cmdline_opts.verbose);
|
||||||
cmdline_opts.verbose ?
|
|
||||||
LOG_FILENAME_BASENAME :
|
|
||||||
LOG_FILENAME_NONE);
|
|
||||||
log_set_print_timestamp(osmo_stderr_target, 0);
|
log_set_print_timestamp(osmo_stderr_target, 0);
|
||||||
log_set_use_color(osmo_stderr_target, 0);
|
log_set_use_color(osmo_stderr_target, 0);
|
||||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
|
||||||
log_set_print_category(osmo_stderr_target, 1);
|
log_set_print_category(osmo_stderr_target, 1);
|
||||||
log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
|
log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
|
||||||
|
|
||||||
@@ -1050,7 +998,6 @@ int main(int argc, char **argv)
|
|||||||
test_subscr_aud();
|
test_subscr_aud();
|
||||||
test_subscr_aud_invalid_len();
|
test_subscr_aud_invalid_len();
|
||||||
test_subscr_sqn();
|
test_subscr_sqn();
|
||||||
test_ind();
|
|
||||||
|
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
db_close(dbc);
|
db_close(dbc);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ struct hlr_subscriber {
|
|||||||
.imsi = '123456789000002',
|
.imsi = '123456789000002',
|
||||||
}
|
}
|
||||||
|
|
||||||
db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EEXIST
|
db_subscr_create(dbc, imsi0, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EIO
|
||||||
DAUC IMSI='123456789000000': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
DAUC IMSI='123456789000000': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
||||||
|
|
||||||
db_subscr_get_by_imsi(dbc, imsi0, &g_subscr) --> 0
|
db_subscr_get_by_imsi(dbc, imsi0, &g_subscr) --> 0
|
||||||
@@ -36,10 +36,10 @@ struct hlr_subscriber {
|
|||||||
.imsi = '123456789000000',
|
.imsi = '123456789000000',
|
||||||
}
|
}
|
||||||
|
|
||||||
db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EEXIST
|
db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EIO
|
||||||
DAUC IMSI='123456789000001': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
DAUC IMSI='123456789000001': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
||||||
|
|
||||||
db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EEXIST
|
db_subscr_create(dbc, imsi1, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EIO
|
||||||
DAUC IMSI='123456789000001': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
DAUC IMSI='123456789000001': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
||||||
|
|
||||||
db_subscr_get_by_imsi(dbc, imsi1, &g_subscr) --> 0
|
db_subscr_get_by_imsi(dbc, imsi1, &g_subscr) --> 0
|
||||||
@@ -48,10 +48,10 @@ struct hlr_subscriber {
|
|||||||
.imsi = '123456789000001',
|
.imsi = '123456789000001',
|
||||||
}
|
}
|
||||||
|
|
||||||
db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EEXIST
|
db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EIO
|
||||||
DAUC IMSI='123456789000002': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
DAUC IMSI='123456789000002': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
||||||
|
|
||||||
db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EEXIST
|
db_subscr_create(dbc, imsi2, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS) --> -EIO
|
||||||
DAUC IMSI='123456789000002': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
DAUC IMSI='123456789000002': Cannot create subscriber: SQL error: (2067) UNIQUE constraint failed: subscriber.imsi
|
||||||
|
|
||||||
db_subscr_get_by_imsi(dbc, imsi2, &g_subscr) --> 0
|
db_subscr_get_by_imsi(dbc, imsi2, &g_subscr) --> 0
|
||||||
@@ -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',
|
||||||
@@ -1613,83 +1613,3 @@ db_subscr_get_by_imsi(dbc, imsi0, &g_subscr) --> -ENOENT
|
|||||||
|
|
||||||
===== test_subscr_sqn: SUCCESS
|
===== test_subscr_sqn: SUCCESS
|
||||||
|
|
||||||
|
|
||||||
===== test_ind
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-23\0" ind = 1
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"sgsn-11\0" ind = 2
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-42\0" ind = 3
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"sgsn-22\0" ind = 4
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-0x17\0" ind = 5
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"sgsn-0xaa\0" ind = 6
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-42\0" ind = 3
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"sgsn-22\0" ind = 4
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-0x17\0" ind = 5
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"sgsn-0xaa\0" ind = 6
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"sgsn-0xbb\0" ind = 7
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-0x2a\0" ind = 8
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-42\0" ind = 3
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"sgsn-22\0" ind = 4
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-23\0" ind = 1
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"sgsn-11\0" ind = 2
|
|
||||||
|
|
||||||
db_ind_del(dbc, &vlr) --> 0
|
|
||||||
|
|
||||||
"msc-0x17\0" ind deleted
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"msc-0x2a\0" ind = 8
|
|
||||||
|
|
||||||
db_ind(dbc, &vlr, &ind) --> 0
|
|
||||||
|
|
||||||
"any-unknown\0" ind = 9
|
|
||||||
|
|
||||||
===== test_ind: SUCCESS
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -85,8 +85,6 @@ DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 2
|
|||||||
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 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 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 +99,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
|
||||||
|
|
||||||
@@ -119,13 +117,6 @@ algo_id_3g|ind_bitlen|k|op|opc|sqn|subscriber_id
|
|||||||
5|5|44444444444444444444444444444444|44444444444444444444444444444444||0|5
|
5|5|44444444444444444444444444444444|44444444444444444444444444444444||0|5
|
||||||
5|5|55555555555555555555555555555555||55555555555555555555555555555555|0|6
|
5|5|55555555555555555555555555555555||55555555555555555555555555555555|0|6
|
||||||
|
|
||||||
Table: ind
|
|
||||||
name|type|notnull|dflt_value|pk
|
|
||||||
ind|INTEGER|0||1
|
|
||||||
vlr|TEXT|1||0
|
|
||||||
|
|
||||||
Table ind contents:
|
|
||||||
|
|
||||||
Table: subscriber
|
Table: subscriber
|
||||||
name|type|notnull|dflt_value|pk
|
name|type|notnull|dflt_value|pk
|
||||||
ggsn_number|VARCHAR(15)|0||0
|
ggsn_number|VARCHAR(15)|0||0
|
||||||
@@ -180,5 +171,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 5
|
||||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
|
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -17,7 +17,7 @@ EXTRA_DIST = \
|
|||||||
gsup_test.err \
|
gsup_test.err \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
check_PROGRAMS = \
|
noinst_PROGRAMS = \
|
||||||
gsup_test \
|
gsup_test \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
ctx = talloc_named_const(NULL, 0, "gsup_test");
|
ctx = talloc_named_const(NULL, 0, "gsup_test");
|
||||||
osmo_init_logging2(ctx, &info);
|
osmo_init_logging2(ctx, &info);
|
||||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
log_set_print_filename(osmo_stderr_target, 0);
|
||||||
log_set_print_timestamp(osmo_stderr_target, 0);
|
log_set_print_timestamp(osmo_stderr_target, 0);
|
||||||
log_set_use_color(osmo_stderr_target, 0);
|
log_set_use_color(osmo_stderr_target, 0);
|
||||||
log_set_print_category(osmo_stderr_target, 1);
|
log_set_print_category(osmo_stderr_target, 1);
|
||||||
|
|||||||
44
tests/gsup_server/Makefile.am
Normal file
44
tests/gsup_server/Makefile.am
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
AM_CPPFLAGS = \
|
||||||
|
$(all_includes) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
AM_CFLAGS = \
|
||||||
|
-Wall \
|
||||||
|
-ggdb3 \
|
||||||
|
-I$(top_srcdir)/include \
|
||||||
|
$(LIBOSMOCORE_CFLAGS) \
|
||||||
|
$(LIBOSMOGSM_CFLAGS) \
|
||||||
|
$(LIBOSMOABIS_CFLAGS) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
AM_LDFLAGS = \
|
||||||
|
-no-install \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
gsup_server_test.ok \
|
||||||
|
gsup_server_test.err \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
noinst_PROGRAMS = \
|
||||||
|
gsup_server_test \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
gsup_server_test_SOURCES = \
|
||||||
|
gsup_server_test.c \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
gsup_server_test_LDADD = \
|
||||||
|
$(top_srcdir)/src/gsup_server.c \
|
||||||
|
$(top_srcdir)/src/gsup_router.c \
|
||||||
|
$(top_srcdir)/src/gsup_send.c \
|
||||||
|
$(top_srcdir)/src/gsupclient/cni_peer_id.c \
|
||||||
|
$(top_srcdir)/src/gsupclient/gsup_req.c \
|
||||||
|
$(LIBOSMOCORE_LIBS) \
|
||||||
|
$(LIBOSMOGSM_LIBS) \
|
||||||
|
$(LIBOSMOABIS_LIBS) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
.PHONY: update_exp
|
||||||
|
update_exp:
|
||||||
|
$(builddir)/gsup_server_test >"$(srcdir)/gsup_server_test.ok" 2>"$(srcdir)/gsup_server_test.err"
|
||||||
145
tests/gsup_server/gsup_server_test.c
Normal file
145
tests/gsup_server/gsup_server_test.c
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
|
||||||
|
*
|
||||||
|
* 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 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 <stdio.h>
|
||||||
|
#include <osmocom/core/utils.h>
|
||||||
|
#include <osmocom/hlr/gsup_server.h>
|
||||||
|
|
||||||
|
#define comment_start() printf("\n===== %s\n", __func__)
|
||||||
|
#define comment_end() printf("===== %s: SUCCESS\n\n", __func__)
|
||||||
|
#define btw(fmt, args...) printf("\n" fmt "\n", ## args)
|
||||||
|
|
||||||
|
#define VERBOSE_ASSERT(val, expect_op, fmt) \
|
||||||
|
do { \
|
||||||
|
printf(#val " == " fmt "\n", (val)); \
|
||||||
|
OSMO_ASSERT((val) expect_op); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void osmo_gsup_server_add_conn(struct llist_head *clients,
|
||||||
|
struct osmo_gsup_conn *conn);
|
||||||
|
|
||||||
|
static void test_add_conn(void)
|
||||||
|
{
|
||||||
|
struct llist_head _list;
|
||||||
|
struct llist_head *clients = &_list;
|
||||||
|
struct osmo_gsup_conn conn_inst[23] = {};
|
||||||
|
struct osmo_gsup_conn *conn;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
comment_start();
|
||||||
|
|
||||||
|
INIT_LLIST_HEAD(clients);
|
||||||
|
|
||||||
|
btw("Add 10 items");
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
osmo_gsup_server_add_conn(clients, &conn_inst[i]);
|
||||||
|
printf("conn_inst[%u].auc_3g_ind == %u\n", i, conn_inst[i].auc_3g_ind);
|
||||||
|
OSMO_ASSERT(clients->next == &conn_inst[0].list);
|
||||||
|
}
|
||||||
|
|
||||||
|
btw("Expecting a list of 0..9");
|
||||||
|
i = 0;
|
||||||
|
llist_for_each_entry(conn, clients, list) {
|
||||||
|
printf("conn[%u].auc_3g_ind == %u\n", i, conn->auc_3g_ind);
|
||||||
|
OSMO_ASSERT(conn->auc_3g_ind == i);
|
||||||
|
OSMO_ASSERT(conn == &conn_inst[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
btw("Punch two holes in the sequence in arbitrary order,"
|
||||||
|
" a larger one from 2..4 and a single one at 7.");
|
||||||
|
llist_del(&conn_inst[4].list);
|
||||||
|
llist_del(&conn_inst[2].list);
|
||||||
|
llist_del(&conn_inst[3].list);
|
||||||
|
llist_del(&conn_inst[7].list);
|
||||||
|
|
||||||
|
btw("Expecting a list of 0,1, 5,6, 8,9");
|
||||||
|
i = 0;
|
||||||
|
llist_for_each_entry(conn, clients, list) {
|
||||||
|
printf("conn[%u].auc_3g_ind == %u\n", i, conn->auc_3g_ind);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
btw("Add conns, expecting them to take the open slots");
|
||||||
|
osmo_gsup_server_add_conn(clients, &conn_inst[12]);
|
||||||
|
VERBOSE_ASSERT(conn_inst[12].auc_3g_ind, == 2, "%u");
|
||||||
|
|
||||||
|
osmo_gsup_server_add_conn(clients, &conn_inst[13]);
|
||||||
|
VERBOSE_ASSERT(conn_inst[13].auc_3g_ind, == 3, "%u");
|
||||||
|
|
||||||
|
osmo_gsup_server_add_conn(clients, &conn_inst[14]);
|
||||||
|
VERBOSE_ASSERT(conn_inst[14].auc_3g_ind, == 4, "%u");
|
||||||
|
|
||||||
|
osmo_gsup_server_add_conn(clients, &conn_inst[17]);
|
||||||
|
VERBOSE_ASSERT(conn_inst[17].auc_3g_ind, == 7, "%u");
|
||||||
|
|
||||||
|
osmo_gsup_server_add_conn(clients, &conn_inst[18]);
|
||||||
|
VERBOSE_ASSERT(conn_inst[18].auc_3g_ind, == 10, "%u");
|
||||||
|
|
||||||
|
btw("Expecting a list of 0..10");
|
||||||
|
i = 0;
|
||||||
|
llist_for_each_entry(conn, clients, list) {
|
||||||
|
printf("conn[%u].auc_3g_ind == %u\n", i, conn->auc_3g_ind);
|
||||||
|
OSMO_ASSERT(conn->auc_3g_ind == i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
btw("Does it also work for the first item?");
|
||||||
|
llist_del(&conn_inst[0].list);
|
||||||
|
|
||||||
|
btw("Expecting a list of 1..10");
|
||||||
|
i = 0;
|
||||||
|
llist_for_each_entry(conn, clients, list) {
|
||||||
|
printf("conn[%u].auc_3g_ind == %u\n", i, conn->auc_3g_ind);
|
||||||
|
OSMO_ASSERT(conn->auc_3g_ind == i + 1);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
btw("Add another conn, should take auc_3g_ind == 0");
|
||||||
|
osmo_gsup_server_add_conn(clients, &conn_inst[20]);
|
||||||
|
VERBOSE_ASSERT(conn_inst[20].auc_3g_ind, == 0, "%u");
|
||||||
|
|
||||||
|
btw("Expecting a list of 0..10");
|
||||||
|
i = 0;
|
||||||
|
llist_for_each_entry(conn, clients, list) {
|
||||||
|
printf("conn[%u].auc_3g_ind == %u\n", i, conn->auc_3g_ind);
|
||||||
|
OSMO_ASSERT(conn->auc_3g_ind == i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
btw("If a client reconnects, it will (likely) get the same auc_3g_ind");
|
||||||
|
VERBOSE_ASSERT(conn_inst[5].auc_3g_ind, == 5, "%u");
|
||||||
|
llist_del(&conn_inst[5].list);
|
||||||
|
conn_inst[5].auc_3g_ind = 423;
|
||||||
|
osmo_gsup_server_add_conn(clients, &conn_inst[5]);
|
||||||
|
VERBOSE_ASSERT(conn_inst[5].auc_3g_ind, == 5, "%u");
|
||||||
|
|
||||||
|
comment_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
printf("test_gsup_server.c\n");
|
||||||
|
|
||||||
|
test_add_conn();
|
||||||
|
|
||||||
|
printf("Done\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
0
tests/gsup_server/gsup_server_test.err
Normal file
0
tests/gsup_server/gsup_server_test.err
Normal file
94
tests/gsup_server/gsup_server_test.ok
Normal file
94
tests/gsup_server/gsup_server_test.ok
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
test_gsup_server.c
|
||||||
|
|
||||||
|
===== test_add_conn
|
||||||
|
|
||||||
|
Add 10 items
|
||||||
|
conn_inst[0].auc_3g_ind == 0
|
||||||
|
conn_inst[1].auc_3g_ind == 1
|
||||||
|
conn_inst[2].auc_3g_ind == 2
|
||||||
|
conn_inst[3].auc_3g_ind == 3
|
||||||
|
conn_inst[4].auc_3g_ind == 4
|
||||||
|
conn_inst[5].auc_3g_ind == 5
|
||||||
|
conn_inst[6].auc_3g_ind == 6
|
||||||
|
conn_inst[7].auc_3g_ind == 7
|
||||||
|
conn_inst[8].auc_3g_ind == 8
|
||||||
|
conn_inst[9].auc_3g_ind == 9
|
||||||
|
|
||||||
|
Expecting a list of 0..9
|
||||||
|
conn[0].auc_3g_ind == 0
|
||||||
|
conn[1].auc_3g_ind == 1
|
||||||
|
conn[2].auc_3g_ind == 2
|
||||||
|
conn[3].auc_3g_ind == 3
|
||||||
|
conn[4].auc_3g_ind == 4
|
||||||
|
conn[5].auc_3g_ind == 5
|
||||||
|
conn[6].auc_3g_ind == 6
|
||||||
|
conn[7].auc_3g_ind == 7
|
||||||
|
conn[8].auc_3g_ind == 8
|
||||||
|
conn[9].auc_3g_ind == 9
|
||||||
|
|
||||||
|
Punch two holes in the sequence in arbitrary order, a larger one from 2..4 and a single one at 7.
|
||||||
|
|
||||||
|
Expecting a list of 0,1, 5,6, 8,9
|
||||||
|
conn[0].auc_3g_ind == 0
|
||||||
|
conn[1].auc_3g_ind == 1
|
||||||
|
conn[2].auc_3g_ind == 5
|
||||||
|
conn[3].auc_3g_ind == 6
|
||||||
|
conn[4].auc_3g_ind == 8
|
||||||
|
conn[5].auc_3g_ind == 9
|
||||||
|
|
||||||
|
Add conns, expecting them to take the open slots
|
||||||
|
conn_inst[12].auc_3g_ind == 2
|
||||||
|
conn_inst[13].auc_3g_ind == 3
|
||||||
|
conn_inst[14].auc_3g_ind == 4
|
||||||
|
conn_inst[17].auc_3g_ind == 7
|
||||||
|
conn_inst[18].auc_3g_ind == 10
|
||||||
|
|
||||||
|
Expecting a list of 0..10
|
||||||
|
conn[0].auc_3g_ind == 0
|
||||||
|
conn[1].auc_3g_ind == 1
|
||||||
|
conn[2].auc_3g_ind == 2
|
||||||
|
conn[3].auc_3g_ind == 3
|
||||||
|
conn[4].auc_3g_ind == 4
|
||||||
|
conn[5].auc_3g_ind == 5
|
||||||
|
conn[6].auc_3g_ind == 6
|
||||||
|
conn[7].auc_3g_ind == 7
|
||||||
|
conn[8].auc_3g_ind == 8
|
||||||
|
conn[9].auc_3g_ind == 9
|
||||||
|
conn[10].auc_3g_ind == 10
|
||||||
|
|
||||||
|
Does it also work for the first item?
|
||||||
|
|
||||||
|
Expecting a list of 1..10
|
||||||
|
conn[0].auc_3g_ind == 1
|
||||||
|
conn[1].auc_3g_ind == 2
|
||||||
|
conn[2].auc_3g_ind == 3
|
||||||
|
conn[3].auc_3g_ind == 4
|
||||||
|
conn[4].auc_3g_ind == 5
|
||||||
|
conn[5].auc_3g_ind == 6
|
||||||
|
conn[6].auc_3g_ind == 7
|
||||||
|
conn[7].auc_3g_ind == 8
|
||||||
|
conn[8].auc_3g_ind == 9
|
||||||
|
conn[9].auc_3g_ind == 10
|
||||||
|
|
||||||
|
Add another conn, should take auc_3g_ind == 0
|
||||||
|
conn_inst[20].auc_3g_ind == 0
|
||||||
|
|
||||||
|
Expecting a list of 0..10
|
||||||
|
conn[0].auc_3g_ind == 0
|
||||||
|
conn[1].auc_3g_ind == 1
|
||||||
|
conn[2].auc_3g_ind == 2
|
||||||
|
conn[3].auc_3g_ind == 3
|
||||||
|
conn[4].auc_3g_ind == 4
|
||||||
|
conn[5].auc_3g_ind == 5
|
||||||
|
conn[6].auc_3g_ind == 6
|
||||||
|
conn[7].auc_3g_ind == 7
|
||||||
|
conn[8].auc_3g_ind == 8
|
||||||
|
conn[9].auc_3g_ind == 9
|
||||||
|
conn[10].auc_3g_ind == 10
|
||||||
|
|
||||||
|
If a client reconnects, it will (likely) get the same auc_3g_ind
|
||||||
|
conn_inst[5].auc_3g_ind == 5
|
||||||
|
conn_inst[5].auc_3g_ind == 5
|
||||||
|
===== test_add_conn: SUCCESS
|
||||||
|
|
||||||
|
Done
|
||||||
@@ -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) \
|
||||||
|
|||||||
@@ -32,6 +32,148 @@ struct qname_enc_dec_test {
|
|||||||
size_t qname_max_len; /* default: strlen(qname) + 1 */
|
size_t qname_max_len; /* default: strlen(qname) + 1 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct qname_enc_dec_test qname_enc_dec_test_data[] = {
|
||||||
|
{
|
||||||
|
/* OK: typical mslookup domain */
|
||||||
|
.domain = "hlr.1234567.imsi",
|
||||||
|
.qname = "\x03" "hlr" "\x07" "1234567" "\x04" "imsi",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Wrong format: double dot */
|
||||||
|
.domain = "hlr..imsi",
|
||||||
|
.qname = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Wrong format: double dot */
|
||||||
|
.domain = "hlr",
|
||||||
|
.qname = "\x03hlr\0\x03imsi",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Wrong format: dot at end */
|
||||||
|
.domain = "hlr.",
|
||||||
|
.qname = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Wrong format: dot at start */
|
||||||
|
.domain = ".hlr",
|
||||||
|
.qname = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Wrong format: empty */
|
||||||
|
.domain = "",
|
||||||
|
.qname = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* OK: maximum length */
|
||||||
|
.domain =
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"12345"
|
||||||
|
,
|
||||||
|
.qname =
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\x05" "12345"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Error: too long domain */
|
||||||
|
.domain =
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"123456789." "123456789." "123456789." "123456789." "123456789."
|
||||||
|
"12345toolong"
|
||||||
|
,
|
||||||
|
.qname = NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Error: too long qname */
|
||||||
|
.domain = NULL,
|
||||||
|
.qname =
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
"\t123456789\t123456789\t123456789\t123456789\t123456789"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Error: wrong token length in qname */
|
||||||
|
.domain = NULL,
|
||||||
|
.qname = "\x03" "hlr" "\x07" "1234567" "\x05" "imsi",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Error: wrong token length in qname */
|
||||||
|
.domain = NULL,
|
||||||
|
.qname = "\x02" "hlr" "\x07" "1234567" "\x04" "imsi",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Wrong format: token length at end of qname */
|
||||||
|
.domain = NULL,
|
||||||
|
.qname = "\x03hlr\x03",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* Error: overflow in label length */
|
||||||
|
.domain = NULL,
|
||||||
|
.qname = "\x03" "hlr" "\x07" "1234567" "\x04" "imsi",
|
||||||
|
.qname_max_len = 17,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_enc_dec_rfc_qname(void *ctx)
|
||||||
|
{
|
||||||
|
char quote_buf[300];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
fprintf(stderr, "-- %s --\n", __func__);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(qname_enc_dec_test_data); i++) {
|
||||||
|
const struct qname_enc_dec_test *t = &qname_enc_dec_test_data[i];
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
if (t->domain) {
|
||||||
|
fprintf(stderr, "domain: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), t->domain, -1));
|
||||||
|
fprintf(stderr, "exp: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), t->qname, -1));
|
||||||
|
res = osmo_mdns_rfc_qname_encode(ctx, t->domain);
|
||||||
|
fprintf(stderr, "res: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), res, -1));
|
||||||
|
if (t->qname == res || (t->qname && res && strcmp(t->qname, res) == 0))
|
||||||
|
fprintf(stderr, "=> OK\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "=> ERROR\n");
|
||||||
|
if (res)
|
||||||
|
talloc_free(res);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t->qname) {
|
||||||
|
size_t qname_max_len = t->qname_max_len;
|
||||||
|
if (qname_max_len)
|
||||||
|
fprintf(stderr, "qname_max_len: %lu\n", qname_max_len);
|
||||||
|
else
|
||||||
|
qname_max_len = strlen(t->qname) + 1;
|
||||||
|
|
||||||
|
fprintf(stderr, "qname: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), t->qname, -1));
|
||||||
|
fprintf(stderr, "exp: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), t->domain, -1));
|
||||||
|
res = osmo_mdns_rfc_qname_decode(ctx, t->qname, qname_max_len);
|
||||||
|
fprintf(stderr, "res: %s\n", osmo_quote_str_buf2(quote_buf, sizeof(quote_buf), res, -1));
|
||||||
|
if (t->domain == res || (t->domain && res && strcmp(t->domain, res) == 0))
|
||||||
|
fprintf(stderr, "=> OK\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "=> ERROR\n");
|
||||||
|
if (res)
|
||||||
|
talloc_free(res);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define PRINT_HDR(hdr, name) \
|
#define PRINT_HDR(hdr, name) \
|
||||||
fprintf(stderr, "header %s:\n" \
|
fprintf(stderr, "header %s:\n" \
|
||||||
".id = %i\n" \
|
".id = %i\n" \
|
||||||
@@ -74,7 +216,7 @@ static const struct osmo_mdns_rfc_header header_enc_dec_test_data[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
void test_enc_dec_rfc_header(void)
|
void test_enc_dec_rfc_header()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -99,7 +241,7 @@ void test_enc_dec_rfc_header(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_enc_dec_rfc_header_einval(void)
|
void test_enc_dec_rfc_header_einval()
|
||||||
{
|
{
|
||||||
struct osmo_mdns_rfc_header out = {0};
|
struct osmo_mdns_rfc_header out = {0};
|
||||||
struct msgb *msg = msgb_alloc(4096, "dns_test");
|
struct msgb *msg = msgb_alloc(4096, "dns_test");
|
||||||
@@ -147,7 +289,7 @@ void test_enc_dec_rfc_question(void *ctx)
|
|||||||
struct msgb *msg = msgb_alloc(4096, "dns_test");
|
struct msgb *msg = msgb_alloc(4096, "dns_test");
|
||||||
|
|
||||||
PRINT_QST(&in, "in");
|
PRINT_QST(&in, "in");
|
||||||
assert(osmo_mdns_rfc_question_encode(msg, &in) == 0);
|
assert(osmo_mdns_rfc_question_encode(ctx, msg, &in) == 0);
|
||||||
fprintf(stderr, "encoded: %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg)));
|
fprintf(stderr, "encoded: %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg)));
|
||||||
out = osmo_mdns_rfc_question_decode(ctx, msgb_data(msg), msgb_length(msg));
|
out = osmo_mdns_rfc_question_decode(ctx, msgb_data(msg), msgb_length(msg));
|
||||||
assert(out);
|
assert(out);
|
||||||
@@ -211,7 +353,7 @@ void test_enc_dec_rfc_record(void *ctx)
|
|||||||
size_t record_len;
|
size_t record_len;
|
||||||
|
|
||||||
PRINT_REC(&in, "in");
|
PRINT_REC(&in, "in");
|
||||||
assert(osmo_mdns_rfc_record_encode(msg, &in) == 0);
|
assert(osmo_mdns_rfc_record_encode(ctx, msg, &in) == 0);
|
||||||
fprintf(stderr, "encoded: %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg)));
|
fprintf(stderr, "encoded: %s\n", osmo_hexdump(msgb_data(msg), msgb_length(msg)));
|
||||||
out = osmo_mdns_rfc_record_decode(ctx, msgb_data(msg), msgb_length(msg), &record_len);
|
out = osmo_mdns_rfc_record_decode(ctx, msgb_data(msg), msgb_length(msg), &record_len);
|
||||||
fprintf(stderr, "record_len: %lu\n", record_len);
|
fprintf(stderr, "record_len: %lu\n", record_len);
|
||||||
@@ -436,17 +578,18 @@ static void test_result_from_answer(void *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main()
|
||||||
{
|
{
|
||||||
void *ctx = talloc_named_const(NULL, 0, "main");
|
void *ctx = talloc_named_const(NULL, 0, "main");
|
||||||
osmo_init_logging2(ctx, NULL);
|
osmo_init_logging2(ctx, NULL);
|
||||||
|
|
||||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
log_set_print_filename(osmo_stderr_target, 0);
|
||||||
log_set_print_level(osmo_stderr_target, 1);
|
log_set_print_level(osmo_stderr_target, 1);
|
||||||
log_set_print_category(osmo_stderr_target, 1);
|
log_set_print_category(osmo_stderr_target, 1);
|
||||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
log_set_print_category_hex(osmo_stderr_target, 0);
|
||||||
log_set_use_color(osmo_stderr_target, 0);
|
log_set_use_color(osmo_stderr_target, 0);
|
||||||
|
|
||||||
|
test_enc_dec_rfc_qname(ctx);
|
||||||
test_enc_dec_rfc_header();
|
test_enc_dec_rfc_header();
|
||||||
test_enc_dec_rfc_header_einval();
|
test_enc_dec_rfc_header_einval();
|
||||||
test_enc_dec_rfc_question(ctx);
|
test_enc_dec_rfc_question(ctx);
|
||||||
|
|||||||
@@ -1,3 +1,85 @@
|
|||||||
|
-- test_enc_dec_rfc_qname --
|
||||||
|
domain: "hlr.1234567.imsi"
|
||||||
|
exp: "\3hlr\a1234567\4imsi"
|
||||||
|
res: "\3hlr\a1234567\4imsi"
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
qname: "\3hlr\a1234567\4imsi"
|
||||||
|
exp: "hlr.1234567.imsi"
|
||||||
|
res: "hlr.1234567.imsi"
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
domain: "hlr..imsi"
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
domain: "hlr"
|
||||||
|
exp: "\3hlr"
|
||||||
|
res: "\3hlr"
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
qname: "\3hlr"
|
||||||
|
exp: "hlr"
|
||||||
|
res: "hlr"
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
domain: "hlr."
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
domain: ".hlr"
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
domain: ""
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
domain: "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.12345"
|
||||||
|
exp: "\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\512345"
|
||||||
|
res: "\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\512345"
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
qname: "\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\512345"
|
||||||
|
exp: "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.12345"
|
||||||
|
res: "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.12345"
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
domain: "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.12345toolong"
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
qname: "\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\t123456789\
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
qname: "\3hlr\a1234567\5imsi"
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
qname: "\2hlr\a1234567\4imsi"
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
qname: "\3hlr\3"
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
|
qname_max_len: 17
|
||||||
|
qname: "\3hlr\a1234567\4imsi"
|
||||||
|
exp: NULL
|
||||||
|
res: NULL
|
||||||
|
=> OK
|
||||||
|
|
||||||
-- test_enc_dec_rfc_header --
|
-- test_enc_dec_rfc_header --
|
||||||
header in:
|
header in:
|
||||||
.id = 1337
|
.id = 1337
|
||||||
|
|||||||
@@ -80,14 +80,14 @@ static int server_recv(struct osmo_fd *osmo_fd, unsigned int what)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void server_init(void)
|
static void server_init()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n", __func__);
|
fprintf(stderr, "%s\n", __func__);
|
||||||
server_mc = osmo_mdns_sock_init(ctx, TEST_IP, TEST_PORT, server_recv, NULL, 0);
|
server_mc = osmo_mdns_sock_init(ctx, TEST_IP, TEST_PORT, server_recv, NULL, 0);
|
||||||
OSMO_ASSERT(server_mc);
|
OSMO_ASSERT(server_mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void server_stop(void)
|
static void server_stop()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n", __func__);
|
fprintf(stderr, "%s\n", __func__);
|
||||||
OSMO_ASSERT(server_mc);
|
OSMO_ASSERT(server_mc);
|
||||||
@@ -98,7 +98,7 @@ static void server_stop(void)
|
|||||||
struct osmo_mslookup_client* client;
|
struct osmo_mslookup_client* client;
|
||||||
struct osmo_mslookup_client_method* client_method;
|
struct osmo_mslookup_client_method* client_method;
|
||||||
|
|
||||||
static void client_init(void)
|
static void client_init()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n", __func__);
|
fprintf(stderr, "%s\n", __func__);
|
||||||
client = osmo_mslookup_client_new(ctx);
|
client = osmo_mslookup_client_new(ctx);
|
||||||
@@ -117,7 +117,7 @@ static void client_recv(struct osmo_mslookup_client *client, uint32_t request_ha
|
|||||||
osmo_mslookup_client_request_cancel(client, request_handle);
|
osmo_mslookup_client_request_cancel(client, request_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void client_query(void)
|
static void client_query()
|
||||||
{
|
{
|
||||||
struct osmo_mslookup_id id = {.type = OSMO_MSLOOKUP_ID_IMSI,
|
struct osmo_mslookup_id id = {.type = OSMO_MSLOOKUP_ID_IMSI,
|
||||||
.imsi = "123456789012345"};
|
.imsi = "123456789012345"};
|
||||||
@@ -134,7 +134,7 @@ static void client_query(void)
|
|||||||
osmo_mslookup_client_request(client, &query, &handling);
|
osmo_mslookup_client_request(client, &query, &handling);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void client_stop(void)
|
static void client_stop()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n", __func__);
|
fprintf(stderr, "%s\n", __func__);
|
||||||
osmo_mslookup_client_free(client);
|
osmo_mslookup_client_free(client);
|
||||||
@@ -154,7 +154,7 @@ const struct timeval fake_time_start_time = { 0, 0 };
|
|||||||
osmo_timers_update(); \
|
osmo_timers_update(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void fake_time_start(void)
|
static void fake_time_start()
|
||||||
{
|
{
|
||||||
struct timespec *clock_override;
|
struct timespec *clock_override;
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ static void fake_time_start(void)
|
|||||||
osmo_clock_override_enable(CLOCK_MONOTONIC, true);
|
osmo_clock_override_enable(CLOCK_MONOTONIC, true);
|
||||||
fake_time_passes(0, 0);
|
fake_time_passes(0, 0);
|
||||||
}
|
}
|
||||||
static void test_server_client(void)
|
static void test_server_client()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "-- %s --\n", __func__);
|
fprintf(stderr, "-- %s --\n", __func__);
|
||||||
server_init();
|
server_init();
|
||||||
@@ -190,7 +190,7 @@ static void test_server_client(void)
|
|||||||
client_stop();
|
client_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_multicast_enabled(void)
|
bool is_multicast_enabled()
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
struct addrinfo *ai;
|
struct addrinfo *ai;
|
||||||
@@ -222,7 +222,7 @@ bool is_multicast_enabled(void)
|
|||||||
/*
|
/*
|
||||||
* Run all tests
|
* Run all tests
|
||||||
*/
|
*/
|
||||||
int main(int argc, char **argv)
|
int main()
|
||||||
{
|
{
|
||||||
if (!is_multicast_enabled()) {
|
if (!is_multicast_enabled()) {
|
||||||
fprintf(stderr, "ERROR: multicast is disabled! (OS#4361)");
|
fprintf(stderr, "ERROR: multicast is disabled! (OS#4361)");
|
||||||
@@ -233,7 +233,7 @@ int main(int argc, char **argv)
|
|||||||
ctx = talloc_named_const(NULL, 0, "main");
|
ctx = talloc_named_const(NULL, 0, "main");
|
||||||
osmo_init_logging2(ctx, NULL);
|
osmo_init_logging2(ctx, NULL);
|
||||||
|
|
||||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
log_set_print_filename(osmo_stderr_target, 0);
|
||||||
log_set_print_level(osmo_stderr_target, 0);
|
log_set_print_level(osmo_stderr_target, 0);
|
||||||
log_set_print_category(osmo_stderr_target, 0);
|
log_set_print_category(osmo_stderr_target, 0);
|
||||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
log_set_print_category_hex(osmo_stderr_target, 0);
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ const struct timeval fake_time_start_time = { 0, 0 };
|
|||||||
osmo_timers_update(); \
|
osmo_timers_update(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static void fake_time_start(void)
|
static void fake_time_start()
|
||||||
{
|
{
|
||||||
struct timespec *clock_override;
|
struct timespec *clock_override;
|
||||||
|
|
||||||
@@ -169,12 +169,12 @@ static void result_cb_once(struct osmo_mslookup_client *client,
|
|||||||
LOGP(DMSLOOKUP, LOGL_DEBUG, "result_cb(): %s\n", osmo_mslookup_result_name_c(ctx, query, result));
|
LOGP(DMSLOOKUP, LOGL_DEBUG, "result_cb(): %s\n", osmo_mslookup_result_name_c(ctx, query, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main()
|
||||||
{
|
{
|
||||||
ctx = talloc_named_const(NULL, 0, "main");
|
ctx = talloc_named_const(NULL, 0, "main");
|
||||||
osmo_init_logging2(ctx, NULL);
|
osmo_init_logging2(ctx, NULL);
|
||||||
|
|
||||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
log_set_print_filename(osmo_stderr_target, 0);
|
||||||
log_set_print_level(osmo_stderr_target, 0);
|
log_set_print_level(osmo_stderr_target, 0);
|
||||||
log_set_print_category(osmo_stderr_target, 0);
|
log_set_print_category(osmo_stderr_target, 0);
|
||||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
log_set_print_category_hex(osmo_stderr_target, 0);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const char *domains[] = {
|
|||||||
"qwerty.1.qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmm",
|
"qwerty.1.qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnmm",
|
||||||
};
|
};
|
||||||
|
|
||||||
void test_osmo_mslookup_query_init_from_domain_str(void)
|
void test_osmo_mslookup_query_init_from_domain_str()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < ARRAY_SIZE(domains); i++) {
|
for (i = 0; i < ARRAY_SIZE(domains); i++) {
|
||||||
@@ -68,12 +68,12 @@ void test_osmo_mslookup_query_init_from_domain_str(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main()
|
||||||
{
|
{
|
||||||
ctx = talloc_named_const(NULL, 0, "main");
|
ctx = talloc_named_const(NULL, 0, "main");
|
||||||
osmo_init_logging2(ctx, NULL);
|
osmo_init_logging2(ctx, NULL);
|
||||||
|
|
||||||
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
|
log_set_print_filename(osmo_stderr_target, 0);
|
||||||
log_set_print_level(osmo_stderr_target, 0);
|
log_set_print_level(osmo_stderr_target, 0);
|
||||||
log_set_print_category(osmo_stderr_target, 0);
|
log_set_print_category(osmo_stderr_target, 0);
|
||||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
log_set_print_category_hex(osmo_stderr_target, 0);
|
||||||
|
|||||||
@@ -13,10 +13,6 @@ OsmoHLR> ?
|
|||||||
OsmoHLR> list
|
OsmoHLR> list
|
||||||
...
|
...
|
||||||
show gsup-connections
|
show gsup-connections
|
||||||
show subscribers all
|
|
||||||
show subscribers (imei|imsi|msisdn) FILTER
|
|
||||||
show subscribers (cs|ps) (on|off)
|
|
||||||
show subscribers last-seen
|
|
||||||
subscriber (imsi|msisdn|id|imei) IDENT show
|
subscriber (imsi|msisdn|id|imei) IDENT show
|
||||||
show subscriber (imsi|msisdn|id|imei) IDENT
|
show subscriber (imsi|msisdn|id|imei) IDENT
|
||||||
show mslookup services
|
show mslookup services
|
||||||
@@ -47,23 +43,20 @@ 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
|
||||||
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
|
||||||
ussd route prefix PREFIX internal (own-msisdn|own-imsi|test-idle)
|
ussd route prefix PREFIX internal (own-msisdn|own-imsi)
|
||||||
ussd route prefix PREFIX external EUSE
|
ussd route prefix PREFIX external EUSE
|
||||||
no ussd route prefix PREFIX
|
no ussd route prefix PREFIX
|
||||||
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>
|
||||||
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|<3-15>) (none|cs|ps|cs+ps)
|
subscriber-create-on-demand (no-msisdn|<3-15>) (none|cs|ps|cs+ps)
|
||||||
@@ -110,15 +103,8 @@ hlr
|
|||||||
database hlr_vty_test.db
|
database hlr_vty_test.db
|
||||||
gsup
|
gsup
|
||||||
bind ip 127.0.0.1
|
bind ip 127.0.0.1
|
||||||
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
|
||||||
@@ -355,18 +341,18 @@ OsmoHLR(config-mslookup-server-msc)# show running-config
|
|||||||
mslookup
|
mslookup
|
||||||
server
|
server
|
||||||
mdns bind 239.192.23.42 4266
|
mdns bind 239.192.23.42 4266
|
||||||
service foo.bar at 123.45.67.89 1011
|
service foo.bar at 123.45.67.89 1011
|
||||||
service baz.bar at 121.31.41.5 1617
|
service baz.bar at 121.31.41.5 1617
|
||||||
service baz.bar at a:b:c::d 1819
|
service baz.bar at a:b:c::d 1819
|
||||||
msc ipa-name MSC-1
|
msc MSC-1
|
||||||
msc ipa-name msc-901-70-23
|
msc msc-901-70-23
|
||||||
service foo.bar at 76.54.32.10 1234
|
service foo.bar at 76.54.32.10 1234
|
||||||
service baz.bar at 12.11.10.98 7654
|
service baz.bar at 12.11.10.98 7654
|
||||||
service baz.bar at dd:cc:bb::a 3210
|
service baz.bar at dd:cc:bb::a 3210
|
||||||
msc ipa-name msc-901-70-42
|
msc msc-901-70-42
|
||||||
service foo.bar at 1.1.1.1 1111
|
service foo.bar at 1.1.1.1 1111
|
||||||
service baz.bar at 2.2.2.2 2222
|
service baz.bar at 2.2.2.2 2222
|
||||||
service baz.bar at 2222:2222:2222::2 2222
|
service baz.bar at 2222:2222:2222::2 2222
|
||||||
client
|
client
|
||||||
gateway-proxy 1.2.3.4 4222
|
gateway-proxy 1.2.3.4 4222
|
||||||
mdns bind 239.192.23.42 4266
|
mdns bind 239.192.23.42 4266
|
||||||
@@ -411,14 +397,14 @@ OsmoHLR(config-mslookup-client)# show running-config
|
|||||||
mslookup
|
mslookup
|
||||||
server
|
server
|
||||||
mdns bind 239.192.23.42 4266
|
mdns bind 239.192.23.42 4266
|
||||||
service foo.bar at 123.45.67.89 1011
|
service foo.bar at 123.45.67.89 1011
|
||||||
service baz.bar at 121.31.41.5 1617
|
service baz.bar at 121.31.41.5 1617
|
||||||
msc ipa-name MSC-1
|
msc MSC-1
|
||||||
msc ipa-name msc-901-70-23
|
msc msc-901-70-23
|
||||||
service foo.bar at 76.54.32.10 1234
|
service foo.bar at 76.54.32.10 1234
|
||||||
service baz.bar at 12.11.10.98 7654
|
service baz.bar at 12.11.10.98 7654
|
||||||
msc ipa-name msc-901-70-42
|
msc msc-901-70-42
|
||||||
service foo.bar at 1.1.1.1 1111
|
service foo.bar at 1.1.1.1 1111
|
||||||
client
|
client
|
||||||
mdns bind 239.192.23.42 4266
|
mdns bind 239.192.23.42 4266
|
||||||
...
|
...
|
||||||
@@ -443,56 +429,15 @@ OsmoHLR(config-mslookup-server)# show running-config
|
|||||||
mslookup
|
mslookup
|
||||||
server
|
server
|
||||||
mdns bind 239.192.23.42 4266
|
mdns bind 239.192.23.42 4266
|
||||||
service foo.bar at 123.45.67.89 1011
|
service foo.bar at 123.45.67.89 1011
|
||||||
service baz.bar at 121.31.41.5 1617
|
service baz.bar at 121.31.41.5 1617
|
||||||
service gsup.hlr at 23.42.17.11 4223
|
service gsup.hlr at 23.42.17.11 4223
|
||||||
msc ipa-name MSC-1
|
msc MSC-1
|
||||||
msc ipa-name msc-901-70-23
|
msc msc-901-70-23
|
||||||
service foo.bar at 76.54.32.10 1234
|
service foo.bar at 76.54.32.10 1234
|
||||||
service baz.bar at 12.11.10.98 7654
|
service baz.bar at 12.11.10.98 7654
|
||||||
msc ipa-name msc-901-70-42
|
msc msc-901-70-42
|
||||||
service foo.bar at 1.1.1.1 1111
|
service foo.bar at 1.1.1.1 1111
|
||||||
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 *
|
|
||||||
...
|
|
||||||
|
|||||||
@@ -610,102 +610,5 @@ periodic_lu_timer 0
|
|||||||
periodic_rau_tau_timer 0
|
periodic_rau_tau_timer 0
|
||||||
lmsi 00000000
|
lmsi 00000000
|
||||||
|
|
||||||
SET 101 subscriber.create 901991234567891
|
GET 101 subscriber.by-id-0x0123.info
|
||||||
SET_REPLY 101 subscriber.create 124
|
ERROR 101 Invalid value part of 'by-xxx-value' selector.
|
||||||
|
|
||||||
GET 102 subscriber.by-id-124.info
|
|
||||||
GET_REPLY 102 subscriber.by-id-124.info
|
|
||||||
id 124
|
|
||||||
imsi 901991234567891
|
|
||||||
nam_cs 1
|
|
||||||
nam_ps 1
|
|
||||||
ms_purged_cs 0
|
|
||||||
ms_purged_ps 0
|
|
||||||
periodic_lu_timer 0
|
|
||||||
periodic_rau_tau_timer 0
|
|
||||||
lmsi 00000000
|
|
||||||
|
|
||||||
GET 103 subscriber.by-imsi-901991234567891.msisdn
|
|
||||||
GET_REPLY 103 subscriber.by-imsi-901991234567891.msisdn none
|
|
||||||
|
|
||||||
SET 104 subscriber.by-imsi-901991234567891.msisdn 555666
|
|
||||||
SET_REPLY 104 subscriber.by-imsi-901991234567891.msisdn OK
|
|
||||||
|
|
||||||
GET 105 subscriber.by-imsi-901991234567891.msisdn
|
|
||||||
GET_REPLY 105 subscriber.by-imsi-901991234567891.msisdn 555666
|
|
||||||
|
|
||||||
SET 106 subscriber.by-imsi-901991234567891.msisdn 888000
|
|
||||||
SET_REPLY 106 subscriber.by-imsi-901991234567891.msisdn OK
|
|
||||||
|
|
||||||
GET 107 subscriber.by-imsi-901991234567891.msisdn
|
|
||||||
GET_REPLY 107 subscriber.by-imsi-901991234567891.msisdn 888000
|
|
||||||
|
|
||||||
GET 108 subscriber.by-imsi-901991234567891.info
|
|
||||||
GET_REPLY 108 subscriber.by-imsi-901991234567891.info
|
|
||||||
id 124
|
|
||||||
imsi 901991234567891
|
|
||||||
msisdn 888000
|
|
||||||
nam_cs 1
|
|
||||||
nam_ps 1
|
|
||||||
ms_purged_cs 0
|
|
||||||
ms_purged_ps 0
|
|
||||||
periodic_lu_timer 0
|
|
||||||
periodic_rau_tau_timer 0
|
|
||||||
lmsi 00000000
|
|
||||||
|
|
||||||
SET 109 subscriber.by-imsi-901991234567891.msisdn none
|
|
||||||
SET_REPLY 109 subscriber.by-imsi-901991234567891.msisdn OK
|
|
||||||
|
|
||||||
GET 110 subscriber.by-imsi-901991234567891.msisdn
|
|
||||||
GET_REPLY 110 subscriber.by-imsi-901991234567891.msisdn none
|
|
||||||
|
|
||||||
GET 111 subscriber.by-imsi-901991234567891.info
|
|
||||||
GET_REPLY 111 subscriber.by-imsi-901991234567891.info
|
|
||||||
id 124
|
|
||||||
imsi 901991234567891
|
|
||||||
nam_cs 1
|
|
||||||
nam_ps 1
|
|
||||||
ms_purged_cs 0
|
|
||||||
ms_purged_ps 0
|
|
||||||
periodic_lu_timer 0
|
|
||||||
periodic_rau_tau_timer 0
|
|
||||||
lmsi 00000000
|
|
||||||
|
|
||||||
GET 112 subscriber.by-imsi-901991234567891.aud2g
|
|
||||||
GET_REPLY 112 subscriber.by-imsi-901991234567891.aud2g none
|
|
||||||
|
|
||||||
SET 113 subscriber.by-imsi-901991234567891.aud2g xor-2g,c01ffedc1cadaeac1d1f1edacac1ab0a
|
|
||||||
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_REPLY 115 subscriber.by-imsi-901991234567891.aud2g OK
|
|
||||||
|
|
||||||
GET 116 subscriber.by-imsi-901991234567891.aud2g
|
|
||||||
GET_REPLY 116 subscriber.by-imsi-901991234567891.aud2g none
|
|
||||||
|
|
||||||
GET 117 subscriber.by-imsi-901991234567891.aud3g
|
|
||||||
GET_REPLY 117 subscriber.by-imsi-901991234567891.aud3g none
|
|
||||||
|
|
||||||
SET 118 subscriber.by-imsi-901991234567891.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OP,FB2A3D1B360F599ABAB99DB8669F8308
|
|
||||||
SET_REPLY 118 subscriber.by-imsi-901991234567891.aud3g OK
|
|
||||||
|
|
||||||
GET 119 subscriber.by-imsi-901991234567891.aud3g
|
|
||||||
GET_REPLY 119 subscriber.by-imsi-901991234567891.aud3g MILENAGE,c01ffedc1cadaeac1d1f1edacac1ab0a,OP,fb2a3d1b360f599abab99db8669f8308,5
|
|
||||||
|
|
||||||
SET 120 subscriber.by-imsi-901991234567891.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,FB2A3D1B360F599ABAB99DB8669F8308,7
|
|
||||||
SET_REPLY 120 subscriber.by-imsi-901991234567891.aud3g OK
|
|
||||||
|
|
||||||
GET 121 subscriber.by-imsi-901991234567891.aud3g
|
|
||||||
GET_REPLY 121 subscriber.by-imsi-901991234567891.aud3g MILENAGE,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,7
|
|
||||||
|
|
||||||
SET 122 subscriber.by-imsi-901991234567891.aud3g none
|
|
||||||
SET_REPLY 122 subscriber.by-imsi-901991234567891.aud3g OK
|
|
||||||
|
|
||||||
GET 123 subscriber.by-imsi-901991234567891.aud3g
|
|
||||||
GET_REPLY 123 subscriber.by-imsi-901991234567891.aud3g none
|
|
||||||
|
|
||||||
SET 124 subscriber.delete 901991234567891
|
|
||||||
SET_REPLY 124 subscriber.delete 124
|
|
||||||
|
|||||||
@@ -8,10 +8,9 @@ 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 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 +143,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 +154,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
|
2G auth: XOR
|
||||||
KI=deaf0ff1ced0d0dabbedd1ced1cef00d
|
KI=deaf0ff1ced0d0dabbedd1ced1cef00d
|
||||||
|
|
||||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki BeefedCafeFaceAcedAddedDecadeFee
|
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki BeefedCafeFaceAcedAddedDecadeFee
|
||||||
@@ -241,7 +240,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 +249,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 +268,19 @@ 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-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
|
||||||
|
|||||||
@@ -105,51 +105,3 @@ GET 46 subscriber.by-imsi-1234567890123456.ps-enabled
|
|||||||
ERROR 46 Invalid value part of 'by-xxx-value' selector.
|
ERROR 46 Invalid value part of 'by-xxx-value' selector.
|
||||||
GET 47 subscriber.by-imsi-1234567890123456.cs-enabled
|
GET 47 subscriber.by-imsi-1234567890123456.cs-enabled
|
||||||
ERROR 47 Invalid value part of 'by-xxx-value' selector.
|
ERROR 47 Invalid value part of 'by-xxx-value' selector.
|
||||||
|
|
||||||
GET 48 subscriber.by-id-0x0123.info
|
|
||||||
ERROR 48 Invalid value part of 'by-xxx-value' selector.
|
|
||||||
|
|
||||||
SET 49 subscriber.create zzz
|
|
||||||
ERROR 49 Invalid IMSI value.
|
|
||||||
|
|
||||||
SET 50 subscriber.create 901990000000001
|
|
||||||
ERROR 50 Subscriber already exists.
|
|
||||||
|
|
||||||
SET 51 subscriber.by-imsi-1234567890123456.msisdn hellobadmsisdn
|
|
||||||
ERROR 51 Value failed verification.
|
|
||||||
|
|
||||||
SET 52 subscriber.delete 100000
|
|
||||||
ERROR 52 Subscriber doesn't exist.
|
|
||||||
|
|
||||||
SET 53 subscriber.delete zzz
|
|
||||||
ERROR 53 Invalid IMSI value.
|
|
||||||
|
|
||||||
SET 54 subscriber.by-imsi-901990000000003.aud2g foobar
|
|
||||||
ERROR 54 Value failed verification.
|
|
||||||
|
|
||||||
SET 55 subscriber.by-imsi-901990000000003.aud2g foobar,2134
|
|
||||||
ERROR 55 Unknown auth algorithm.
|
|
||||||
|
|
||||||
SET 56 subscriber.by-imsi-901990000000003.aud2g xor-2g,2134
|
|
||||||
ERROR 56 Invalid KI.
|
|
||||||
|
|
||||||
SET 57 subscriber.by-imsi-901990000000003.aud3g foobar
|
|
||||||
ERROR 57 Value failed verification.
|
|
||||||
|
|
||||||
SET 58 subscriber.by-imsi-901990000000003.aud3g foobar,2134
|
|
||||||
ERROR 58 Unknown auth algorithm.
|
|
||||||
|
|
||||||
SET 59 subscriber.by-imsi-901990000000003.aud3g milenage,2134
|
|
||||||
ERROR 59 Invalid KI.
|
|
||||||
|
|
||||||
SET 60 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.
|
|
||||||
|
|
||||||
SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,zzz
|
|
||||||
ERROR 62 Invalid OP/OPC.
|
|
||||||
|
|
||||||
SET 63 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,
|
|
||||||
ERROR 63 Invalid format.
|
|
||||||
|
|||||||
@@ -22,6 +22,13 @@ cat $abs_srcdir/gsup/gsup_test.err > experr
|
|||||||
AT_CHECK([$abs_top_builddir/tests/gsup/gsup_test], [], [expout], [experr])
|
AT_CHECK([$abs_top_builddir/tests/gsup/gsup_test], [], [expout], [experr])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
|
AT_SETUP([gsup_server])
|
||||||
|
AT_KEYWORDS([gsup_server])
|
||||||
|
cat $abs_srcdir/gsup_server/gsup_server_test.ok > expout
|
||||||
|
cat $abs_srcdir/gsup_server/gsup_server_test.err > experr
|
||||||
|
AT_CHECK([$abs_top_builddir/tests/gsup_server/gsup_server_test], [], [expout], [experr])
|
||||||
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([db])
|
AT_SETUP([db])
|
||||||
AT_KEYWORDS([db])
|
AT_KEYWORDS([db])
|
||||||
cat $abs_srcdir/db/db_test.ok > expout
|
cat $abs_srcdir/db/db_test.ok > expout
|
||||||
|
|||||||
Reference in New Issue
Block a user