mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr.git
				synced 2025-11-03 21:53:30 +00:00 
			
		
		
		
	Compare commits
	
		
			29 Commits
		
	
	
		
			neels/for_
			...
			1.4.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					4d7cbfcc9a | ||
| 
						 | 
					bfeea69cab | ||
| 
						 | 
					3f9d1977df | ||
| 
						 | 
					608e2e483f | ||
| 
						 | 
					60673e7f77 | ||
| 
						 | 
					ca8e6efca6 | ||
| 
						 | 
					ed2e36316b | ||
| 
						 | 
					649c335602 | ||
| 
						 | 
					6240465503 | ||
| 
						 | 
					8c9087dd16 | ||
| 
						 | 
					2bd1a45553 | ||
| 
						 | 
					d6993ea4b5 | ||
| 
						 | 
					f551ccf9fb | ||
| 
						 | 
					b5a5676cff | ||
| 
						 | 
					89fda3024a | ||
| 
						 | 
					dd746949d0 | ||
| 
						 | 
					cc90bfd0f4 | ||
| 
						 | 
					f4d64cb98b | ||
| 
						 | 
					bd94b41fa8 | ||
| 
						 | 
					6e237d3a90 | ||
| 
						 | 
					dac855e5c8 | ||
| 
						 | 
					6a6c7f87ca | ||
| 
						 | 
					6cfef3ac26 | ||
| 
						 | 
					66f0b5fbea | ||
| 
						 | 
					c47d5c0d77 | ||
| 
						 | 
					dfbc2cbbc2 | ||
| 
						 | 
					89649ea997 | ||
| 
						 | 
					23ac586522 | ||
| 
						 | 
					de50b20116 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -26,6 +26,7 @@ m4
 | 
				
			|||||||
*.m4
 | 
					*.m4
 | 
				
			||||||
missing
 | 
					missing
 | 
				
			||||||
.deps
 | 
					.deps
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
*.pc
 | 
					*.pc
 | 
				
			||||||
.libs
 | 
					.libs
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										66
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					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 git://git.osmocom.org/osmo-hlr.git
 | 
				
			||||||
 | 
						git clone https://git.osmocom.org/osmo-hlr.git
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There is a cgit interface at https://git.osmocom.org/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,4 +7,3 @@
 | 
				
			|||||||
# 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
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								configure.ac
									
									
									
									
									
								
							@@ -12,6 +12,8 @@ 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])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,11 +41,11 @@ PKG_PROG_PKG_CONFIG([0.20])
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
PKG_CHECK_MODULES(TALLOC, [talloc >= 2.0.1])
 | 
					PKG_CHECK_MODULES(TALLOC, [talloc >= 2.0.1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.4.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.5.0)
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.4.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.5.0)
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.4.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.5.0)
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.4.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.5.0)
 | 
				
			||||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
 | 
					PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PKG_CHECK_MODULES(SQLITE3, sqlite3)
 | 
					PKG_CHECK_MODULES(SQLITE3, sqlite3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -204,7 +206,6 @@ 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,3 +2,13 @@ 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,7 +35,6 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,11 +56,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 distcheck || cat-testlogs.sh
 | 
					DISTCHECK_CONFIGURE_FLAGS="$CONFIG" $MAKE $PARALLEL_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 maintainer-clean
 | 
					$MAKE $PARALLEL_MAKE maintainer-clean
 | 
				
			||||||
osmo-clean-workspace.sh
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										95
									
								
								contrib/osmo-hlr-post-upgrade.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								contrib/osmo-hlr-post-upgrade.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					#!/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) >= 0.6.0
 | 
					BuildRequires:  pkgconfig(libosmoabis) >= 1.1.0
 | 
				
			||||||
BuildRequires:  pkgconfig(libosmocore) >= 1.2.0
 | 
					BuildRequires:  pkgconfig(libosmocore) >= 1.5.0
 | 
				
			||||||
BuildRequires:  pkgconfig(libosmoctrl) >= 1.2.0
 | 
					BuildRequires:  pkgconfig(libosmoctrl) >= 1.5.0
 | 
				
			||||||
BuildRequires:  pkgconfig(libosmogsm) >= 1.2.0
 | 
					BuildRequires:  pkgconfig(libosmogsm) >= 1.5.0
 | 
				
			||||||
BuildRequires:  pkgconfig(libosmovty) >= 1.2.0
 | 
					BuildRequires:  pkgconfig(libosmovty) >= 1.5.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
 | 
				
			||||||
@@ -136,10 +136,13 @@ 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
 | 
				
			||||||
@@ -162,6 +165,8 @@ 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*
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										121
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										121
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,124 @@
 | 
				
			|||||||
 | 
					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 ]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@@ -5,15 +5,14 @@ Maintainer: Osmocom team <openbsc@lists.osmocom.org>
 | 
				
			|||||||
