mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr.git
				synced 2025-10-30 03:33:48 +00:00 
			
		
		
		
	Compare commits
	
		
			23 Commits
		
	
	
		
			cccamp2019
			...
			osmith/fix
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 276c5a7719 | ||
|  | 80dc9ae4be | ||
|  | a377c41bd4 | ||
|  | 06f5af22c8 | ||
|  | 07e1602d2d | ||
|  | abdfdb8a4a | ||
|  | 7355d0ddfe | ||
|  | 6b305b4c30 | ||
|  | a7d0f87eb7 | ||
|  | 981e126686 | ||
|  | 7143f3a0cb | ||
|  | f0968798a2 | ||
|  | 2f75803e5d | ||
|  | 7f4dd11682 | ||
|  | a8045daeef | ||
|  | 4359b885d4 | ||
|  | 5b65461d68 | ||
|  | f8ad67e7fc | ||
|  | c3d40326ec | ||
|  | a9f8a4bdce | ||
|  | f5459de2e2 | ||
|  | 7d2843df4c | ||
|  | 2b0bf31183 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -50,6 +50,7 @@ tests/gsup_server/gsup_server_test | ||||
| tests/gsup/gsup_test | ||||
| tests/db/db_test | ||||
| tests/hlr_vty_test.db* | ||||
| tests/db_upgrade/*.dump | ||||
|  | ||||
| # manuals | ||||
| doc/manuals/*.html | ||||
|   | ||||
| @@ -175,6 +175,8 @@ AC_OUTPUT( | ||||
| 	src/Makefile | ||||
| 	src/gsupclient/Makefile | ||||
| 	include/Makefile | ||||
| 	include/osmocom/Makefile | ||||
| 	include/osmocom/hlr/Makefile | ||||
| 	libosmo-gsup-client.pc | ||||
| 	sql/Makefile | ||||
| 	doc/manuals/Makefile | ||||
| @@ -184,6 +186,6 @@ AC_OUTPUT( | ||||
| 	tests/auc/Makefile | ||||
| 	tests/auc/gen_ts_55_205_test_sets/Makefile | ||||
| 	tests/gsup_server/Makefile | ||||
| 	tests/gsup/Makefile | ||||
| 	tests/db/Makefile | ||||
| 	tests/db_upgrade/Makefile | ||||
| 	) | ||||
|   | ||||
							
								
								
									
										2
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							| @@ -7,7 +7,7 @@ Build-Depends: debhelper (>= 9), | ||||
|                dh-autoreconf, | ||||
|                dh-systemd (>= 1.5), | ||||
|                autotools-dev, | ||||
|                python-minimal, | ||||
|                python3-minimal, | ||||
|                libosmocore-dev, | ||||
|                libosmo-abis-dev, | ||||
|                libosmo-netif-dev, | ||||
|   | ||||
| @@ -52,7 +52,7 @@ transceiving only RAND and SRES, may be applicable. (See 3GPP TS 33.102, chapter | ||||
| |aud3g.ind_bitlen|5|Nr of index bits at lower SQN end | ||||
| |apn|| | ||||
| |vlr_number||3GPP TS 23.008 chapter 2.4.5 | ||||
| |hlr_number||3GPP TS 23.008 chapter 2.4.6 | ||||
| |msc_number||3GPP TS 23.008 chapter 2.4.6 | ||||
| |sgsn_number||3GPP TS 23.008 chapter 2.4.8.1 | ||||
| |sgsn_address||3GPP TS 23.008 chapter 2.13.10 | ||||
| |ggsn_number||3GPP TS 23.008 chapter 2.4.8.2 | ||||
|   | ||||
| @@ -1,2 +1,3 @@ | ||||
| nobase_include_HEADERS = osmocom/gsupclient/gsup_client.h | ||||
| SUBDIRS = osmocom | ||||
|  | ||||
| nobase_include_HEADERS = osmocom/gsupclient/gsup_client.h | ||||
|   | ||||
							
								
								
									
										3
									
								
								include/osmocom/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								include/osmocom/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| SUBDIRS = \ | ||||
| 	hlr \ | ||||
| 	$(NULL) | ||||
| @@ -6,18 +6,17 @@ | ||||
|  * Author: Jacob Erlbeck | ||||
|  * | ||||
|  * 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 | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along | ||||
|  * with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
|   | ||||
							
								
								
									
										14
									
								
								include/osmocom/hlr/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								include/osmocom/hlr/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| noinst_HEADERS = \ | ||||
| 	auc.h \ | ||||
| 	ctrl.h \ | ||||
| 	db.h \ | ||||
| 	gsup_router.h \ | ||||
| 	gsup_server.h \ | ||||
| 	hlr.h \ | ||||
| 	hlr_ussd.h \ | ||||
| 	hlr_vty.h \ | ||||
| 	hlr_vty_subscr.h \ | ||||
| 	logging.h \ | ||||
| 	luop.h \ | ||||
| 	rand.h \ | ||||
| 	$(NULL) | ||||
| @@ -28,6 +28,7 @@ enum stmt_idx { | ||||
| 	DB_STMT_AUC_3G_INSERT, | ||||
| 	DB_STMT_AUC_3G_DELETE, | ||||
| 	DB_STMT_SET_LAST_LU_SEEN, | ||||
| 	DB_STMT_SET_LAST_LU_SEEN_PS, | ||||
| 	DB_STMT_EXISTS_BY_IMSI, | ||||
| 	DB_STMT_EXISTS_BY_MSISDN, | ||||
| 	_NUM_DB_STMT | ||||
| @@ -65,7 +66,7 @@ int db_update_sqn(struct db_context *dbc, int64_t id, | ||||
| int db_get_auc(struct db_context *dbc, const char *imsi, | ||||
| 	       unsigned int auc_3g_ind, struct osmo_auth_vector *vec, | ||||
| 	       unsigned int num_vec, const uint8_t *rand_auts, | ||||
| 	       const uint8_t *auts); | ||||
| 	       const uint8_t *auts, bool separation_bit); | ||||
| 
 | ||||
| #include <osmocom/core/linuxlist.h> | ||||
| #include <osmocom/gsm/protocol/gsm_23_003.h> | ||||
| @@ -95,6 +96,7 @@ struct hlr_subscriber { | ||||
| 	bool		ms_purged_cs; | ||||
| 	bool		ms_purged_ps; | ||||
| 	time_t		last_lu_seen; | ||||
| 	time_t		last_lu_seen_ps; | ||||
| }; | ||||
| 
 | ||||
| /* A format string for use with strptime(3). This format string is
 | ||||
| @@ -1,7 +1,7 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include "gsup_server.h" | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| 
 | ||||
| struct gsup_route { | ||||
| 	struct llist_head list; | ||||
| @@ -47,6 +47,7 @@ struct osmo_gsup_conn { | ||||
| 	bool supports_ps; /* client supports OSMO_GSUP_CN_DOMAIN_PS */ | ||||
| }; | ||||
| 
 | ||||
| struct msgb *osmo_gsup_msgb_alloc(const char *label); | ||||
| 
 | ||||