Build-Depends: debhelper (>= 9),
 | 
					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.4.0),
 | 
					               libosmocore-dev (>= 1.5.0),
 | 
				
			||||||
               libosmo-abis-dev,
 | 
					               libosmo-abis-dev (>= 1.1.0),
 | 
				
			||||||
               libosmo-netif-dev,
 | 
					               libosmo-netif-dev (>= 1.1.0),
 | 
				
			||||||
               libsqlite3-dev,
 | 
					               libsqlite3-dev,
 | 
				
			||||||
               sqlite3,
 | 
					               sqlite3,
 | 
				
			||||||
               osmo-gsm-manuals-dev
 | 
					               osmo-gsm-manuals-dev (>= 1.1.0)
 | 
				
			||||||
Standards-Version: 3.9.6
 | 
					Standards-Version: 3.9.6
 | 
				
			||||||
Vcs-Browser: http://cgit.osmocom.org/osmo-hlr
 | 
					Vcs-Browser: http://cgit.osmocom.org/osmo-hlr
 | 
				
			||||||
Vcs-Git: git://git.osmocom.org/osmo-hlr
 | 
					Vcs-Git: git://git.osmocom.org/osmo-hlr
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								debian/osmo-hlr.install
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-hlr.install
									
									
									
									
										vendored
									
									
								
							@@ -5,4 +5,5 @@
 | 
				
			|||||||
/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/osmocom/osmo-hlr-post-upgrade.sh
 | 
				
			||||||
/var/lib/osmocom
 | 
					/var/lib/osmocom
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								debian/postinst
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										5
									
								
								debian/postinst
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					#!/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
 | 
				
			||||||
@@ -14,6 +14,12 @@ 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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,15 +50,29 @@ 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.  There above command will restore
 | 
					to the named internal USSD handler.  The 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.  There is one other handler called
 | 
					the subscribers own phone number.  More information on internal USSD
 | 
				
			||||||