| int osmo_gsup_conn_send(struct osmo_gsup_conn *conn, struct msgb *msg); | ||||
| int osmo_gsup_conn_ccm_get(const struct osmo_gsup_conn *clnt, uint8_t **addr, | ||||
| @@ -5,7 +5,7 @@ | ||||
| #include <osmocom/core/linuxlist.h> | ||||
| #include <osmocom/gsm/gsup.h> | ||||
| 
 | ||||
| #include "gsup_server.h" | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| 
 | ||||
| #define NCSS_GUARD_TIMEOUT_DEFAULT 30 | ||||
| 
 | ||||
| @@ -25,7 +25,7 @@ | ||||
| #include <osmocom/core/logging.h> | ||||
| #include <osmocom/vty/vty.h> | ||||
| #include <osmocom/vty/command.h> | ||||
| #include "hlr.h" | ||||
| #include <osmocom/hlr/hlr.h> | ||||
| 
 | ||||
| enum hlr_vty_node { | ||||
| 	HLR_NODE = _LAST_OSMOVTY_NODE + 1, | ||||
| @@ -27,8 +27,8 @@ | ||||
| #include <osmocom/core/timer.h> | ||||
| #include <osmocom/gsm/gsup.h> | ||||
| 
 | ||||
| #include "db.h" | ||||
| #include "gsup_server.h" | ||||
| #include <osmocom/hlr/db.h> | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| 
 | ||||
| #define CANCEL_TIMEOUT_SECS	30 | ||||
| #define ISD_TIMEOUT_SECS	30 | ||||
							
								
								
									
										10
									
								
								sql/hlr.sql
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								sql/hlr.sql
									
									
									
									
									
								
							| @@ -12,7 +12,7 @@ CREATE TABLE subscriber ( | ||||
| 	-- Chapter 2.4.5 | ||||
| 	vlr_number	VARCHAR(15), | ||||
| 	-- Chapter 2.4.6 | ||||
| 	hlr_number	VARCHAR(15), | ||||
| 	msc_number	VARCHAR(15), | ||||
| 	-- Chapter 2.4.8.1 | ||||
| 	sgsn_number	VARCHAR(15), | ||||
| 	-- Chapter 2.13.10 | ||||
| @@ -42,7 +42,8 @@ CREATE TABLE subscriber ( | ||||
|  | ||||
| 	-- Timestamp of last location update seen from subscriber | ||||
| 	-- The value is a string which encodes a UTC timestamp in granularity of seconds. | ||||
| 	last_lu_seen TIMESTAMP default NULL | ||||
| 	last_lu_seen TIMESTAMP default NULL, | ||||
| 	last_lu_seen_ps TIMESTAMP default NULL | ||||
| ); | ||||
|  | ||||
| CREATE TABLE subscriber_apn ( | ||||
| @@ -69,11 +70,12 @@ CREATE TABLE auc_3g ( | ||||
| 	op		VARCHAR(32),		-- hex string: operator's secret key (128bit) | ||||
| 	opc		VARCHAR(32),		-- hex string: derived from OP and K (128bit) | ||||
| 	sqn		INTEGER NOT NULL DEFAULT 0,	-- sequence number of key usage | ||||
| 	ind_bitlen	INTEGER NOT NULL DEFAULT 5	-- nr of index bits at lower SQN end | ||||
| 	-- nr of index bits at lower SQN end | ||||
| 	ind_bitlen	INTEGER NOT NULL DEFAULT 5 | ||||
| ); | ||||
|  | ||||
| CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi); | ||||
|  | ||||
| -- Set HLR database schema version number | ||||
| -- Note: This constant is currently duplicated in src/db.c and must be kept in sync! | ||||
| PRAGMA user_version = 2; | ||||
| PRAGMA user_version = 4; | ||||
|   | ||||
| @@ -11,6 +11,7 @@ AM_CFLAGS = \ | ||||
| 	$(NULL) | ||||
|  | ||||
| AM_CPPFLAGS = -I$(top_srcdir)/include \ | ||||
| 	-I$(top_builddir)/include \ | ||||
| 	$(NULL) | ||||
|  | ||||
| EXTRA_DIST = \ | ||||
| @@ -24,18 +25,6 @@ BUILT_SOURCES = \ | ||||
| CLEANFILES = $(BUILT_SOURCES) | ||||
|  | ||||
| noinst_HEADERS = \ | ||||
| 	auc.h \ | ||||
| 	db.h \ | ||||
| 	hlr.h \ | ||||
| 	luop.h \ | ||||
| 	gsup_router.h \ | ||||
| 	gsup_server.h \ | ||||
| 	logging.h \ | ||||
| 	rand.h \ | ||||
| 	ctrl.h \ | ||||
| 	hlr_vty.h \ | ||||
| 	hlr_vty_subscr.h \ | ||||
| 	hlr_ussd.h \ | ||||
| 	db_bootstrap.h \ | ||||
| 	$(NULL) | ||||
|  | ||||
|   | ||||
| @@ -23,8 +23,8 @@ | ||||
| #include <osmocom/core/utils.h> | ||||
| #include <osmocom/crypt/auth.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "rand.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/rand.h> | ||||
|  | ||||
| #define hexb(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf)) | ||||
| #define hex(buf,sz) osmo_hexdump_nospc((void*)buf, sz) | ||||
|   | ||||
| @@ -28,9 +28,9 @@ | ||||
| #include <osmocom/gsm/gsm23003.h> | ||||
| #include <osmocom/ctrl/ports.h> | ||||
|  | ||||
| #include "hlr.h" | ||||
| #include "ctrl.h" | ||||
| #include "db.h" | ||||
| #include <osmocom/hlr/hlr.h> | ||||
| #include <osmocom/hlr/ctrl.h> | ||||
| #include <osmocom/hlr/db.h> | ||||
|  | ||||
| #define SEL_BY "by-" | ||||
| #define SEL_BY_IMSI SEL_BY "imsi-" | ||||
|   | ||||
							
								
								
									
										274
									
								
								src/db.c
									
									
									
									
									
								
							
							
						
						
									
										274
									
								
								src/db.c
									
									
									
									
									
								
							| @@ -23,12 +23,12 @@ | ||||
| #include <sqlite3.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "db.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/db.h> | ||||
| #include "db_bootstrap.h" | ||||
|  | ||||
| /* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */ | ||||
| #define CURRENT_SCHEMA_VERSION	2 | ||||
| #define CURRENT_SCHEMA_VERSION	4 | ||||
|  | ||||
| #define SEL_COLUMNS \ | ||||
| 	"id," \ | ||||
| @@ -45,7 +45,8 @@ | ||||
| 	"lmsi," \ | ||||
| 	"ms_purged_cs," \ | ||||
| 	"ms_purged_ps," \ | ||||
| 	"last_lu_seen" | ||||
| 	"last_lu_seen," \ | ||||
| 	"last_lu_seen_ps" \ | ||||
|  | ||||
| static const char *stmt_sql[] = { | ||||
| 	[DB_STMT_SEL_BY_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi = ?", | ||||
| @@ -79,6 +80,7 @@ static const char *stmt_sql[] = { | ||||
| 		" VALUES($subscriber_id, $algo_id_3g, $k, $op, $opc, $ind_bitlen)", | ||||
| 	[DB_STMT_AUC_3G_DELETE] = "DELETE FROM auc_3g WHERE subscriber_id = $subscriber_id", | ||||
| 	[DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch') WHERE id = $subscriber_id", | ||||
| 	[DB_STMT_SET_LAST_LU_SEEN_PS] = "UPDATE subscriber SET last_lu_seen_ps = datetime($val, 'unixepoch') WHERE id = $subscriber_id", | ||||
| 	[DB_STMT_EXISTS_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi", | ||||
| 	[DB_STMT_EXISTS_BY_MSISDN] = "SELECT 1 FROM subscriber WHERE msisdn = $msisdn", | ||||
| }; | ||||
| @@ -201,28 +203,38 @@ void db_close(struct db_context *dbc) | ||||
| 	talloc_free(dbc); | ||||
| } | ||||
|  | ||||
| static int db_bootstrap(struct db_context *dbc) | ||||
| static int db_run_statements(struct db_context *dbc, const char **statements, size_t statements_count) | ||||
| { | ||||
| 	int rc; | ||||
| 	int i; | ||||
| 	for (i = 0; i < ARRAY_SIZE(stmt_bootstrap_sql); i++) { | ||||
| 		int rc; | ||||
| 	for (i = 0; i < statements_count; i++) { | ||||
| 		const char *stmt_str = statements[i]; | ||||
| 		sqlite3_stmt *stmt; | ||||
| 		rc = sqlite3_prepare_v2(dbc->db, stmt_bootstrap_sql[i], -1, &stmt, NULL); | ||||
|  | ||||
| 		rc = sqlite3_prepare_v2(dbc->db, stmt_str, -1, &stmt, NULL); | ||||
| 		if (rc != SQLITE_OK) { | ||||
| 			LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", stmt_bootstrap_sql[i]); | ||||
| 			LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", stmt_str); | ||||
| 			return rc; | ||||
| 		} | ||||
|  | ||||
| 		rc = sqlite3_step(stmt); | ||||
| 		db_remove_reset(stmt); | ||||
| 		sqlite3_finalize(stmt); | ||||
| 		if (rc != SQLITE_DONE) { | ||||
| 			LOGP(DDB, LOGL_ERROR, "Cannot bootstrap database: SQL error: (%d) %s," | ||||
| 			     " during stmt '%s'", | ||||
| 			     rc, sqlite3_errmsg(dbc->db), stmt_bootstrap_sql[i]); | ||||
| 			LOGP(DDB, LOGL_ERROR, "SQL error: (%d) %s, during stmt '%s'", | ||||
| 			     rc, sqlite3_errmsg(dbc->db), stmt_str); | ||||
| 			return rc; | ||||
| 		} | ||||
| 	} | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| static int db_bootstrap(struct db_context *dbc) | ||||
| { | ||||
| 	int rc = db_run_statements(dbc, stmt_bootstrap_sql, ARRAY_SIZE(stmt_bootstrap_sql)); | ||||
| 	if (rc != SQLITE_DONE) { | ||||
| 		LOGP(DDB, LOGL_ERROR, "Cannot bootstrap database\n"); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	return SQLITE_OK; | ||||
| } | ||||
|  | ||||
| @@ -263,72 +275,180 @@ static bool db_is_bootstrapped_v0(struct db_context *dbc) | ||||
| static int | ||||
| db_upgrade_v1(struct db_context *dbc) | ||||
| { | ||||
| 	sqlite3_stmt *stmt; | ||||
| 	int rc; | ||||
| 	const char *update_stmt_sql = "ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL"; | ||||
| 	const char *set_schema_version_sql = "PRAGMA user_version = 1"; | ||||
| 	const char *statements[] = { | ||||
| 		"ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL", | ||||
| 		"PRAGMA user_version = 1", | ||||
| 	}; | ||||
|  | ||||
| 	rc = sqlite3_prepare_v2(dbc->db, update_stmt_sql, -1, &stmt, NULL); | ||||
| 	if (rc != SQLITE_OK) { | ||||
| 		LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", update_stmt_sql); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	rc = sqlite3_step(stmt); | ||||
| 	db_remove_reset(stmt); | ||||
| 	sqlite3_finalize(stmt); | ||||
| 	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 %d\n", 1); | ||||
| 		LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 1\n"); | ||||
| 		return rc; | ||||
| 	} | ||||
|  | ||||
| 	rc = sqlite3_prepare_v2(dbc->db, set_schema_version_sql, -1, &stmt, NULL); | ||||
| 	if (rc != SQLITE_OK) { | ||||
| 		LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", set_schema_version_sql); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	rc = sqlite3_step(stmt); | ||||
| 	if (rc != SQLITE_DONE) | ||||
| 		LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version %d\n", 1); | ||||
|  | ||||
| 	db_remove_reset(stmt); | ||||
| 	sqlite3_finalize(stmt); | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| static int db_upgrade_v2(struct db_context *dbc) | ||||
| { | ||||
| 	sqlite3_stmt *stmt; | ||||
| 	int rc; | ||||
| 	const char *update_stmt_sql = "ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14) default NULL"; | ||||
| 	const char *set_schema_version_sql = "PRAGMA user_version = 2"; | ||||
| 	const char *statements[] = { | ||||
| 		"ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14)", | ||||
| 		"PRAGMA user_version = 2", | ||||
| 	}; | ||||
|  | ||||
| 	rc = sqlite3_prepare_v2(dbc->db, update_stmt_sql, -1, &stmt, NULL); | ||||
| 	if (rc != SQLITE_OK) { | ||||
| 		LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", update_stmt_sql); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	rc = sqlite3_step(stmt); | ||||
| 	db_remove_reset(stmt); | ||||
| 	sqlite3_finalize(stmt); | ||||
| 	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 %d\n", 1); | ||||
| 		LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 2\n"); | ||||
| 		return rc; | ||||
| 	} | ||||
|  | ||||
| 	rc = sqlite3_prepare_v2(dbc->db, set_schema_version_sql, -1, &stmt, NULL); | ||||
| 	if (rc != SQLITE_OK) { | ||||
| 		LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", set_schema_version_sql); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	rc = sqlite3_step(stmt); | ||||
| 	if (rc != SQLITE_DONE) | ||||
| 		LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version %d\n", 1); | ||||
|  | ||||
| 	db_remove_reset(stmt); | ||||
| 	sqlite3_finalize(stmt); | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| static int db_upgrade_v3(struct db_context *dbc) | ||||
| { | ||||
| 	int rc; | ||||
|  | ||||
| 	/* A newer SQLite version would allow simply 'ATLER TABLE subscriber RENAME COLUMN hlr_number TO msc_number'. | ||||
| 	 * This is a really expensive workaround for that in order to cover earlier SQLite versions as well: | ||||
| 	 * Create a new table with the new column name and copy the data over (https://www.sqlite.org/faq.html#q11). | ||||
| 	 */ | ||||
| #define SUBSCR_V3_CREATE  \ | ||||
| "(\n" \ | ||||
| "-- OsmoHLR's DB scheme is modelled roughly after TS 23.008 version 13.3.0\n" \ | ||||
| "	id		INTEGER PRIMARY KEY,\n" \ | ||||
| "	-- Chapter 2.1.1.1\n" \ | ||||
| "	imsi		VARCHAR(15) UNIQUE NOT NULL,\n" \ | ||||
| "	-- Chapter 2.1.2\n" \ | ||||
| "	msisdn		VARCHAR(15) UNIQUE,\n" \ | ||||
| "	-- Chapter 2.2.3: Most recent / current IMEISV\n" \ | ||||
| "	imeisv		VARCHAR,\n" \ | ||||
| "	-- Chapter 2.1.9: Most recent / current IMEI\n" \ | ||||
| "	imei		VARCHAR(14),\n" \ | ||||
| "	-- Chapter 2.4.5\n" \ | ||||
| "	vlr_number	VARCHAR(15),\n" \ | ||||
| "	-- Chapter 2.4.6\n" \ | ||||
| "	msc_number	VARCHAR(15),\n" \ | ||||
| "	-- Chapter 2.4.8.1\n" \ | ||||
| "	sgsn_number	VARCHAR(15),\n" \ | ||||
| "	-- Chapter 2.13.10\n" \ | ||||
| "	sgsn_address	VARCHAR,\n" \ | ||||
| "	-- Chapter 2.4.8.2\n" \ | ||||
| "	ggsn_number	VARCHAR(15),\n" \ | ||||
| "	-- Chapter 2.4.9.2\n" \ | ||||
| "	gmlc_number	VARCHAR(15),\n" \ | ||||
| "	-- Chapter 2.4.23\n" \ | ||||
| "	smsc_number	VARCHAR(15),\n" \ | ||||
| "	-- Chapter 2.4.24\n" \ | ||||
| "	periodic_lu_tmr	INTEGER,\n" \ | ||||
| "	-- Chapter 2.13.115\n" \ | ||||
| "	periodic_rau_tau_tmr INTEGER,\n" \ | ||||
| "	-- Chapter 2.1.1.2: network access mode\n" \ | ||||
| "	nam_cs		BOOLEAN NOT NULL DEFAULT 1,\n" \ | ||||
| "	nam_ps		BOOLEAN NOT NULL DEFAULT 1,\n" \ | ||||
| "	-- Chapter 2.1.8\n" \ | ||||
| "	lmsi		INTEGER,\n" \ | ||||
|  \ | ||||
| "	-- The below purged flags might not even be stored non-volatile,\n" \ | ||||
| "	-- refer to TS 23.012 Chapter 3.6.1.4\n" \ | ||||
| "	-- Chapter 2.7.5\n" \ | ||||
| "	ms_purged_cs	BOOLEAN NOT NULL DEFAULT 0,\n" \ | ||||
| "	-- Chapter 2.7.6\n" \ | ||||
| "	ms_purged_ps	BOOLEAN NOT NULL DEFAULT 0,\n" \ | ||||
|  \ | ||||
| "	-- Timestamp of last location update seen from subscriber\n" \ | ||||
| "	-- The value is a string which encodes a UTC timestamp in granularity of seconds.\n" \ | ||||
| "	last_lu_seen TIMESTAMP default NULL\n" \ | ||||
| ")\n" | ||||
|  | ||||
| #define SUBSCR_V2_COLUMN_NAMES \ | ||||
| 	"id," \ | ||||
| 	"imsi," \ | ||||
| 	"msisdn," \ | ||||
| 	"imeisv," \ | ||||
| 	"imei," \ | ||||
| 	"vlr_number," \ | ||||
| 	"hlr_number," \ | ||||
| 	"sgsn_number," \ | ||||
| 	"sgsn_address," \ | ||||
| 	"ggsn_number," \ | ||||
| 	"gmlc_number," \ | ||||
| 	"smsc_number," \ | ||||
| 	"periodic_lu_tmr," \ | ||||
| 	"periodic_rau_tau_tmr," \ | ||||
| 	"nam_cs," \ | ||||
| 	"nam_ps," \ | ||||
| 	"lmsi," \ | ||||
| 	"ms_purged_cs," \ | ||||
| 	"ms_purged_ps," \ | ||||
| 	"last_lu_seen" | ||||
|  | ||||
| #define SUBSCR_V3_COLUMN_NAMES \ | ||||
| 	"id," \ | ||||
| 	"imsi," \ | ||||
| 	"msisdn," \ | ||||
| 	"imeisv," \ | ||||
| 	"imei," \ | ||||
| 	"vlr_number," \ | ||||
| 	"msc_number," \ | ||||
| 	"sgsn_number," \ | ||||
| 	"sgsn_address," \ | ||||
| 	"ggsn_number," \ | ||||
| 	"gmlc_number," \ | ||||
| 	"smsc_number," \ | ||||
| 	"periodic_lu_tmr," \ | ||||
| 	"periodic_rau_tau_tmr," \ | ||||
| 	"nam_cs," \ | ||||
| 	"nam_ps," \ | ||||
| 	"lmsi," \ | ||||
| 	"ms_purged_cs," \ | ||||
| 	"ms_purged_ps," \ | ||||
| 	"last_lu_seen" | ||||
|  | ||||
| 	const char *statements[] = { | ||||
| 		"BEGIN TRANSACTION", | ||||
| 		"CREATE TEMPORARY TABLE subscriber_backup" SUBSCR_V3_CREATE, | ||||
| 		"INSERT INTO subscriber_backup SELECT " SUBSCR_V2_COLUMN_NAMES " FROM subscriber", | ||||
| 		"DROP TABLE subscriber", | ||||
| 		"CREATE TABLE subscriber" SUBSCR_V3_CREATE, | ||||
| 		"INSERT INTO subscriber SELECT " SUBSCR_V3_COLUMN_NAMES " FROM subscriber_backup", | ||||
| 		"DROP TABLE subscriber_backup", | ||||
| 		"COMMIT", | ||||
| 		"PRAGMA user_version = 3", | ||||
| 	}; | ||||
|  | ||||
| 	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 3\n"); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| static int db_upgrade_v4(struct db_context *dbc) | ||||
| { | ||||
| 	int rc; | ||||
| 	const char *statements[] = { | ||||
| 		"ALTER TABLE subscriber ADD COLUMN last_lu_seen_ps TIMESTAMP default NULL", | ||||
| 		"PRAGMA user_version = 4", | ||||
| 	}; | ||||
|  | ||||
| 	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 4\n"); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	return rc; | ||||
| } | ||||
|  | ||||
| typedef int (*db_upgrade_func_t)(struct db_context *dbc); | ||||
| static db_upgrade_func_t db_upgrade_path[] = { | ||||
| 	db_upgrade_v1, | ||||
| 	db_upgrade_v2, | ||||
| 	db_upgrade_v3, | ||||
| 	db_upgrade_v4, | ||||
| }; | ||||
|  | ||||
| static int db_get_user_version(struct db_context *dbc) | ||||
| { | ||||
| 	const char *user_version_sql = "PRAGMA user_version"; | ||||
| @@ -439,32 +559,16 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logg | ||||
|  | ||||
| 	LOGP(DDB, LOGL_NOTICE, "Database '%s' has HLR DB schema version %d\n", dbc->fname, version); | ||||
|  | ||||
| 	if (version < CURRENT_SCHEMA_VERSION && allow_upgrade) { | ||||
| 		switch (version) { | ||||
| 		case 0: | ||||
| 			rc = db_upgrade_v1(dbc); | ||||
| 			if (rc != SQLITE_DONE) { | ||||
| 				LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version 1: (rc=%d) %s\n", | ||||
| 				     rc, sqlite3_errmsg(dbc->db)); | ||||
| 				goto out_free; | ||||
| 			} | ||||
| 			version = 1; | ||||
| 			/* fall through */ | ||||
| 		case 1: | ||||
| 			rc = db_upgrade_v2(dbc); | ||||
| 			if (rc != SQLITE_DONE) { | ||||
| 				LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version 2: (rc=%d) %s\n", | ||||
| 				     rc, sqlite3_errmsg(dbc->db)); | ||||
| 				goto out_free; | ||||
| 			} | ||||
| 			version = 2; | ||||
| 			/* fall through */ | ||||
| 		/* case N: ... */ | ||||
| 		default: | ||||
| 			break; | ||||
| 	for (; allow_upgrade && (version < ARRAY_SIZE(db_upgrade_path)); version++) { | ||||
| 		db_upgrade_func_t upgrade_func = db_upgrade_path[version]; | ||||
| 		rc = upgrade_func(dbc); | ||||
| 		if (rc != SQLITE_DONE) { | ||||
| 			LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version %d: (rc=%d) %s\n", | ||||
| 			     version+1, rc, sqlite3_errmsg(dbc->db)); | ||||
| 			goto out_free; | ||||
| 		} | ||||
| 		LOGP(DDB, LOGL_NOTICE, "Database '%s' has been upgraded to HLR DB schema version %d\n", | ||||
| 		     dbc->fname, version); | ||||
| 		     dbc->fname, version+1); | ||||
| 	} | ||||
|  | ||||
| 	if (version != CURRENT_SCHEMA_VERSION) { | ||||
|   | ||||
							
								
								
									
										16
									
								
								src/db_auc.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/db_auc.c
									
									
									
									
									
								
							| @@ -26,10 +26,10 @@ | ||||
|  | ||||
| #include <sqlite3.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "db.h" | ||||
| #include "auc.h" | ||||
| #include "rand.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/db.h> | ||||
| #include <osmocom/hlr/auc.h> | ||||
| #include <osmocom/hlr/rand.h> | ||||
|  | ||||
| #define LOGAUC(imsi, level, fmt, args ...)	LOGP(DAUC, level, "IMSI='%s': " fmt, imsi, ## args) | ||||
|  | ||||
| @@ -189,7 +189,7 @@ out: | ||||
| int db_get_auc(struct db_context *dbc, const char *imsi, | ||||
| 	       unsigned int auc_3g_ind, struct osmo_auth_vector *vec, | ||||
| 	       unsigned int num_vec, const uint8_t *rand_auts, | ||||
| 	       const uint8_t *auts) | ||||
| 	       const uint8_t *auts, bool separation_bit) | ||||
| { | ||||
| 	struct osmo_sub_auth_data aud2g, aud3g; | ||||
| 	int64_t subscr_id; | ||||
| @@ -209,6 +209,12 @@ int db_get_auc(struct db_context *dbc, const char *imsi, | ||||
| 		       aud3g.u.umts.ind_bitlen, aud3g.u.umts.ind); | ||||
| 		aud3g.u.umts.ind &= (1U << aud3g.u.umts.ind_bitlen) - 1; | ||||
| 	} | ||||
| 	/* the first bit (bit0) cannot be used as AMF anymore, but has been | ||||
| 	 * re-appropriated as the separation bit.  See 3GPP TS 33.102 Annex H | ||||
| 	 * together with 3GPP TS 33.401 / 33.402 / 33.501 */ | ||||
| 	aud3g.u.umts.amf[0] = aud3g.u.umts.amf[0] & 0x7f; | ||||
| 	if (separation_bit) | ||||
| 		aud3g.u.umts.amf[0] |= 0x80; | ||||
|  | ||||
| 	LOGAUC(imsi, LOGL_DEBUG, "Calling to generate %u vectors\n", num_vec); | ||||
| 	rc = auc_compute_vectors(vec, num_vec, &aud2g, &aud3g, rand_auts, auts); | ||||
|   | ||||
							
								
								
									
										56
									
								
								src/db_hlr.c
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								src/db_hlr.c
									
									
									
									
									
								
							| @@ -33,11 +33,11 @@ | ||||
|  | ||||
| #include <sqlite3.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "hlr.h" | ||||
| #include "db.h" | ||||
| #include "gsup_server.h" | ||||
| #include "luop.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/hlr.h> | ||||
| #include <osmocom/hlr/db.h> | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| #include <osmocom/hlr/luop.h> | ||||
|  | ||||
| #define LOGHLR(imsi, level, fmt, args ...)	LOGP(DAUC, level, "IMSI='%s': " fmt, imsi, ## args) | ||||
|  | ||||
| @@ -438,14 +438,36 @@ out: | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static void parse_last_lu_seen(time_t *dst, const char *last_lu_seen_str, const char *imsi, const char *label) | ||||
| { | ||||
| 	struct tm tm = {0}; | ||||
| 	time_t val; | ||||
| 	if (!last_lu_seen_str || last_lu_seen_str[0] == '\0') | ||||
| 		return; | ||||
|  | ||||
| 	if (strptime(last_lu_seen_str, DB_LAST_LU_SEEN_FMT, &tm) == NULL) { | ||||
| 		LOGP(DAUC, LOGL_ERROR, "IMSI-%s: Last LU Seen %s: Cannot parse timestamp '%s'\n", | ||||
| 		     imsi, label, last_lu_seen_str); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	errno = 0; | ||||
| 	val = mktime(&tm); | ||||
| 	if (val == -1) { | ||||
| 		LOGP(DAUC, LOGL_ERROR, "IMSI-%s: Last LU Seen %s: Cannot convert timestamp '%s' to time_t: %s\n", | ||||
| 		     imsi, label, last_lu_seen_str, strerror(errno)); | ||||
| 		val = 0; | ||||
| 	} | ||||
|  | ||||
| 	*dst = val; | ||||
| } | ||||
|  | ||||
| /* Common code for db_subscr_get_by_*() functions. */ | ||||
| static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscriber *subscr, | ||||
| 		  const char **err) | ||||
| { | ||||
| 	int rc; | ||||
| 	int ret = 0; | ||||
| 	const char *last_lu_seen_str; | ||||
| 	struct tm tm = {0}; | ||||
|  | ||||
| 	/* execute the statement */ | ||||
| 	rc = sqlite3_step(stmt); | ||||
| @@ -479,20 +501,10 @@ static int db_sel(struct db_context *dbc, sqlite3_stmt *stmt, struct hlr_subscri | ||||
| 	subscr->lmsi = sqlite3_column_int(stmt, 11); | ||||
| 	subscr->ms_purged_cs = sqlite3_column_int(stmt, 12); | ||||
| 	subscr->ms_purged_ps = sqlite3_column_int(stmt, 13); | ||||
| 	last_lu_seen_str = (const char *)sqlite3_column_text(stmt, 14); | ||||
| 	if (last_lu_seen_str && last_lu_seen_str[0] != '\0') { | ||||
| 		if (strptime(last_lu_seen_str, DB_LAST_LU_SEEN_FMT, &tm) == NULL) { | ||||
| 			LOGP(DAUC, LOGL_ERROR, "Cannot parse last LU timestamp '%s' of subscriber with IMSI='%s': %s\n", | ||||
| 			     last_lu_seen_str, subscr->imsi, strerror(errno)); | ||||
| 		} else { | ||||
| 			subscr->last_lu_seen = mktime(&tm); | ||||
| 			if (subscr->last_lu_seen == -1) { | ||||
| 				LOGP(DAUC, LOGL_ERROR, "Cannot convert LU timestamp '%s' to time_t: %s\n", | ||||
| 				     last_lu_seen_str, strerror(errno)); | ||||
| 				subscr->last_lu_seen = 0; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	parse_last_lu_seen(&subscr->last_lu_seen, (const char *)sqlite3_column_text(stmt, 14), | ||||
| 			   subscr->imsi, "CS"); | ||||
| 	parse_last_lu_seen(&subscr->last_lu_seen_ps, (const char *)sqlite3_column_text(stmt, 15), | ||||
| 			   subscr->imsi, "PS"); | ||||
|  | ||||
| out: | ||||
| 	db_remove_reset(stmt); | ||||
| @@ -770,7 +782,7 @@ int db_subscr_lu(struct db_context *dbc, int64_t subscr_id, | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	stmt = dbc->stmt[DB_STMT_SET_LAST_LU_SEEN]; | ||||
| 	stmt = dbc->stmt[is_ps? DB_STMT_SET_LAST_LU_SEEN_PS : DB_STMT_SET_LAST_LU_SEEN]; | ||||
|  | ||||
| 	if (!db_bind_int64(stmt, "$subscriber_id", subscr_id)) | ||||
| 		return -EIO; | ||||
|   | ||||
| @@ -23,9 +23,9 @@ | ||||
| #include <osmocom/core/linuxlist.h> | ||||
| #include <osmocom/core/talloc.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "gsup_server.h" | ||||
| #include "gsup_router.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| #include <osmocom/hlr/gsup_router.h> | ||||
|  | ||||
| /*! Find a route for the given address. | ||||
|  * \param[in] gs gsup server | ||||
|   | ||||
| @@ -21,8 +21,8 @@ | ||||
|  | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "gsup_server.h" | ||||
| #include "gsup_router.h" | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| #include <osmocom/hlr/gsup_router.h> | ||||
|  | ||||
| #include <osmocom/core/logging.h> | ||||
|  | ||||
|   | ||||
| @@ -27,8 +27,15 @@ | ||||
| #include <osmocom/gsm/gsm48_ie.h> | ||||
| #include <osmocom/gsm/apn.h> | ||||
|  | ||||
| #include "gsup_server.h" | ||||
| #include "gsup_router.h" | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| #include <osmocom/hlr/gsup_router.h> | ||||
|  | ||||
| struct msgb *osmo_gsup_msgb_alloc(const char *label) | ||||
| { | ||||
| 	struct msgb *msg = msgb_alloc_headroom(1024+16, 16, label); | ||||
| 	OSMO_ASSERT(msg); | ||||
| 	return msg; | ||||
| } | ||||
|  | ||||
| static void osmo_gsup_server_send(struct osmo_gsup_conn *conn, | ||||
| 			     int proto_ext, struct msgb *msg_tx) | ||||
|   | ||||
| @@ -386,7 +386,8 @@ int osmo_gsup_client_enc_send(struct osmo_gsup_client *gsupc, | ||||
| 	rc = osmo_gsup_client_send(gsupc, gsup_msgb); | ||||
| 	if (rc) { | ||||
| 		LOGP(DLGSUP, LOGL_ERROR, "Couldn't send GSUP message\n"); | ||||
| 		goto error; | ||||
| 		/* Do not free, osmo_gsup_client_send() already has. */ | ||||
| 		return rc; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
|   | ||||
							
								
								
									
										74
									
								
								src/hlr.c
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								src/hlr.c
									
									
									
									
									
								
							| @@ -37,16 +37,16 @@ | ||||
| #include <osmocom/gsm/gsm_utils.h> | ||||
| #include <osmocom/gsm/protocol/gsm_23_003.h> | ||||
|  | ||||
| #include "db.h" | ||||
| #include "hlr.h" | ||||
| #include "ctrl.h" | ||||
| #include "logging.h" | ||||
| #include "gsup_server.h" | ||||
| #include "gsup_router.h" | ||||
| #include "rand.h" | ||||
| #include "luop.h" | ||||
| #include "hlr_vty.h" | ||||
| #include "hlr_ussd.h" | ||||
| #include <osmocom/hlr/db.h> | ||||
| #include <osmocom/hlr/hlr.h> | ||||
| #include <osmocom/hlr/ctrl.h> | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| #include <osmocom/hlr/gsup_router.h> | ||||
| #include <osmocom/hlr/rand.h> | ||||
| #include <osmocom/hlr/luop.h> | ||||
| #include <osmocom/hlr/hlr_vty.h> | ||||
| #include <osmocom/hlr/hlr_ussd.h> | ||||
|  | ||||
| struct hlr *g_hlr; | ||||
| static void *hlr_ctx = NULL; | ||||
| @@ -128,7 +128,7 @@ osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr) | ||||
| 		} | ||||
|  | ||||
| 		/* Send ISD to MSC/SGSN */ | ||||
| 		msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP ISD UPDATE"); | ||||
| 		msg_out = osmo_gsup_msgb_alloc("GSUP ISD UPDATE"); | ||||
| 		if (msg_out == NULL) { | ||||
| 			LOGP(DLGSUP, LOGL_ERROR, | ||||
| 			       "IMSI='%s': Cannot notify GSUP client; could not allocate msg buffer " | ||||
| @@ -233,6 +233,7 @@ static int rx_send_auth_info(struct osmo_gsup_conn *conn, | ||||
| { | ||||
| 	struct osmo_gsup_message gsup_out; | ||||
| 	struct msgb *msg_out; | ||||
| 	bool separation_bit = false; | ||||
| 	int rc; | ||||
|  | ||||
| 	subscr_create_on_demand(gsup->imsi); | ||||
| @@ -241,10 +242,13 @@ static int rx_send_auth_info(struct osmo_gsup_conn *conn, | ||||
| 	memset(&gsup_out, 0, sizeof(gsup_out)); | ||||
| 	memcpy(&gsup_out.imsi, &gsup->imsi, sizeof(gsup_out.imsi)); | ||||
|  | ||||
| 	if (gsup->current_rat_type == OSMO_RAT_EUTRAN_SGS) | ||||
| 		separation_bit = true; | ||||
|  | ||||
| 	rc = db_get_auc(dbc, gsup->imsi, conn->auc_3g_ind, | ||||
| 			gsup_out.auth_vectors, | ||||
| 			ARRAY_SIZE(gsup_out.auth_vectors), | ||||
| 			gsup->rand, gsup->auts); | ||||
| 			gsup->rand, gsup->auts, separation_bit); | ||||
| 	if (rc <= 0) { | ||||
| 		gsup_out.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR; | ||||
| 		switch (rc) { | ||||
| @@ -271,7 +275,7 @@ static int rx_send_auth_info(struct osmo_gsup_conn *conn, | ||||
| 		gsup_out.num_auth_vectors = rc; | ||||
| 	} | ||||
|  | ||||
| 	msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP AUC response"); | ||||
| 	msg_out = osmo_gsup_msgb_alloc("GSUP AUC response"); | ||||
| 	osmo_gsup_encode(msg_out, &gsup_out); | ||||
| 	return osmo_gsup_conn_send(conn, msg_out); | ||||
| } | ||||
| @@ -451,7 +455,7 @@ static int rx_purge_ms_req(struct osmo_gsup_conn *conn, | ||||
| 		gsup_reply.cause = GMM_CAUSE_NET_FAIL; | ||||
| 	} | ||||
|  | ||||
| 	msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP AUC response"); | ||||
| 	msg_out = osmo_gsup_msgb_alloc("GSUP AUC response"); | ||||
| 	osmo_gsup_encode(msg_out, &gsup_reply); | ||||
| 	return osmo_gsup_conn_send(conn, msg_out); | ||||
| } | ||||
| @@ -466,8 +470,7 @@ static int gsup_send_err_reply(struct osmo_gsup_conn *conn, const char *imsi, | ||||
| 	OSMO_STRLCPY_ARRAY(gsup_reply.imsi, imsi); | ||||
| 	gsup_reply.message_type = type_err; | ||||
| 	gsup_reply.cause = err_cause; | ||||
| 	msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP ERR response"); | ||||
| 	OSMO_ASSERT(msg_out); | ||||
| 	msg_out = osmo_gsup_msgb_alloc("GSUP ERR response"); | ||||
| 	osmo_gsup_encode(msg_out, &gsup_reply); | ||||
| 	LOGP(DMAIN, LOGL_NOTICE, "Tx %s\n", osmo_gsup_message_type_name(type_err)); | ||||
| 	return osmo_gsup_conn_send(conn, msg_out); | ||||
| @@ -525,7 +528,7 @@ static int rx_check_imei_req(struct osmo_gsup_conn *conn, const struct osmo_gsup | ||||
| 	/* Accept all IMEIs */ | ||||
| 	gsup_reply.imei_result = OSMO_GSUP_IMEI_RESULT_ACK; | ||||
| 	gsup_reply.message_type = OSMO_GSUP_MSGT_CHECK_IMEI_RESULT; | ||||
| 	msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP Check_IMEI response"); | ||||
| 	msg_out = osmo_gsup_msgb_alloc("GSUP Check_IMEI response"); | ||||
| 	memcpy(gsup_reply.imsi, gsup->imsi, sizeof(gsup_reply.imsi)); | ||||
| 	osmo_gsup_encode(msg_out, &gsup_reply); | ||||
| 	return osmo_gsup_conn_send(conn, msg_out); | ||||
| @@ -591,8 +594,7 @@ static int read_cb_forward(struct osmo_gsup_conn *conn, struct msgb *msg, const | ||||
| end: | ||||
| 	/* Send error back to source */ | ||||
| 	if (ret) { | ||||
| 		struct msgb *msg_err = msgb_alloc_headroom(1024+16, 16, "GSUP forward ERR response"); | ||||
| 		OSMO_ASSERT(msg_err); | ||||
| 		struct msgb *msg_err = osmo_gsup_msgb_alloc("GSUP forward ERR response"); | ||||
| 		gsup_err->message_type = OSMO_GSUP_MSGT_E_ROUTING_ERROR; | ||||
| 		osmo_gsup_encode(msg_err, gsup_err); | ||||
| 		LOGP_GSUP_FWD(gsup_err, LOGL_NOTICE, "Tx %s\n", osmo_gsup_message_type_name(gsup_err->message_type)); | ||||
| @@ -706,6 +708,7 @@ static void print_help() | ||||
| 	printf("  -T --timestamp             Prefix every log line with a timestamp.\n"); | ||||
| 	printf("  -e --log-level number      Set a global loglevel.\n"); | ||||
| 	printf("  -U --db-upgrade            Allow HLR database schema upgrades.\n"); | ||||
| 	printf("  -C --db-check              Quit after opening (and upgrading) the database.\n"); | ||||
| 	printf("  -V --version               Print the version of OsmoHLR.\n"); | ||||
| } | ||||
|  | ||||
| @@ -714,6 +717,7 @@ static struct { | ||||
| 	const char *db_file; | ||||
| 	bool daemonize; | ||||
| 	bool db_upgrade; | ||||
| 	bool db_check; | ||||
| } cmdline_opts = { | ||||
| 	.config_file = "osmo-hlr.cfg", | ||||
| 	.db_file = NULL, | ||||
| @@ -735,6 +739,7 @@ static void handle_options(int argc, char **argv) | ||||
| 			{"log-level", 1, 0, 'e'}, | ||||
| 			{"timestamp", 0, 0, 'T'}, | ||||
| 			{"db-upgrade", 0, 0, 'U' }, | ||||
| 			{"db-check", 0, 0, 'C' }, | ||||
| 			{"version", 0, 0, 'V' }, | ||||
| 			{0, 0, 0, 0} | ||||
| 		}; | ||||
| @@ -773,6 +778,9 @@ static void handle_options(int argc, char **argv) | ||||
| 		case 'U': | ||||
| 			cmdline_opts.db_upgrade = true; | ||||
| 			break; | ||||
| 		case 'C': | ||||
| 			cmdline_opts.db_check = true; | ||||
| 			break; | ||||
| 		case 'V': | ||||
| 			print_version(1); | ||||
| 			exit(0); | ||||
| @@ -784,6 +792,11 @@ static void handle_options(int argc, char **argv) | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (argc > optind) { | ||||
| 		fprintf(stderr, "Unsupported positional arguments on command line\n"); | ||||
| 		exit(2); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void signal_hdlr(int signal) | ||||
| @@ -856,12 +869,6 @@ int main(int argc, char **argv) | ||||
| 		return rc; | ||||
| 	} | ||||
|  | ||||
| 	/* start telnet after reading config for vty_get_bind_addr() */ | ||||
| 	rc = telnet_init_dynif(hlr_ctx, NULL, vty_get_bind_addr(), | ||||
| 			       OSMO_VTY_PORT_HLR); | ||||
| 	if (rc < 0) | ||||
| 		return rc; | ||||
|  | ||||
| 	LOGP(DMAIN, LOGL_NOTICE, "hlr starting\n"); | ||||
|  | ||||
| 	rc = rand_init(); | ||||
| @@ -879,6 +886,23 @@ int main(int argc, char **argv) | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	if (cmdline_opts.db_check) { | ||||
| 		LOGP(DMAIN, LOGL_NOTICE, "Cmdline option --db-check: Database was opened successfully, quitting.\n"); | ||||
| 		db_close(g_hlr->dbc); | ||||
| 		log_fini(); | ||||
| 		talloc_free(hlr_ctx); | ||||
| 		talloc_free(tall_vty_ctx); | ||||
| 		talloc_disable_null_tracking(); | ||||
| 		exit(0); | ||||
| 	} | ||||
|  | ||||
| 	/* start telnet after reading config for vty_get_bind_addr() */ | ||||
| 	rc = telnet_init_dynif(hlr_ctx, NULL, vty_get_bind_addr(), | ||||
| 			       OSMO_VTY_PORT_HLR); | ||||
| 	if (rc < 0) | ||||
| 		return rc; | ||||
|  | ||||
|  | ||||
| 	g_hlr->gs = osmo_gsup_server_create(hlr_ctx, g_hlr->gsup_bind_addr, OSMO_GSUP_PORT, | ||||
| 					    read_cb, &g_lu_ops, g_hlr); | ||||
| 	if (!g_hlr->gs) { | ||||
|   | ||||
| @@ -29,9 +29,9 @@ | ||||
| #include <osmocom/core/logging.h> | ||||
| #include <osmocom/core/application.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "db.h" | ||||
| #include "rand.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/db.h> | ||||
| #include <osmocom/hlr/rand.h> | ||||
|  | ||||
| struct hlr_db_tool_ctx { | ||||
| 	/* DB context */ | ||||
|   | ||||
| @@ -29,12 +29,12 @@ | ||||
| #include <string.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "hlr.h" | ||||
| #include "hlr_ussd.h" | ||||
| #include "gsup_server.h" | ||||
| #include "gsup_router.h" | ||||
| #include "logging.h" | ||||
| #include "db.h" | ||||
| #include <osmocom/hlr/hlr.h> | ||||
| #include <osmocom/hlr/hlr_ussd.h> | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| #include <osmocom/hlr/gsup_router.h> | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/db.h> | ||||
|  | ||||
| /*********************************************************************** | ||||
|  * core data structures expressing config from VTY | ||||
| @@ -317,7 +317,7 @@ static int ss_tx_ussd_7bit(struct ss_session *ss, bool final, uint8_t invoke_id, | ||||
|  * Internal USSD Handlers | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| #include "db.h" | ||||
| #include <osmocom/hlr/db.h> | ||||
|  | ||||
| static int handle_ussd_own_msisdn(struct osmo_gsup_conn *conn, struct ss_session *ss, | ||||
| 				  const struct osmo_gsup_message *gsup, const struct ss_request *req) | ||||
| @@ -464,8 +464,7 @@ static int handle_ussd(struct osmo_gsup_conn *conn, struct ss_session *ss, | ||||
| 	} | ||||
|  | ||||
| 	if (is_euse_originated) { | ||||
| 		msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP USSD FW"); | ||||
| 		OSMO_ASSERT(msg_out); | ||||
| 		msg_out = osmo_gsup_msgb_alloc("GSUP USSD FW"); | ||||
| 		/* Received from EUSE, Forward to VLR */ | ||||
| 		osmo_gsup_encode(msg_out, gsup); | ||||
| 		ss_gsup_send(ss, conn->server, msg_out); | ||||
| @@ -481,8 +480,7 @@ static int handle_ussd(struct osmo_gsup_conn *conn, struct ss_session *ss, | ||||
| 				LOGPSS(ss, LOGL_ERROR, "Cannot find conn for EUSE %s\n", addr); | ||||
| 				ss_tx_error(ss, req->invoke_id, GSM0480_ERR_CODE_SYSTEM_FAILURE); | ||||
| 			} else { | ||||
| 				msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP USSD FW"); | ||||
| 				OSMO_ASSERT(msg_out); | ||||
| 				msg_out = osmo_gsup_msgb_alloc("GSUP USSD FW"); | ||||
| 				osmo_gsup_encode(msg_out, gsup); | ||||
| 				osmo_gsup_conn_send(conn, msg_out); | ||||
| 			} | ||||
|   | ||||
| @@ -33,12 +33,12 @@ | ||||
| #include <osmocom/vty/misc.h> | ||||
| #include <osmocom/abis/ipa.h> | ||||
|  | ||||
| #include "db.h" | ||||
| #include "hlr.h" | ||||
| #include "hlr_vty.h" | ||||
| #include "hlr_vty_subscr.h" | ||||
| #include "hlr_ussd.h" | ||||
| #include "gsup_server.h" | ||||
| #include <osmocom/hlr/db.h> | ||||
| #include <osmocom/hlr/hlr.h> | ||||
| #include <osmocom/hlr/hlr_vty.h> | ||||
| #include <osmocom/hlr/hlr_vty_subscr.h> | ||||
| #include <osmocom/hlr/hlr_ussd.h> | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
|  | ||||
| struct cmd_node hlr_node = { | ||||
| 	HLR_NODE, | ||||
| @@ -150,7 +150,7 @@ DEFUN(cfg_hlr_gsup_bind_ip, | ||||
|  * USSD Entity | ||||
|  ***********************************************************************/ | ||||
|  | ||||
| #include "hlr_ussd.h" | ||||
| #include <osmocom/hlr/hlr_ussd.h> | ||||
|  | ||||
| #define USSD_STR "USSD Configuration\n" | ||||
| #define UROUTE_STR "Routing Configuration\n" | ||||
|   | ||||
| @@ -28,8 +28,8 @@ | ||||
| #include <osmocom/vty/command.h> | ||||
| #include <osmocom/core/utils.h> | ||||
|  | ||||
| #include "hlr.h" | ||||
| #include "db.h" | ||||
| #include <osmocom/hlr/hlr.h> | ||||
| #include <osmocom/hlr/db.h> | ||||
|  | ||||
| struct vty; | ||||
|  | ||||
| @@ -47,12 +47,20 @@ get_datestr(const time_t *t, char *datebuf) | ||||
| 	return s; | ||||
| } | ||||
|  | ||||
| static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t last_lu_seen) | ||||
| { | ||||
| 	char datebuf[26]; /* for ctime_r(3) */ | ||||
| 	if (!last_lu_seen) | ||||
| 		return; | ||||
| 	vty_out(vty, "    last LU seen on %s: %s UTC%s", domain_label, get_datestr(&last_lu_seen, datebuf), | ||||
| 		VTY_NEWLINE); | ||||
| } | ||||
|  | ||||
| static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr) | ||||
| { | ||||
| 	int rc; | ||||
| 	struct osmo_sub_auth_data aud2g; | ||||
| 	struct osmo_sub_auth_data aud3g; | ||||
| 	char datebuf[26]; /* for ctime_r(3) */ | ||||
|  | ||||
| 	vty_out(vty, "    ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE); | ||||
|  | ||||
| @@ -87,8 +95,8 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr) | ||||
| 		vty_out(vty, "    PS disabled%s", VTY_NEWLINE); | ||||
| 	if (subscr->ms_purged_ps) | ||||
| 		vty_out(vty, "    PS purged%s", VTY_NEWLINE); | ||||
| 	if (subscr->last_lu_seen) | ||||
| 		vty_out(vty, "    last LU seen: %s UTC%s", get_datestr(&subscr->last_lu_seen, datebuf), VTY_NEWLINE); | ||||
| 	dump_last_lu_seen(vty, "CS", subscr->last_lu_seen); | ||||
| 	dump_last_lu_seen(vty, "PS", subscr->last_lu_seen_ps); | ||||
|  | ||||
| 	if (!*subscr->imsi) | ||||
| 		return; | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| #include <osmocom/core/utils.h> | ||||
| #include "logging.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
|  | ||||
| const struct log_info_cat hlr_log_info_cat[] = { | ||||
| 	[DMAIN] = { | ||||
|   | ||||
							
								
								
									
										11
									
								
								src/luop.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/luop.c
									
									
									
									
									
								
							| @@ -28,10 +28,10 @@ | ||||
| #include <osmocom/gsm/gsup.h> | ||||
| #include <osmocom/gsm/apn.h> | ||||
|  | ||||
| #include "gsup_server.h" | ||||
| #include "gsup_router.h" | ||||
| #include "logging.h" | ||||
| #include "luop.h" | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
| #include <osmocom/hlr/gsup_router.h> | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/luop.h> | ||||
|  | ||||
| const struct value_string lu_state_names[] = { | ||||
| 	{ LU_S_NULL,			"NULL" }, | ||||
| @@ -50,8 +50,7 @@ static void _luop_tx_gsup(struct lu_operation *luop, | ||||
| { | ||||
| 	struct msgb *msg_out; | ||||
|  | ||||
| 	msg_out = msgb_alloc_headroom(1024+16, 16, "GSUP LUOP"); | ||||
| 	OSMO_ASSERT(msg_out); | ||||
| 	msg_out = osmo_gsup_msgb_alloc("GSUP LUOP"); | ||||
| 	osmo_gsup_encode(msg_out, gsup); | ||||
|  | ||||
| 	osmo_gsup_addr_send(luop->gsup_server, luop->peer, | ||||
|   | ||||
| @@ -44,7 +44,7 @@ | ||||
|  | ||||
| #include <osmocom/gsupclient/gsup_client.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
|  | ||||
| static struct osmo_gsup_client *g_gc; | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ SUBDIRS = \ | ||||
| 	auc \ | ||||
| 	gsup_server \ | ||||
| 	db \ | ||||
| 	gsup \ | ||||
| 	db_upgrade \ | ||||
| 	$(NULL) | ||||
|  | ||||
| # The `:;' works around a Bash 3.2 bug when the output is not writeable. | ||||
| @@ -44,12 +44,14 @@ python-tests: | ||||
| # don't run vty and ctrl tests concurrently so that the ports don't conflict | ||||
| 	$(MAKE) vty-test | ||||
| 	$(MAKE) ctrl-test | ||||
| 	$(MAKE) db-upgrade-equivalence-test | ||||
| else | ||||
| python-tests: | ||||
| 	echo "Not running python-based external tests (determined at configure-time)" | ||||
| endif | ||||
|  | ||||
| VTY_TEST_DB = hlr_vty_test.db | ||||
| VTY_TEST ?= *.vty | ||||
|  | ||||
| # To update the VTY script from current application behavior, | ||||
| # pass -u to vty_script_runner.py by doing: | ||||
| @@ -61,9 +63,8 @@ vty-test: | ||||
| 	osmo_verify_transcript_vty.py -v \ | ||||
| 		-n OsmoHLR -p 4258 \ | ||||
| 		-r "$(top_builddir)/src/osmo-hlr -c $(top_srcdir)/doc/examples/osmo-hlr.cfg -l $(VTY_TEST_DB)" \ | ||||
| 		$(U) $(srcdir)/*.vty | ||||
| 	-rm -f $(VTY_TEST_DB) | ||||
| 	-rm $(VTY_TEST_DB)-* | ||||
| 		$(U) $(srcdir)/$(VTY_TEST) | ||||
| 	-rm -f $(VTY_TEST_DB) $(VTY_TEST_DB)-* | ||||
|  | ||||
| CTRL_TEST_DB = hlr_ctrl_test.db | ||||
|  | ||||
| @@ -81,6 +82,9 @@ ctrl-test: | ||||
| 	-rm -f $(CTRL_TEST_DB) | ||||
| 	-rm $(CTRL_TEST_DB)-* | ||||
|  | ||||
| db-upgrade-equivalence-test: | ||||
| 	$(MAKE) -C db_upgrade upgrade-equivalence-test | ||||
|  | ||||
| check-local: atconfig $(TESTSUITE) | ||||
| 	$(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) | ||||
| 	$(MAKE) $(AM_MAKEFLAGS) python-tests | ||||
|   | ||||
| @@ -2,12 +2,12 @@ SUBDIRS = gen_ts_55_205_test_sets | ||||
|  | ||||
| AM_CPPFLAGS = \ | ||||
| 	$(all_includes) \ | ||||
| 	-I$(top_srcdir)/src \ | ||||
| 	$(NULL) | ||||
|  | ||||
| AM_CFLAGS = \ | ||||
| 	-Wall \ | ||||
| 	-ggdb3 \ | ||||
| 	-I$(top_srcdir)/include \ | ||||
| 	$(LIBOSMOCORE_CFLAGS) \ | ||||
| 	$(LIBOSMOGSM_CFLAGS) \ | ||||
| 	$(NULL) | ||||
|   | ||||
| @@ -29,8 +29,8 @@ | ||||
|  | ||||
| #include <osmocom/crypt/auth.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "auc.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/auc.h> | ||||
|  | ||||
| #define comment_start() fprintf(stderr, "\n===== %s\n", __func__); | ||||
| #define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__); | ||||
|   | ||||
| @@ -33,8 +33,8 @@ | ||||
|  | ||||
| #include <osmocom/crypt/auth.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "auc.h" | ||||
| #include <osmocom/hlr/logging.h> | ||||
| #include <osmocom/hlr/auc.h> | ||||
|  | ||||
| #define comment_start() fprintf(stderr, "\n===== %s\n", __func__); | ||||
| #define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__); | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| #!/usr/bin/env python | ||||
| # FIXME: use python3 once buildslaves are updated. | ||||
| #!/usr/bin/env python3 | ||||
| # Convert test sets pasted from 3GPP TS 55.205 to C code. | ||||
|   | ||||
| # (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| AM_CFLAGS = \ | ||||
| 	$(all_includes) \ | ||||
| 	-I$(top_srcdir)/src \ | ||||
| 	-I$(top_builddir)/src \ | ||||
| 	-I$(top_srcdir)/include \ | ||||
| 	-I$(top_builddir)/include \ | ||||
| 	-Wall \ | ||||
| 	-ggdb3 \ | ||||
| 	$(LIBOSMOCORE_CFLAGS) \ | ||||
|   | ||||
| @@ -27,8 +27,8 @@ | ||||
| #include <osmocom/core/utils.h> | ||||
| #include <osmocom/core/logging.h> | ||||
|  | ||||
| #include "db.h" | ||||
| #include "logging.h" | ||||
| #include <osmocom/hlr/db.h> | ||||
| #include <osmocom/hlr/logging.h> | ||||
|  | ||||
| #define comment_start() fprintf(stderr, "\n===== %s\n", __func__); | ||||
| #define comment(fmt, args...) fprintf(stderr, "\n--- " fmt "\n\n", ## args); | ||||
| @@ -115,7 +115,7 @@ static void _fill_invalid(void *dest, size_t size) | ||||
| #define ASSERT_DB_GET_AUC(imsi, expect_rc) \ | ||||
| 	do { \ | ||||
| 		struct osmo_auth_vector vec[N_VECTORS]; \ | ||||
| 		ASSERT_RC(db_get_auc(dbc, imsi, 3, vec, N_VECTORS, NULL, NULL), expect_rc); \ | ||||
| 		ASSERT_RC(db_get_auc(dbc, imsi, 3, vec, N_VECTORS, NULL, NULL, false), expect_rc); \ | ||||
| 	} while (0) | ||||
|  | ||||
| /* Not linking the real auc_compute_vectors(), just returning num_vec. | ||||
|   | ||||
| @@ -814,7 +814,7 @@ db_get_auth_data(dbc, unknown_imsi, &g_aud2g, &g_aud3g, &g_id) --> -2 | ||||
| DAUC IMSI='999999999': No such subscriber | ||||
|  | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> -2 | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> -2 | ||||
| DAUC IMSI='123456789000000': No such subscriber | ||||
|  | ||||
|  | ||||
| @@ -833,7 +833,7 @@ DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> -ENOKEY | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> -ENOKEY | ||||
| DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
| @@ -852,7 +852,7 @@ DAUC IMSI='123456789000000': No 3G Auth Data | ||||
| } | ||||
| 3G: none | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> 3 | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> 3 | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
| DAUC IMSI='123456789000000': Calling to generate 3 vectors | ||||
| DAUC IMSI='123456789000000': Generated 3 vectors | ||||
| @@ -915,7 +915,7 @@ DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> -ENOKEY | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> -ENOKEY | ||||
| DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
| @@ -940,7 +940,7 @@ DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> -ENOKEY | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> -ENOKEY | ||||
| DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
| @@ -963,7 +963,7 @@ DAUC IMSI='123456789000000': No 2G Auth Data | ||||
|   .u.umts.ind_bitlen = 5, | ||||
| } | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> 3 | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> 3 | ||||
| DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': Calling to generate 3 vectors | ||||
| DAUC IMSI='123456789000000': Generated 3 vectors | ||||
| @@ -1042,7 +1042,7 @@ DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> -ENOKEY | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> -ENOKEY | ||||
| DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
| @@ -1064,7 +1064,7 @@ DAUC IMSI='123456789000000': No 2G Auth Data | ||||
|   .u.umts.ind_bitlen = 5, | ||||
| } | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> 3 | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> 3 | ||||
| DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': Calling to generate 3 vectors | ||||
| DAUC IMSI='123456789000000': Generated 3 vectors | ||||
| @@ -1077,7 +1077,7 @@ DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> -ENOKEY | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> -ENOKEY | ||||
| DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
| @@ -1105,7 +1105,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0 | ||||
|   .u.umts.ind_bitlen = 5, | ||||
| } | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> 3 | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> 3 | ||||
| DAUC IMSI='123456789000000': Calling to generate 3 vectors | ||||
| DAUC IMSI='123456789000000': Generated 3 vectors | ||||
| DAUC IMSI='123456789000000': Updating SQN=0 in DB | ||||
| @@ -1323,7 +1323,7 @@ DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> -ENOKEY | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> -ENOKEY | ||||
| DAUC IMSI='123456789000000': No 2G Auth Data | ||||
| DAUC IMSI='123456789000000': No 3G Auth Data | ||||
|  | ||||
| @@ -1332,7 +1332,7 @@ db_subscr_delete_by_id(dbc, id) --> 0 | ||||
| db_subscr_get_by_imsi(dbc, imsi0, &g_subscr) --> -ENOENT | ||||
| DAUC Cannot read subscriber from db: IMSI='123456789000000': No such subscriber | ||||
|  | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL) --> -2 | ||||
| db_get_auc(dbc, imsi0, 3, vec, N_VECTORS, NULL, NULL, false) --> -2 | ||||
| DAUC IMSI='123456789000000': No such subscriber | ||||
|  | ||||
| ===== test_subscr_aud: SUCCESS | ||||
|   | ||||
							
								
								
									
										14
									
								
								tests/db_upgrade/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/db_upgrade/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| EXTRA_DIST = \ | ||||
| 	db_upgrade_test.sh \ | ||||
| 	db_upgrade_test.err \ | ||||
| 	db_upgrade_test.ok \ | ||||
| 	hlr_db_v0.sql \ | ||||
| 	osmo-hlr.cfg \ | ||||
| 	create_subscribers.vty \ | ||||
| 	$(NULL) | ||||
|  | ||||
| update_exp: | ||||
| 	$(srcdir)/db_upgrade_test.sh $(srcdir) $(builddir) >"$(srcdir)/db_upgrade_test.ok" 2>"$(srcdir)/db_upgrade_test.err" | ||||
|  | ||||
| upgrade-equivalence-test: | ||||
| 	$(srcdir)/db_upgrade_test.sh $(srcdir) $(builddir) do-equivalence-test | ||||
							
								
								
									
										47
									
								
								tests/db_upgrade/create_subscribers.vty
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								tests/db_upgrade/create_subscribers.vty
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| OsmoHLR> enable | ||||
| OsmoHLR# subscriber imsi 123456789012345 create | ||||
| % Created subscriber 123456789012345 | ||||
|     ID: 1 | ||||
|     IMSI: 123456789012345 | ||||
|     MSISDN: none | ||||
| OsmoHLR# subscriber imsi 123456789012345 update msisdn 098765432109876 | ||||
| % Updated subscriber IMSI='123456789012345' to MSISDN='098765432109876' | ||||
| OsmoHLR# subscriber imsi 123456789012345 update aud2g comp128v1 ki BeefedCafeFaceAcedAddedDecadeFee | ||||
| OsmoHLR# subscriber imsi 123456789012345 update aud3g milenage k C01ffedC1cadaeAc1d1f1edAcac1aB0a opc CededEffacedAceFacedBadFadedBeef | ||||
| OsmoHLR# subscriber imsi 111111111 create | ||||
| % Created subscriber 111111111 | ||||
|     ID: 2 | ||||
|     IMSI: 111111111 | ||||
|     MSISDN: none | ||||
| OsmoHLR# subscriber imsi 222222222 create | ||||
| % Created subscriber 222222222 | ||||
|     ID: 3 | ||||
|     IMSI: 222222222 | ||||
|     MSISDN: none | ||||
| OsmoHLR# subscriber imsi 222222222 update msisdn 22222 | ||||
| % Updated subscriber IMSI='222222222' to MSISDN='22222' | ||||
| OsmoHLR# subscriber imsi 333333 create | ||||
| % Created subscriber 333333 | ||||
|     ID: 4 | ||||
|     IMSI: 333333 | ||||
|     MSISDN: none | ||||
| OsmoHLR# subscriber imsi 333333 update msisdn 3 | ||||
| % Updated subscriber IMSI='333333' to MSISDN='3' | ||||
| OsmoHLR# subscriber imsi 333333 update aud2g comp128v2 ki 33333333333333333333333333333333 | ||||
| OsmoHLR# subscriber imsi 444444444444444 create | ||||
| % Created subscriber 444444444444444 | ||||
|     ID: 5 | ||||
|     IMSI: 444444444444444 | ||||
|     MSISDN: none | ||||
| OsmoHLR# subscriber imsi 444444444444444 update msisdn 4444 | ||||
| % Updated subscriber IMSI='444444444444444' to MSISDN='4444' | ||||
| OsmoHLR# subscriber imsi 444444444444444 update aud3g milenage k 44444444444444444444444444444444 op 44444444444444444444444444444444 | ||||
| OsmoHLR# subscriber imsi 5555555 create | ||||
| % Created subscriber 5555555 | ||||
|     ID: 6 | ||||
|     IMSI: 5555555 | ||||
|     MSISDN: none | ||||
| OsmoHLR# subscriber imsi 5555555 update msisdn 55555555555555 | ||||
| % Updated subscriber IMSI='5555555' to MSISDN='55555555555555' | ||||
| OsmoHLR# subscriber imsi 5555555 update aud2g xor ki 55555555555555555555555555555555 | ||||
| OsmoHLR# subscriber imsi 5555555 update aud3g milenage k 55555555555555555555555555555555 opc 55555555555555555555555555555555 | ||||
							
								
								
									
										6
									
								
								tests/db_upgrade/create_subscribers_step2.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/db_upgrade/create_subscribers_step2.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| update subscriber set vlr_number = 'MSC-1' where id = 1; | ||||
| update subscriber set ms_purged_cs = 1 where id = 2; | ||||
| update subscriber set ms_purged_ps = 1 where id = 3; | ||||
| update subscriber set nam_cs = 0 where id = 4; | ||||
| update subscriber set nam_ps = 0 where id = 5; | ||||
| update subscriber set nam_cs = 0, nam_ps = 0 where id = 6; | ||||
							
								
								
									
										0
									
								
								tests/db_upgrade/db_upgrade_test.err
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/db_upgrade/db_upgrade_test.err
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										172
									
								
								tests/db_upgrade/db_upgrade_test.ok
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								tests/db_upgrade/db_upgrade_test.ok
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,172 @@ | ||||
| Creating db in schema version 0 | ||||
|  | ||||
| Version 0 db: | ||||
|  | ||||
| Table: auc_2g | ||||
| name|type|notnull|dflt_value|pk | ||||
| algo_id_2g|INTEGER|1||0 | ||||
| ki|VARCHAR(32)|1||0 | ||||
| subscriber_id|INTEGER|0||1 | ||||
|  | ||||
| Table auc_2g contents: | ||||
| algo_id_2g|ki|subscriber_id | ||||
| 1|BeefedCafeFaceAcedAddedDecadeFee|1 | ||||
| 2|33333333333333333333333333333333|4 | ||||
| 4|55555555555555555555555555555555|6 | ||||
|  | ||||
| Table: auc_3g | ||||
| name|type|notnull|dflt_value|pk | ||||
| algo_id_3g|INTEGER|1||0 | ||||
| ind_bitlen|INTEGER|1|5|0 | ||||
| k|VARCHAR(32)|1||0 | ||||
| op|VARCHAR(32)|0||0 | ||||
| opc|VARCHAR(32)|0||0 | ||||
| sqn|INTEGER|1|0|0 | ||||
| subscriber_id|INTEGER|0||1 | ||||
|  | ||||
| Table auc_3g contents: | ||||
| algo_id_3g|ind_bitlen|k|op|opc|sqn|subscriber_id | ||||
| 5|5|C01ffedC1cadaeAc1d1f1edAcac1aB0a||CededEffacedAceFacedBadFadedBeef|0|1 | ||||
| 5|5|44444444444444444444444444444444|44444444444444444444444444444444||0|5 | ||||
| 5|5|55555555555555555555555555555555||55555555555555555555555555555555|0|6 | ||||
|  | ||||
| Table: subscriber | ||||
| name|type|notnull|dflt_value|pk | ||||
| ggsn_number|VARCHAR(15)|0||0 | ||||
| gmlc_number|VARCHAR(15)|0||0 | ||||
| hlr_number|VARCHAR(15)|0||0 | ||||
| id|INTEGER|0||1 | ||||
| imeisv|VARCHAR|0||0 | ||||
| imsi|VARCHAR(15)|1||0 | ||||
| lmsi|INTEGER|0||0 | ||||
| ms_purged_cs|BOOLEAN|1|0|0 | ||||
| ms_purged_ps|BOOLEAN|1|0|0 | ||||
| msisdn|VARCHAR(15)|0||0 | ||||
| nam_cs|BOOLEAN|1|1|0 | ||||
| nam_ps|BOOLEAN|1|1|0 | ||||
| periodic_lu_tmr|INTEGER|0||0 | ||||
| periodic_rau_tau_tmr|INTEGER|0||0 | ||||
| sgsn_address|VARCHAR|0||0 | ||||
| sgsn_number|VARCHAR(15)|0||0 | ||||
| smsc_number|VARCHAR(15)|0||0 | ||||
| vlr_number|VARCHAR(15)|0||0 | ||||
|  | ||||
| Table subscriber contents: | ||||
| ggsn_number|gmlc_number|hlr_number|id|imeisv|imsi|lmsi|ms_purged_cs|ms_purged_ps|msisdn|nam_cs|nam_ps|periodic_lu_tmr|periodic_rau_tau_tmr|sgsn_address|sgsn_number|smsc_number|vlr_number | ||||
| |||1||123456789012345||0|0|098765432109876|1|1||||||MSC-1 | ||||
| |||2||111111111||1|0||1|1|||||| | ||||
| |||3||222222222||0|1|22222|1|1|||||| | ||||
| |||4||333333||0|0|3|0|1|||||| | ||||
| |||5||444444444444444||0|0|4444|1|0|||||| | ||||
| |||6||5555555||0|0|55555555555555|0|0|||||| | ||||
|  | ||||
| Table: subscriber_apn | ||||
| name|type|notnull|dflt_value|pk | ||||
| apn|VARCHAR(256)|1||0 | ||||
| subscriber_id|INTEGER|0||0 | ||||
|  | ||||
| Table subscriber_apn contents: | ||||
|  | ||||
| Table: subscriber_multi_msisdn | ||||
| name|type|notnull|dflt_value|pk | ||||
| msisdn|VARCHAR(15)|1||0 | ||||
| subscriber_id|INTEGER|0||0 | ||||
|  | ||||
| Table subscriber_multi_msisdn contents: | ||||
|  | ||||
| Launching osmo-hlr to upgrade db: | ||||
| osmo-hlr --database $db --db-upgrade --db-check --config-file $srcdir/osmo-hlr.cfg | ||||
| rc = 0 | ||||
| DMAIN hlr starting | ||||
| DDB using database: <PATH>test.db | ||||
| DDB Database <PATH>test.db' has HLR DB schema version 0 | ||||
| DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 1 | ||||
| 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 4 | ||||
| DMAIN Cmdline option --db-check: Database was opened successfully, quitting. | ||||
|  | ||||
| Resulting db: | ||||
|  | ||||
| Table: auc_2g | ||||
| name|type|notnull|dflt_value|pk | ||||
| algo_id_2g|INTEGER|1||0 | ||||
| ki|VARCHAR(32)|1||0 | ||||
| subscriber_id|INTEGER|0||1 | ||||
|  | ||||
| Table auc_2g contents: | ||||
| algo_id_2g|ki|subscriber_id | ||||
| 1|BeefedCafeFaceAcedAddedDecadeFee|1 | ||||
| 2|33333333333333333333333333333333|4 | ||||
| 4|55555555555555555555555555555555|6 | ||||
|  | ||||
| Table: auc_3g | ||||
| name|type|notnull|dflt_value|pk | ||||
| algo_id_3g|INTEGER|1||0 | ||||
| ind_bitlen|INTEGER|1|5|0 | ||||
| k|VARCHAR(32)|1||0 | ||||
| op|VARCHAR(32)|0||0 | ||||
| opc|VARCHAR(32)|0||0 | ||||
| sqn|INTEGER|1|0|0 | ||||
| subscriber_id|INTEGER|0||1 | ||||
|  | ||||
| Table auc_3g contents: | ||||
| algo_id_3g|ind_bitlen|k|op|opc|sqn|subscriber_id | ||||
| 5|5|C01ffedC1cadaeAc1d1f1edAcac1aB0a||CededEffacedAceFacedBadFadedBeef|0|1 | ||||
| 5|5|44444444444444444444444444444444|44444444444444444444444444444444||0|5 | ||||
| 5|5|55555555555555555555555555555555||55555555555555555555555555555555|0|6 | ||||
|  | ||||
| Table: subscriber | ||||
| name|type|notnull|dflt_value|pk | ||||
| ggsn_number|VARCHAR(15)|0||0 | ||||
| gmlc_number|VARCHAR(15)|0||0 | ||||
| id|INTEGER|0||1 | ||||
| imei|VARCHAR(14)|0||0 | ||||
| imeisv|VARCHAR|0||0 | ||||
| imsi|VARCHAR(15)|1||0 | ||||
| last_lu_seen|TIMESTAMP|0|NULL|0 | ||||
| last_lu_seen_ps|TIMESTAMP|0|NULL|0 | ||||
| lmsi|INTEGER|0||0 | ||||
| ms_purged_cs|BOOLEAN|1|0|0 | ||||
| ms_purged_ps|BOOLEAN|1|0|0 | ||||
| msc_number|VARCHAR(15)|0||0 | ||||
| msisdn|VARCHAR(15)|0||0 | ||||
| nam_cs|BOOLEAN|1|1|0 | ||||
| nam_ps|BOOLEAN|1|1|0 | ||||
| periodic_lu_tmr|INTEGER|0||0 | ||||
| periodic_rau_tau_tmr|INTEGER|0||0 | ||||
| sgsn_address|VARCHAR|0||0 | ||||
| sgsn_number|VARCHAR(15)|0||0 | ||||
| smsc_number|VARCHAR(15)|0||0 | ||||
| vlr_number|VARCHAR(15)|0||0 | ||||
|  | ||||
| Table subscriber contents: | ||||
| ggsn_number|gmlc_number|id|imei|imeisv|imsi|last_lu_seen|last_lu_seen_ps|lmsi|ms_purged_cs|ms_purged_ps|msc_number|msisdn|nam_cs|nam_ps|periodic_lu_tmr|periodic_rau_tau_tmr|sgsn_address|sgsn_number|smsc_number|vlr_number | ||||
| ||1|||123456789012345||||0|0||098765432109876|1|1||||||MSC-1 | ||||
| ||2|||111111111||||1|0|||1|1|||||| | ||||
| ||3|||222222222||||0|1||22222|1|1|||||| | ||||
| ||4|||333333||||0|0||3|0|1|||||| | ||||
| ||5|||444444444444444||||0|0||4444|1|0|||||| | ||||
| ||6|||5555555||||0|0||55555555555555|0|0|||||| | ||||
|  | ||||
| Table: subscriber_apn | ||||
| name|type|notnull|dflt_value|pk | ||||
| apn|VARCHAR(256)|1||0 | ||||
| subscriber_id|INTEGER|0||0 | ||||
|  | ||||
| Table subscriber_apn contents: | ||||
|  | ||||
| Table: subscriber_multi_msisdn | ||||
| name|type|notnull|dflt_value|pk | ||||
| msisdn|VARCHAR(15)|1||0 | ||||
| subscriber_id|INTEGER|0||0 | ||||
|  | ||||
| Table subscriber_multi_msisdn contents: | ||||
|  | ||||
| Verify that osmo-hlr can open it: | ||||
| osmo-hlr --database $db --db-check --config-file $srcdir/osmo-hlr.cfg | ||||
| rc = 0 | ||||
| DMAIN hlr starting | ||||
| DDB using database: <PATH>test.db | ||||
| DDB Database <PATH>test.db' has HLR DB schema version 4 | ||||
| DMAIN Cmdline option --db-check: Database was opened successfully, quitting. | ||||
							
								
								
									
										83
									
								
								tests/db_upgrade/db_upgrade_test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										83
									
								
								tests/db_upgrade/db_upgrade_test.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| #!/bin/sh | ||||
| srcdir="${1:-.}" | ||||
| builddir="${2:-.}" | ||||
| do_equivalence_test="$3" | ||||
|  | ||||
| set -e | ||||
|  | ||||
| db="$builddir/test.db" | ||||
| osmo_hlr="$builddir/../../src/osmo-hlr" | ||||
| cfg="$srcdir/osmo-hlr.cfg" | ||||
|  | ||||
| dump_sorted_schema(){ | ||||
| 	db_file="$1" | ||||
| 	tables="$(sqlite3 -batch -noheader "$db_file" "SELECT name FROM sqlite_master WHERE type = 'table' order by name")" | ||||
| 	for table in $tables; do | ||||
| 		echo | ||||
| 		echo "Table: $table" | ||||
| 		sqlite3 -batch -header "$db_file" "SELECT name,type,\"notnull\",dflt_value,pk FROM PRAGMA_TABLE_INFO('$table') order by name;" | ||||
| 		echo | ||||
| 		echo "Table $table contents:" | ||||
| 		columns="$(sqlite3 -batch -noheader "$db_file" "SELECT name FROM PRAGMA_TABLE_INFO('$table') order by name;")" | ||||
| 		sqlite3 -batch -header "$db_file" "SELECT $(echo $columns | sed 's/ /,/g') from $table;" | ||||
| 	done | ||||
| } | ||||
|  | ||||
| rm -f "$db" | ||||
| echo "Creating db in schema version 0" | ||||
| sqlite3 -batch "$db" < "$srcdir/hlr_db_v0.sql" | ||||
|  | ||||
| echo | ||||
| echo "Version 0 db:" | ||||
| dump_sorted_schema "$db" | ||||
|  | ||||
| set +e | ||||
|  | ||||
| echo | ||||
| echo "Launching osmo-hlr to upgrade db:" | ||||
| echo osmo-hlr --database '$db' --db-upgrade --db-check --config-file '$srcdir/osmo-hlr.cfg' | ||||
| "$osmo_hlr" --database "$db" --db-upgrade --db-check --config-file "$cfg" >log 2>&1 | ||||
| echo "rc = $?" | ||||
| cat log | sed 's@[^ "]*/@<PATH>@g' | ||||
|  | ||||
| echo | ||||
| echo "Resulting db:" | ||||
| dump_sorted_schema "$db" | ||||
|  | ||||
| echo | ||||
| echo "Verify that osmo-hlr can open it:" | ||||
| echo osmo-hlr --database '$db' --db-check --config-file '$srcdir/osmo-hlr.cfg' | ||||
| "$osmo_hlr" --database "$db" --db-check --config-file "$cfg" >log 2>&1 | ||||
| echo "rc = $?" | ||||
| cat log | sed 's@[^ "]*/@<PATH>@g' | ||||
|  | ||||
| if [ -n "$do_equivalence_test" ]; then | ||||
| 	# this part requires osmo_interact_vty.py, so this test is not part of the normal run | ||||
| 	set -e -x | ||||
| 	mint_db="$builddir/mint.db" | ||||
| 	rm -f "$mint_db" | ||||
|  | ||||
| 	osmo_verify_transcript_vty.py -v \ | ||||
| 		-n OsmoHLR -p 4258 \ | ||||
| 		-r "$osmo_hlr -c $cfg -l $mint_db" \ | ||||
| 		"$srcdir/create_subscribers.vty" | ||||
| 	sqlite3 -batch "$mint_db" < "$srcdir/create_subscribers_step2.sql" | ||||
|  | ||||
| 	set +x | ||||
| 	test_dump="$builddir/test.dump" | ||||
| 	mint_dump="$builddir/mint.dump" | ||||
|  | ||||
| 	dump_sorted_schema "$db" > "$test_dump" | ||||
| 	dump_sorted_schema "$mint_db" > "$mint_dump" | ||||
|  | ||||
| 	echo | ||||
| 	echo "Newly created sorted schema is:" | ||||
| 	cat "$mint_dump" | ||||
| 	echo | ||||
| 	echo "Diff to upgraded schema:" | ||||
| 	diff -u "$mint_dump" "$test_dump" | ||||
| 	echo "rc=$?" | ||||
| fi | ||||
|  | ||||
| rm -f log | ||||
| rm -f "$db" | ||||
							
								
								
									
										80
									
								
								tests/db_upgrade/hlr_db_v0.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								tests/db_upgrade/hlr_db_v0.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| PRAGMA foreign_keys=OFF; | ||||
| BEGIN TRANSACTION; | ||||
| CREATE TABLE subscriber ( | ||||
| -- OsmoHLR's DB scheme is modelled roughly after TS 23.008 version 13.3.0 | ||||
| 	id		INTEGER PRIMARY KEY, | ||||
| 	-- Chapter 2.1.1.1 | ||||
| 	imsi		VARCHAR(15) UNIQUE NOT NULL, | ||||
| 	-- Chapter 2.1.2 | ||||
| 	msisdn		VARCHAR(15) UNIQUE, | ||||
| 	-- Chapter 2.2.3: Most recent / current IMEI | ||||
| 	imeisv		VARCHAR, | ||||
| 	-- Chapter 2.4.5 | ||||
| 	vlr_number	VARCHAR(15), | ||||
| 	-- Chapter 2.4.6 | ||||
| 	hlr_number	VARCHAR(15), | ||||
| 	-- Chapter 2.4.8.1 | ||||
| 	sgsn_number	VARCHAR(15), | ||||
| 	-- Chapter 2.13.10 | ||||
| 	sgsn_address	VARCHAR, | ||||
| 	-- Chapter 2.4.8.2 | ||||
| 	ggsn_number	VARCHAR(15), | ||||
| 	-- Chapter 2.4.9.2 | ||||
| 	gmlc_number	VARCHAR(15), | ||||
| 	-- Chapter 2.4.23 | ||||
| 	smsc_number	VARCHAR(15), | ||||
| 	-- Chapter 2.4.24 | ||||
| 	periodic_lu_tmr	INTEGER, | ||||
| 	-- Chapter 2.13.115 | ||||
| 	periodic_rau_tau_tmr INTEGER, | ||||
| 	-- Chapter 2.1.1.2: network access mode | ||||
| 	nam_cs		BOOLEAN NOT NULL DEFAULT 1, | ||||
| 	nam_ps		BOOLEAN NOT NULL DEFAULT 1, | ||||
| 	-- Chapter 2.1.8 | ||||
| 	lmsi		INTEGER, | ||||
| 	-- The below purged flags might not even be stored non-volatile, | ||||
| 	-- refer to TS 23.012 Chapter 3.6.1.4 | ||||
| 	-- Chapter 2.7.5 | ||||
| 	ms_purged_cs	BOOLEAN NOT NULL DEFAULT 0, | ||||
| 	-- Chapter 2.7.6 | ||||
| 	ms_purged_ps	BOOLEAN NOT NULL DEFAULT 0 | ||||
| ); | ||||
| INSERT INTO subscriber VALUES(1,'123456789012345','098765432109876',NULL,'MSC-1',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,1,NULL,0,0); | ||||
| INSERT INTO subscriber VALUES(2,'111111111',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,1,NULL,1,0); | ||||
| INSERT INTO subscriber VALUES(3,'222222222','22222',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,1,NULL,0,1); | ||||
| INSERT INTO subscriber VALUES(4,'333333','3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,1,NULL,0,0); | ||||
| INSERT INTO subscriber VALUES(5,'444444444444444','4444',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,0,NULL,0,0); | ||||
| INSERT INTO subscriber VALUES(6,'5555555','55555555555555',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,NULL,0,0); | ||||
| CREATE TABLE subscriber_apn ( | ||||
| 	subscriber_id	INTEGER,		-- subscriber.id | ||||
| 	apn		VARCHAR(256) NOT NULL | ||||
| ); | ||||
| CREATE TABLE subscriber_multi_msisdn ( | ||||
| -- Chapter 2.1.3 | ||||
| 	subscriber_id	INTEGER,		-- subscriber.id | ||||
| 	msisdn		VARCHAR(15) NOT NULL | ||||
| ); | ||||
| CREATE TABLE auc_2g ( | ||||
| 	subscriber_id	INTEGER PRIMARY KEY,	-- subscriber.id | ||||
| 	algo_id_2g	INTEGER NOT NULL,	-- enum osmo_auth_algo value | ||||
| 	ki		VARCHAR(32) NOT NULL	-- hex string: subscriber's secret key (128bit) | ||||
| ); | ||||
| INSERT INTO auc_2g VALUES(1,1,'BeefedCafeFaceAcedAddedDecadeFee'); | ||||
| INSERT INTO auc_2g VALUES(4,2,'33333333333333333333333333333333'); | ||||
| INSERT INTO auc_2g VALUES(6,4,'55555555555555555555555555555555'); | ||||
| CREATE TABLE auc_3g ( | ||||
| 	subscriber_id	INTEGER PRIMARY KEY,	-- subscriber.id | ||||
| 	algo_id_3g	INTEGER NOT NULL,	-- enum osmo_auth_algo value | ||||
| 	k		VARCHAR(32) NOT NULL,	-- hex string: subscriber's secret key (128bit) | ||||
| 	op		VARCHAR(32),		-- hex string: operator's secret key (128bit) | ||||
| 	opc		VARCHAR(32),		-- hex string: derived from OP and K (128bit) | ||||
| 	sqn		INTEGER NOT NULL DEFAULT 0,	-- sequence number of key usage | ||||
| 	-- nr of index bits at lower SQN end | ||||
| 	ind_bitlen	INTEGER NOT NULL DEFAULT 5 | ||||
| ); | ||||
| INSERT INTO auc_3g VALUES(1,5,'C01ffedC1cadaeAc1d1f1edAcac1aB0a',NULL,'CededEffacedAceFacedBadFadedBeef',0,5); | ||||
| INSERT INTO auc_3g VALUES(5,5,'44444444444444444444444444444444','44444444444444444444444444444444',NULL,0,5); | ||||
| INSERT INTO auc_3g VALUES(6,5,'55555555555555555555555555555555',NULL,'55555555555555555555555555555555',0,5); | ||||
| CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi) | ||||
| ; | ||||
| COMMIT; | ||||
							
								
								
									
										6
									
								
								tests/db_upgrade/osmo-hlr.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tests/db_upgrade/osmo-hlr.cfg
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| log stderr | ||||
|  logging level db notice | ||||
|  logging print category-hex 0 | ||||
|  logging print file 0 | ||||
|  logging print category 1 | ||||
|  logging color 0 | ||||
| @@ -1,42 +0,0 @@ | ||||
| AM_CPPFLAGS = \ | ||||
| 	$(all_includes) \ | ||||
| 	-I$(top_srcdir)/src \ | ||||
| 	$(NULL) | ||||
|  | ||||
| AM_CFLAGS = \ | ||||
| 	-Wall \ | ||||
| 	-ggdb3 \ | ||||
| 	$(LIBOSMOCORE_CFLAGS) \ | ||||
| 	$(LIBOSMOGSM_CFLAGS) \ | ||||
| 	$(LIBOSMOABIS_CFLAGS) \ | ||||
| 	$(NULL) | ||||
|  | ||||
| AM_LDFLAGS = \ | ||||
| 	-no-install \ | ||||
| 	$(NULL) | ||||
|  | ||||
| EXTRA_DIST = \ | ||||
| 	gsup_test.ok \ | ||||
| 	gsup_test.err \ | ||||
| 	$(NULL) | ||||
|  | ||||
| noinst_PROGRAMS = \ | ||||
| 	gsup_test \ | ||||
| 	$(NULL) | ||||
|  | ||||
| gsup_test_SOURCES = \ | ||||
| 	gsup_test.c \ | ||||
| 	$(NULL) | ||||
|  | ||||
| gsup_test_LDADD = \ | ||||
| 	$(top_srcdir)/src/luop.c \ | ||||
| 	$(top_srcdir)/src/gsup_server.c \ | ||||
| 	$(top_srcdir)/src/gsup_router.c \ | ||||
| 	$(LIBOSMOCORE_LIBS) \ | ||||
| 	$(LIBOSMOGSM_LIBS) \ | ||||
| 	$(LIBOSMOABIS_LIBS) \ | ||||
| 	$(NULL) | ||||
|  | ||||
| .PHONY: update_exp | ||||
| update_exp: | ||||
| 	$(builddir)/gsup_test >"$(srcdir)/gsup_test.ok" 2>"$(srcdir)/gsup_test.err" | ||||
| @@ -1,91 +0,0 @@ | ||||
| /* (C) 2018 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> | ||||
|  * | ||||
|  * All Rights Reserved | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU Affero General Public License as published by | ||||
|  * the Free Software Foundation; either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU Affero General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Affero General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include <osmocom/core/logging.h> | ||||
| #include <osmocom/core/utils.h> | ||||
| #include <osmocom/core/application.h> | ||||
| #include <osmocom/gsm/gsup.h> | ||||
|  | ||||
| #include "logging.h" | ||||
| #include "luop.h" | ||||
|  | ||||
| struct osmo_gsup_server; | ||||
|  | ||||
| /* override osmo_gsup_addr_send() to not actually send anything. */ | ||||
| int osmo_gsup_addr_send(struct osmo_gsup_server *gs, | ||||
| 			const uint8_t *addr, size_t addrlen, | ||||
| 			struct msgb *msg) | ||||
| { | ||||
| 	LOGP(DMAIN, LOGL_DEBUG, "%s\n", msgb_hexdump(msg)); | ||||
| 	msgb_free(msg); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int db_subscr_get_by_imsi(struct db_context *dbc, const char *imsi, | ||||
| 			  struct hlr_subscriber *subscr) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| /* Verify that the internally allocated msgb is large enough */ | ||||
| void test_gsup_tx_insert_subscr_data() | ||||
| { | ||||
| 	struct lu_operation luop = { | ||||
| 		.state = LU_S_LU_RECEIVED, | ||||
| 		.subscr = { | ||||
| 			.imsi = "123456789012345", | ||||
| 			.msisdn = "987654321098765", | ||||
| 			.nam_cs = true, | ||||
| 			.nam_ps = true, | ||||
| 		}, | ||||
| 		.is_ps = true, | ||||
| 	}; | ||||
|  | ||||
| 	lu_op_tx_insert_subscr_data(&luop); | ||||
| } | ||||
|  | ||||
| const struct log_info_cat default_categories[] = { | ||||
| 	[DMAIN] = { | ||||
| 		.name = "DMAIN", | ||||
| 		.description = "Main Program", | ||||
| 		.enabled = 1, .loglevel = LOGL_DEBUG, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| static struct log_info info = { | ||||
| 	.cat = default_categories, | ||||
| 	.num_cat = ARRAY_SIZE(default_categories), | ||||
| }; | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
| 	void *ctx = talloc_named_const(NULL, 0, "gsup_test"); | ||||
| 	osmo_init_logging2(ctx, &info); | ||||
| 	log_set_print_filename(osmo_stderr_target, 0); | ||||
| 	log_set_print_timestamp(osmo_stderr_target, 0); | ||||
| 	log_set_use_color(osmo_stderr_target, 0); | ||||
| 	log_set_print_category(osmo_stderr_target, 1); | ||||
|  | ||||
| 	test_gsup_tx_insert_subscr_data(); | ||||
|  | ||||
| 	printf("Done.\n"); | ||||
| 	return EXIT_SUCCESS; | ||||
| } | ||||
| @@ -1,2 +0,0 @@ | ||||
| DMAIN 10 01 08 21 43 65 87 09 21 43 f5 08 09 08 89 67 45 23 01 89 67 f5 05 07 10 01 01 12 02 01 2a 28 01 01  | ||||
| DMAIN LU OP state change: LU RECEIVED -> ISD SENT | ||||
| @@ -1 +0,0 @@ | ||||
| Done. | ||||
| @@ -1,11 +1,11 @@ | ||||
| AM_CPPFLAGS = \ | ||||
| 	$(all_includes) \ | ||||
| 	-I$(top_srcdir)/src \ | ||||
| 	$(NULL) | ||||
|  | ||||
| AM_CFLAGS = \ | ||||
| 	-Wall \ | ||||
| 	-ggdb3 \ | ||||
| 	-I$(top_srcdir)/include \ | ||||
| 	$(LIBOSMOCORE_CFLAGS) \ | ||||
| 	$(LIBOSMOGSM_CFLAGS) \ | ||||
| 	$(LIBOSMOABIS_CFLAGS) \ | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <osmocom/core/utils.h> | ||||
| #include "gsup_server.h" | ||||
| #include <osmocom/hlr/gsup_server.h> | ||||
|  | ||||
| #define comment_start() printf("\n===== %s\n", __func__) | ||||
| #define comment_end() printf("===== %s: SUCCESS\n\n", __func__) | ||||
|   | ||||
| @@ -1,3 +1,15 @@ | ||||
| OsmoHLR> ? | ||||
|   show        Show running system information | ||||
|   list        Print command list | ||||
|   exit        Exit current mode and down to previous mode | ||||
|   help        Description of the interactive help system | ||||
|   enable      Turn on privileged mode command | ||||
|   terminal    Set terminal line parameters | ||||
|   who         Display who is on vty | ||||
|   logging     Configure logging | ||||
|   no          Negate a command or set its defaults | ||||
|   logp        Print a message on all log outputs; useful for placing markers in test logs | ||||
|   subscriber  Subscriber management commands | ||||
| OsmoHLR> list | ||||
|   show version | ||||
|   show online-help | ||||
| @@ -25,14 +37,24 @@ OsmoHLR> list | ||||
|   show subscriber (imsi|msisdn|id|imei) IDENT | ||||
|  | ||||
| OsmoHLR> enable | ||||
| OsmoHLR# ? | ||||
|   help        Description of the interactive help system | ||||
|   list        Print command list | ||||
|   write       Write running configuration to memory, network, or terminal | ||||
|   show        Show running system information | ||||
|   exit        Exit current mode and down to previous mode | ||||
|   disable     Turn off privileged mode command | ||||
|   configure   Configuration from vty interface | ||||
|   copy        Copy configuration | ||||
|   terminal    Set terminal line parameters | ||||
|   who         Display who is on vty | ||||
|   logging     Configure logging | ||||
|   no          Negate a command or set its defaults | ||||
|   logp        Print a message on all log outputs; useful for placing markers in test logs | ||||
|   subscriber  Subscriber management commands | ||||
| OsmoHLR# list | ||||
|   help | ||||
|   list | ||||
|   write terminal | ||||
|   write file | ||||
|   write memory | ||||
|   write | ||||
|   show running-config | ||||
| ... | ||||
|   exit | ||||
|   disable | ||||
|   configure terminal | ||||
| @@ -50,28 +72,35 @@ OsmoHLR# list | ||||
| ... | ||||
|  | ||||
| OsmoHLR# configure terminal | ||||
| OsmoHLR(config)# ? | ||||
| ... | ||||
|   banner    Set banner string | ||||
|   service   Set up miscellaneous service | ||||
|   line      Configure a terminal line | ||||
|   ctrl      Configure the Control Interface | ||||
|   log       Configure logging sub-system | ||||
|   stats     Configure stats sub-system | ||||
|   hlr       Configure the HLR | ||||
| OsmoHLR(config)# list | ||||
|   help | ||||
|   list | ||||
|   write terminal | ||||
|   write file | ||||
|   write memory | ||||
|   write | ||||
|   show running-config | ||||
| ... | ||||
|   exit | ||||
|   end | ||||
| ... | ||||
|   hlr | ||||
|  | ||||
| OsmoHLR(config)# hlr | ||||
| OsmoHLR(config-hlr)# ? | ||||
| ... | ||||
|   euse                         Configure a particular External USSD Entity | ||||
|   no                           Negate a command or set its defaults | ||||
|   ussd                         USSD Configuration | ||||
|   ncss-guard-timeout           Set guard timer for NCSS (call independent SS) session activity | ||||
|   store-imei                   Save the IMEI in the database when receiving Check IMEI requests. Note that an MSC does not necessarily send Check IMEI requests (for OsmoMSC, you may want to set 'check-imei-rqd 1'). | ||||
|   subscriber-create-on-demand  Make a new record when a subscriber is first seen. | ||||
| OsmoHLR(config-hlr)# list | ||||
|   help | ||||
|   list | ||||
|   write terminal | ||||
|   write file | ||||
|   write memory | ||||
|   write | ||||
|   show running-config | ||||
| ... | ||||
|   exit | ||||
|   end | ||||
|   gsup | ||||
| @@ -90,16 +119,11 @@ OsmoHLR(config-hlr)# list | ||||
|   no subscriber-create-on-demand | ||||
|  | ||||
| OsmoHLR(config-hlr)# gsup | ||||
| OsmoHLR(config-hlr-gsup)# ? | ||||
| ... | ||||
|   bind   Listen/Bind related socket option | ||||
| OsmoHLR(config-hlr-gsup)# list | ||||
|   help | ||||
|   list | ||||
|   write terminal | ||||
|   write file | ||||
|   write memory | ||||
|   write | ||||
|   show running-config | ||||
|   exit | ||||
|   end | ||||
| ... | ||||
|   bind ip A.B.C.D | ||||
|  | ||||
| OsmoHLR(config-hlr-gsup)# exit | ||||
|   | ||||
| @@ -15,13 +15,6 @@ cat $abs_srcdir/auc/auc_ts_55_205_test_sets.err > experr | ||||
| AT_CHECK([$abs_top_builddir/tests/auc/auc_ts_55_205_test_sets], [], [expout], [experr]) | ||||
| AT_CLEANUP | ||||
|  | ||||
| AT_SETUP([gsup]) | ||||
| AT_KEYWORDS([gsup]) | ||||
| cat $abs_srcdir/gsup/gsup_test.ok > expout | ||||
| cat $abs_srcdir/gsup/gsup_test.err > experr | ||||
| AT_CHECK([$abs_top_builddir/tests/gsup/gsup_test], [], [expout], [experr]) | ||||
| AT_CLEANUP | ||||
|  | ||||
| AT_SETUP([gsup_server]) | ||||
| AT_KEYWORDS([gsup_server]) | ||||
| cat $abs_srcdir/gsup_server/gsup_server_test.ok > expout | ||||
| @@ -36,3 +29,13 @@ cat $abs_srcdir/db/db_test.err > experr | ||||
| sqlite3 db_test.db < $abs_top_srcdir/sql/hlr.sql | ||||
| AT_CHECK([$abs_top_builddir/tests/db/db_test], [], [expout], [experr]) | ||||
| AT_CLEANUP | ||||
|  | ||||
| # AT_SKIP_IF: disable for old sqlite versions, because the way we dump tables in the test doesn't work with it. | ||||
| # https://lists.osmocom.org/pipermail/openbsc/2019-November/013063.html | ||||
| AT_SETUP([db_upgrade]) | ||||
| AT_SKIP_IF([ ! pkg-config sqlite3 --exists --atleast-version=3.16.2 ]) | ||||
| AT_KEYWORDS([db_upgrade]) | ||||
| cat $abs_srcdir/db_upgrade/db_upgrade_test.ok > expout | ||||
| cat $abs_srcdir/db_upgrade/db_upgrade_test.err > experr | ||||
| AT_CHECK([$abs_srcdir/db_upgrade/db_upgrade_test.sh $abs_srcdir/db_upgrade $abs_builddir/db_upgrade], [], [expout], [experr]) | ||||
| AT_CLEANUP | ||||
|   | ||||
		Reference in New Issue
	
	Block a user