`own-imsi` which will return the IMSI instead of the MSISDN.
 | 
					handlers can be found in <<iuse_handlers>>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`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
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -4,10 +4,18 @@
 | 
				
			|||||||
#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,
 | 
				
			||||||
@@ -33,6 +41,9 @@ 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
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -148,6 +159,9 @@ 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,
 | 
				
			||||||
@@ -163,6 +177,9 @@ 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*.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,8 +42,6 @@ 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 */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								sql/hlr.sql
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								sql/hlr.sql
									
									
									
									
									
								
							@@ -79,8 +79,16 @@ CREATE TABLE auc_3g (
 | 
				
			|||||||
	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 = 5;
 | 
					PRAGMA user_version = 6;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								src/db.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/db.c
									
									
									
									
									
								
							@@ -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	5
 | 
					#define CURRENT_SCHEMA_VERSION	6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SEL_COLUMNS \
 | 
					#define SEL_COLUMNS \
 | 
				
			||||||
	"id," \
 | 
						"id," \
 | 
				
			||||||
@@ -51,6 +51,14 @@
 | 
				
			|||||||
	"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 = ?",
 | 
				
			||||||
@@ -85,6 +93,9 @@ 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)
 | 
				
			||||||
@@ -226,7 +237,7 @@ void db_close(struct db_context *dbc)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int db_run_statements(struct db_context *dbc, const char **statements, size_t statements_count)
 | 
					static int db_run_statements(struct db_context *dbc, const char **statements, size_t statements_count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int rc;
 | 
						int rc = 0;
 | 
				
			||||||
	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];
 | 
				
			||||||
@@ -479,6 +490,29 @@ 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 *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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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,
 | 
				
			||||||
@@ -486,6 +520,7 @@ 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,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int db_get_user_version(struct db_context *dbc)
 | 
					static int db_get_user_version(struct db_context *dbc)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										193
									
								
								src/db_hlr.c
									
									
									
									
									
								
							
							
						
						
									
										193
									
								
								src/db_hlr.c
									
									
									
									
									
								
							@@ -264,11 +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:
 | 
				
			||||||
			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:
 | 
					 | 
				
			||||||
			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));
 | 
				
			||||||
@@ -625,6 +625,94 @@ 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.
 | 
				
			||||||
@@ -884,3 +972,106 @@ 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,8 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#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>
 | 
				
			||||||
@@ -315,41 +317,17 @@ static int osmo_gsup_server_closed_cb(struct ipa_server_conn *conn)
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Add conn to the clients list in a way that conn->auc_3g_ind takes the lowest
 | 
					static void update_fd_settings(int fd)
 | 
				
			||||||
 * 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)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct osmo_gsup_conn *c;
 | 
						int ret;
 | 
				
			||||||
	struct osmo_gsup_conn *prev_conn;
 | 
						int val;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c = llist_first_entry_or_null(clients, struct osmo_gsup_conn, list);
 | 
						/*TODO: Set keepalive settings here. See OS#4312 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Is the first index, 0, unused? */
 | 
						val = 1;
 | 
				
			||||||
	if (!c || c->auc_3g_ind > 0) {
 | 
						ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
 | 
				
			||||||
		conn->auc_3g_ind = 0;
 | 
						if (ret < 0)
 | 
				
			||||||
		llist_add(&conn->list, clients);
 | 
							LOGP(DLGSUP, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
 | 
				
			||||||
		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 */
 | 
				
			||||||
@@ -371,10 +349,11 @@ 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;
 | 
				
			||||||
	osmo_gsup_server_add_conn(&gsups->clients, conn);
 | 
						llist_add_tail(&conn->list, &gsups->clients);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LOGP(DLGSUP, LOGL_INFO, "New GSUP client %s:%d (IND=%u)\n",
 | 
						LOGP(DLGSUP, LOGL_INFO, "New GSUP client %s:%d\n", conn->conn->addr, conn->conn->port);
 | 
				
			||||||
	     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);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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=0:0:0
 | 
					LIBVERSION=1:0:1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include \
 | 
					AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include \
 | 
				
			||||||
	    $(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOABIS_CFLAGS)
 | 
						    $(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOABIS_CFLAGS)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -129,6 +131,19 @@ 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;
 | 
				
			||||||
@@ -139,6 +154,7 @@ 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)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								src/hlr.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								src/hlr.c
									
									
									
									
									
								
							@@ -281,13 +281,14 @@ 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(unsigned int auc_3g_ind, struct osmo_gsup_req *req)
 | 
					static int rx_send_auth_info(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);
 | 
				
			||||||
@@ -298,6 +299,14 @@ static int rx_send_auth_info(unsigned int auc_3g_ind, 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,
 | 
				
			||||||
@@ -517,7 +526,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(conn->auc_3g_ind, req);
 | 
							rx_send_auth_info(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);
 | 
				
			||||||
@@ -577,6 +586,10 @@ static void print_help()
 | 
				
			|||||||
	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 {
 | 
				
			||||||
@@ -592,10 +605,37 @@ 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'},
 | 
				
			||||||
@@ -608,6 +648,8 @@ 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}
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -617,6 +659,9 @@ 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();
 | 
				
			||||||
@@ -730,10 +775,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);
 | 
				
			||||||
	handle_options(argc, argv);
 | 
					 | 
				
			||||||
	hlr_vty_init();
 | 
						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) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@
 | 
				
			|||||||
#include <getopt.h>
 | 
					#include <getopt.h>
 | 
				
			||||||
#include <inttypes.h>
 | 
					#include <inttypes.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/core/logging.h>
 | 
					#include <osmocom/core/logging.h>
 | 
				
			||||||
#include <osmocom/core/application.h>
 | 
					#include <osmocom/core/application.h>
 | 
				
			||||||
@@ -70,8 +71,9 @@ static void print_help()
 | 
				
			|||||||
	printf("                             (All commands imply this if none exists yet.)\n");
 | 
						printf("                             (All commands imply this if none exists yet.)\n");
 | 
				
			||||||
	printf("\n");
 | 
						printf("\n");
 | 
				
			||||||
	printf("  import-nitb-db <nitb.db>   Add OsmoNITB db's subscribers to OsmoHLR db.\n");
 | 
						printf("  import-nitb-db <nitb.db>   Add OsmoNITB db's subscribers to OsmoHLR db.\n");
 | 
				
			||||||
	printf("                             Be aware that the import is lossy, only the\n");
 | 
						printf("                             Be aware that the import is somewhat lossy, only the IMSI,\n");
 | 
				
			||||||
	printf("                             IMSI, MSISDN, nam_cs/ps and 2G auth data are set.\n");
 | 
						printf("                             MSISDN, IMEI, nam_cs/ps, 2G auth data and last seen LU are set.\n");
 | 
				
			||||||
 | 
						printf("                             The most recently associated IMEI from the Equipment table is used.\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void print_version(int print_copyright)
 | 
					static void print_version(int print_copyright)
 | 
				
			||||||
@@ -212,9 +214,15 @@ enum nitb_stmt {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const char *nitb_stmt_sql[] = {
 | 
					static const char *nitb_stmt_sql[] = {
 | 
				
			||||||
	[NITB_SELECT_SUBSCR] =
 | 
						[NITB_SELECT_SUBSCR] =
 | 
				
			||||||
		"SELECT imsi, id, extension, authorized"
 | 
							"SELECT s.imsi, s.id, s.extension, s.authorized,"
 | 
				
			||||||
		" FROM Subscriber"
 | 
							" SUBSTR(e.imei,0,15), STRFTIME('%s', s.expire_lu)"
 | 
				
			||||||
		" ORDER BY id",
 | 
							" FROM Subscriber s LEFT JOIN"
 | 
				
			||||||
 | 
							" (SELECT imei, subscriber_id, MAX(Equipment.updated) AS updated"
 | 
				
			||||||
 | 
							" FROM Equipment,EquipmentWatch"
 | 
				
			||||||
 | 
							" WHERE Equipment.id = EquipmentWatch.equipment_id"
 | 
				
			||||||
 | 
							" GROUP BY EquipmentWatch.subscriber_id) e"
 | 
				
			||||||
 | 
							" ON e.subscriber_id = s.id"
 | 
				
			||||||
 | 
							" ORDER by s.id",
 | 
				
			||||||
	[NITB_SELECT_AUTH_KEYS] =
 | 
						[NITB_SELECT_AUTH_KEYS] =
 | 
				
			||||||
		"SELECT algorithm_id, a3a8_ki from authkeys"
 | 
							"SELECT algorithm_id, a3a8_ki from authkeys"
 | 
				
			||||||
		" WHERE subscriber_id = $subscr_id",
 | 
							" WHERE subscriber_id = $subscr_id",
 | 
				
			||||||
@@ -222,8 +230,65 @@ static const char *nitb_stmt_sql[] = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
sqlite3_stmt *nitb_stmt[ARRAY_SIZE(nitb_stmt_sql)] = {};
 | 
					sqlite3_stmt *nitb_stmt[ARRAY_SIZE(nitb_stmt_sql)] = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum hlr_db_stmt {
 | 
				
			||||||
 | 
						HLR_DB_STMT_SET_IMPLICIT_LU_BY_IMSI,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *hlr_db_stmt_sql[] = {
 | 
				
			||||||
 | 
						[HLR_DB_STMT_SET_IMPLICIT_LU_BY_IMSI] =
 | 
				
			||||||
 | 
							"UPDATE subscriber SET last_lu_seen = datetime($last_lu, 'unixepoch') WHERE imsi = $imsi",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sqlite3_stmt *hlr_db_stmt[ARRAY_SIZE(hlr_db_stmt_sql)] = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t _dbd_decode_binary(const unsigned char *in, unsigned char *out);
 | 
					size_t _dbd_decode_binary(const unsigned char *in, unsigned char *out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Set a subscriber's LU timestamp in the HLR database.
 | 
				
			||||||
 | 
					 * In normal operations there is never any need to explicitly
 | 
				
			||||||
 | 
					 * update the value of last_lu_seen, so this function can live here.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \param[in,out] dbc  database context.
 | 
				
			||||||
 | 
					 * \param[in] imsi  ASCII string of IMSI digits
 | 
				
			||||||
 | 
					 * \param[in] imei  ASCII string of identifier digits, or NULL to remove the IMEI.
 | 
				
			||||||
 | 
					 * \returns 0 on success, -ENOENT when the given subscriber does not exist,
 | 
				
			||||||
 | 
					 *         -EIO on database errors.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int db_subscr_update_lu_by_imsi(struct db_context *dbc, const char* imsi, const int last_lu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc, ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sqlite3_stmt *stmt = hlr_db_stmt[HLR_DB_STMT_SET_IMPLICIT_LU_BY_IMSI];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!db_bind_text(stmt, "$imsi", imsi))
 | 
				
			||||||
 | 
							return -EIO;
 | 
				
			||||||
 | 
						if (last_lu && !db_bind_int(stmt, "$last_lu", last_lu))
 | 
				
			||||||
 | 
							return -EIO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* execute the statement */
 | 
				
			||||||
 | 
						rc = sqlite3_step(stmt);
 | 
				
			||||||
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
							LOGP(DAUC, LOGL_ERROR, "Update last_lu_seen for subscriber IMSI='%s': SQL Error: %s\n", imsi,
 | 
				
			||||||
 | 
							     sqlite3_errmsg(dbc->db));
 | 
				
			||||||
 | 
							ret = -EIO;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* verify execution result */
 | 
				
			||||||
 | 
						rc = sqlite3_changes(dbc->db);
 | 
				
			||||||
 | 
						if (!rc) {
 | 
				
			||||||
 | 
							LOGP(DAUC, LOGL_ERROR, "Cannot update last_lu_seen for subscriber IMSI='%s': no such subscriber\n", imsi);
 | 
				
			||||||
 | 
							ret = -ENOENT;
 | 
				
			||||||
 | 
						} else if (rc != 1) {
 | 
				
			||||||
 | 
							LOGP(DAUC, LOGL_ERROR, "Update last_lu_seen for subscriber IMSI='%s': SQL modified %d rows (expected 1)\n",
 | 
				
			||||||
 | 
							     imsi, rc);
 | 
				
			||||||
 | 
							ret = -EIO;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						db_remove_reset(stmt);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void import_nitb_subscr_aud(sqlite3 *nitb_db, const char *imsi, int64_t nitb_id, int64_t hlr_id)
 | 
					void import_nitb_subscr_aud(sqlite3 *nitb_db, const char *imsi, int64_t nitb_id, int64_t hlr_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
@@ -297,6 +362,7 @@ void import_nitb_subscr(sqlite3 *nitb_db, sqlite3_stmt *stmt)
 | 
				
			|||||||
	int64_t imsi;
 | 
						int64_t imsi;
 | 
				
			||||||
	char imsi_str[32];
 | 
						char imsi_str[32];
 | 
				
			||||||
	bool authorized;
 | 
						bool authorized;
 | 
				
			||||||
 | 
						int last_lu_int;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	imsi = sqlite3_column_int64(stmt, 0);
 | 
						imsi = sqlite3_column_int64(stmt, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -315,8 +381,18 @@ void import_nitb_subscr(sqlite3 *nitb_db, sqlite3_stmt *stmt)
 | 
				
			|||||||
	nitb_id = sqlite3_column_int64(stmt, 1);
 | 
						nitb_id = sqlite3_column_int64(stmt, 1);
 | 
				
			||||||
	copy_sqlite3_text_to_buf(subscr.msisdn, stmt, 2);
 | 
						copy_sqlite3_text_to_buf(subscr.msisdn, stmt, 2);
 | 
				
			||||||
	authorized = sqlite3_column_int(stmt, 3) ? true : false;
 | 
						authorized = sqlite3_column_int(stmt, 3) ? true : false;
 | 
				
			||||||
 | 
						copy_sqlite3_text_to_buf(subscr.imei, stmt, 4);
 | 
				
			||||||
 | 
						/* Default periodic LU was 30 mins and the expire_lu
 | 
				
			||||||
 | 
						 * was twice that + 1 min
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						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 */
 | 
				
			||||||
 | 
						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_nam(dbc, imsi_str, authorized, true);
 | 
						db_subscr_nam(dbc, imsi_str, authorized, true);
 | 
				
			||||||
	db_subscr_nam(dbc, imsi_str, authorized, false);
 | 
						db_subscr_nam(dbc, imsi_str, authorized, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -361,6 +437,17 @@ int import_nitb_db(void)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(hlr_db_stmt_sql); i++) {
 | 
				
			||||||
 | 
							sql = hlr_db_stmt_sql[i];
 | 
				
			||||||
 | 
							rc = sqlite3_prepare_v2(g_hlr_db_tool_ctx->dbc->db, hlr_db_stmt_sql[i], -1,
 | 
				
			||||||
 | 
										&hlr_db_stmt[i], NULL);
 | 
				
			||||||
 | 
							if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_ERROR, "OsmoHLR DB: Unable to prepare SQL statement '%s'\n", sql);
 | 
				
			||||||
 | 
								ret = -1;
 | 
				
			||||||
 | 
								goto out_free;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stmt = nitb_stmt[NITB_SELECT_SUBSCR];
 | 
						stmt = nitb_stmt[NITB_SELECT_SUBSCR];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
 | 
						while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
 | 
				
			||||||
@@ -387,6 +474,7 @@ 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);
 | 
				
			||||||
@@ -430,6 +518,11 @@ 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);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -279,19 +279,20 @@ 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,
 | 
				
			||||||
			bool final, struct msgb *ss_msg)
 | 
							       struct msgb *ss_msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct osmo_gsup_message resp = {0};
 | 
						struct osmo_gsup_message resp;
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resp.message_type = gsup_msg_type;
 | 
						resp = (struct osmo_gsup_message) {
 | 
				
			||||||
 | 
							.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);
 | 
				
			||||||
@@ -311,7 +312,8 @@ 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);
 | 
				
			||||||
	return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, true, msg);
 | 
						ss->state = OSMO_GSUP_SESSION_STATE_END;
 | 
				
			||||||
 | 
						return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -320,15 +322,16 @@ 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);
 | 
				
			||||||
	return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, true, msg);
 | 
						ss->state = OSMO_GSUP_SESSION_STATE_END;
 | 
				
			||||||
 | 
						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, bool final, uint8_t invoke_id, const char *text)
 | 
					static int ss_tx_to_ms_ussd_7bit(struct ss_session *ss, 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, final, msg);
 | 
						return ss_tx_to_ms(ss, OSMO_GSUP_MSGT_PROC_SS_RESULT, msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/***********************************************************************
 | 
					/***********************************************************************
 | 
				
			||||||
@@ -344,6 +347,8 @@ 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:
 | 
				
			||||||
@@ -351,7 +356,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, true, req->invoke_id, buf);
 | 
							ss_tx_to_ms_ussd_7bit(ss, 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);
 | 
				
			||||||
@@ -369,7 +374,21 @@ 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_tx_to_ms_ussd_7bit(ss, true, req->invoke_id, buf);
 | 
						ss->state = OSMO_GSUP_SESSION_STATE_END;
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -383,6 +402,10 @@ 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)
 | 
				
			||||||
@@ -496,7 +519,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 immediately */
 | 
								/* Release session if the handler has changed its state to END */
 | 
				
			||||||
 | 
								if (ss->state == OSMO_GSUP_SESSION_STATE_END)
 | 
				
			||||||
				ss_session_free(ss);
 | 
									ss_session_free(ss);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -102,6 +102,8 @@ 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;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -114,8 +116,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, 3G_IND=%u%s",
 | 
						vty_out(vty, " '%s' from %s:%5u, CS=%u, PS=%u%s",
 | 
				
			||||||
		name, isc->addr, isc->port, conn->supports_cs, conn->supports_ps, conn->auc_3g_ind,
 | 
							name, isc->addr, isc->port, conn->supports_cs, conn->supports_ps,
 | 
				
			||||||
		VTY_NEWLINE);
 | 
							VTY_NEWLINE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -174,10 +176,11 @@ 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)"
 | 
					#define INT_CHOICE "(own-msisdn|own-imsi|test-idle)"
 | 
				
			||||||
#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"
 | 
				
			||||||
@@ -305,7 +308,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-existant EUSE %s%s", argv[0], VTY_NEWLINE);
 | 
							vty_out(vty, "%% Cannot remove non-existent 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) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,12 +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)
 | 
					static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen, bool only_age)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	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);
 | 
				
			||||||
@@ -64,7 +65,10 @@ 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
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -108,8 +112,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);
 | 
						dump_last_lu_seen(vty, "CS", subscr->last_lu_seen, false);
 | 
				
			||||||
	dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps);
 | 
						dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!*subscr->imsi)
 | 
						if (!*subscr->imsi)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
@@ -159,6 +163,28 @@ 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];
 | 
				
			||||||
@@ -186,10 +212,52 @@ 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" \
 | 
				
			||||||
@@ -207,7 +275,7 @@ static int get_subscr_by_argv(struct vty *vty, const char *type, const char *id,
 | 
				
			|||||||
DEFUN(subscriber_show,
 | 
					DEFUN(subscriber_show,
 | 
				
			||||||
      subscriber_show_cmd,
 | 
					      subscriber_show_cmd,
 | 
				
			||||||
      SUBSCR "show",
 | 
					      SUBSCR "show",
 | 
				
			||||||
      SUBSCR_HELP "Show subscriber information\n")
 | 
					      SUBSCR_HELP SUBSCR_SHOW_HELP)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hlr_subscriber subscr;
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
	const char *id_type = argv[0];
 | 
						const char *id_type = argv[0];
 | 
				
			||||||
@@ -222,7 +290,50 @@ 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_CMD_HELP SUBSCR_ID_HELP);
 | 
					      SHOW_STR SUBSCR_SHOW_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,
 | 
				
			||||||
@@ -551,6 +662,55 @@ DEFUN(subscriber_aud3g,
 | 
				
			|||||||
	return CMD_SUCCESS;
 | 
						return CMD_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFUN(subscriber_aud3g_xor,
 | 
				
			||||||
 | 
					      subscriber_aud3g_xor_cmd,
 | 
				
			||||||
 | 
					      SUBSCR_UPDATE "aud3g xor k K"
 | 
				
			||||||
 | 
					      " [ind-bitlen] [<0-28>]",
 | 
				
			||||||
 | 
					      SUBSCR_UPDATE_HELP
 | 
				
			||||||
 | 
					      "Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
 | 
				
			||||||
 | 
					      "Use XOR 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", &aud3g.algo, &minlen, &maxlen)) {
 | 
				
			||||||
 | 
							vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor", VTY_NEWLINE);
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
 | 
				
			||||||
 | 
							return CMD_WARNING;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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_imei,
 | 
					DEFUN(subscriber_imei,
 | 
				
			||||||
      subscriber_imei_cmd,
 | 
					      subscriber_imei_cmd,
 | 
				
			||||||
      SUBSCR_UPDATE "imei (none|IMEI)",
 | 
					      SUBSCR_UPDATE "imei (none|IMEI)",
 | 
				
			||||||
@@ -628,6 +788,10 @@ 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);
 | 
				
			||||||
@@ -637,6 +801,7 @@ 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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -487,7 +487,7 @@ static int socket_cb(struct osmo_fd *ofd, unsigned int flags)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	int rc = 0;
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (flags & BSC_FD_READ)
 | 
						if (flags & OSMO_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 = BSC_FD_READ;
 | 
						c->ofd.when = OSMO_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 = BSC_FD_READ;
 | 
						ofd->when = OSMO_FD_READ;
 | 
				
			||||||
	ofd->cb = socket_accept;
 | 
						ofd->cb = socket_accept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = osmo_fd_register(ofd);
 | 
						rc = osmo_fd_register(ofd);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
SUBDIRS = \
 | 
					SUBDIRS = \
 | 
				
			||||||
	auc \
 | 
						auc \
 | 
				
			||||||
	gsup_server \
 | 
					 | 
				
			||||||
	db \
 | 
						db \
 | 
				
			||||||
	gsup \
 | 
						gsup \
 | 
				
			||||||
	db_upgrade \
 | 
						db_upgrade \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -113,6 +113,7 @@ 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_data aud2g;
 | 
						struct osmo_sub_auth_data aud2g;
 | 
				
			||||||
@@ -174,6 +175,8 @@ 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_data aud2g;
 | 
						struct osmo_sub_auth_data aud2g;
 | 
				
			||||||
@@ -284,6 +287,9 @@ 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_data aud2g;
 | 
						struct osmo_sub_auth_data aud2g;
 | 
				
			||||||
@@ -454,6 +460,55 @@ static void test_gen_vectors_3g_only(void)
 | 
				
			|||||||
	comment_end();
 | 
						comment_end();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Subscriber with only 3G (XOR) authentication data,
 | 
				
			||||||
 | 
					 * 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_data aud2g;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud3g;
 | 
				
			||||||
 | 
						struct osmo_auth_vector vec;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						comment_start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aud2g = (struct osmo_sub_auth_data){ 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aud3g = (struct osmo_sub_auth_data){
 | 
				
			||||||
 | 
							.type = OSMO_AUTH_TYPE_UMTS,
 | 
				
			||||||
 | 
							.algo = OSMO_AUTH_ALG_XOR,
 | 
				
			||||||
 | 
							.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 test_gen_vectors_bad_args()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct osmo_auth_vector vec;
 | 
						struct osmo_auth_vector vec;
 | 
				
			||||||
@@ -613,15 +668,20 @@ 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_filename(osmo_stderr_target, cmdline_opts.verbose);
 | 
						log_set_print_filename2(osmo_stderr_target,
 | 
				
			||||||
 | 
									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,6 +217,29 @@ 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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,9 +106,10 @@ int main()
 | 
				
			|||||||
	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_filename(osmo_stderr_target, 0);
 | 
						log_set_print_filename2(osmo_stderr_target, 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");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -918,6 +918,50 @@ static void test_subscr_sqn()
 | 
				
			|||||||
	comment_end();
 | 
						comment_end();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_ind()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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 = {
 | 
				
			||||||
@@ -980,9 +1024,13 @@ 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_filename(osmo_stderr_target, cmdline_opts.verbose);
 | 
						log_set_print_filename2(osmo_stderr_target,
 | 
				
			||||||
 | 
									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");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -998,6 +1046,7 @@ 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);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1613,3 +1613,83 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,6 +85,7 @@ 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
 | 
				
			||||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
 | 
					DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Resulting db:
 | 
					Resulting db:
 | 
				
			||||||
@@ -117,6 +118,13 @@ 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
 | 
				
			||||||
@@ -171,5 +179,5 @@ osmo-hlr --database $db --db-check --config-file $srcdir/osmo-hlr.cfg
 | 
				
			|||||||
rc = 0
 | 
					rc = 0
 | 
				
			||||||
DMAIN hlr starting
 | 
					DMAIN hlr starting
 | 
				
			||||||
DDB using database: <PATH>test.db
 | 
					DDB using database: <PATH>test.db
 | 
				
			||||||
DDB Database <PATH>test.db' has HLR DB schema version 5
 | 
					DDB Database <PATH>test.db' has HLR DB schema version 6
 | 
				
			||||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
 | 
					DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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_filename(osmo_stderr_target, 0);
 | 
						log_set_print_filename2(osmo_stderr_target, 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(osmo_stderr_target, 1);
 | 
						log_set_print_category(osmo_stderr_target, 1);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,44 +0,0 @@
 | 
				
			|||||||
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"
 | 
					 | 
				
			||||||
@@ -1,145 +0,0 @@
 | 
				
			|||||||
/* (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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,94 +0,0 @@
 | 
				
			|||||||
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
 | 
					 | 
				
			||||||
@@ -583,7 +583,7 @@ 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_filename(osmo_stderr_target, 0);
 | 
						log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
 | 
				
			||||||
	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);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -233,7 +233,7 @@ 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_filename(osmo_stderr_target, 0);
 | 
						log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
 | 
				
			||||||
	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);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -174,7 +174,7 @@ 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_filename(osmo_stderr_target, 0);
 | 
						log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
 | 
				
			||||||
	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);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,7 +73,7 @@ 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_filename(osmo_stderr_target, 0);
 | 
						log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
 | 
				
			||||||
	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,6 +13,10 @@ 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
 | 
				
			||||||
@@ -51,7 +55,7 @@ OsmoHLR(config-hlr)# list
 | 
				
			|||||||
  database PATH
 | 
					  database PATH
 | 
				
			||||||
  euse NAME
 | 
					  euse NAME
 | 
				
			||||||
  no euse NAME
 | 
					  no euse NAME
 | 
				
			||||||
  ussd route prefix PREFIX internal (own-msisdn|own-imsi)
 | 
					  ussd route prefix PREFIX internal (own-msisdn|own-imsi|test-idle)
 | 
				
			||||||
  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
 | 
				
			||||||
@@ -103,6 +107,7 @@ 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
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ OsmoHLR# list
 | 
				
			|||||||
  subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor) 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 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 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
 | 
				
			||||||
@@ -268,6 +269,7 @@ 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
 | 
				
			||||||
 | 
					  xor       Use XOR 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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,13 +22,6 @@ 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