mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr.git
synced 2025-11-02 21:23:30 +00:00
Compare commits
21 Commits
falconia/p
...
1.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d052f076e3 | ||
|
|
37f0b3a8f3 | ||
|
|
7a763aa012 | ||
|
|
626f5eb740 | ||
|
|
5800f3add5 | ||
|
|
f8b73f0682 | ||
|
|
f4223f5b53 | ||
|
|
1c23f304d1 | ||
|
|
f4159bd54c | ||
|
|
a854b48762 | ||
|
|
91150802f8 | ||
|
|
8f3fa656e7 | ||
|
|
829713a69d | ||
|
|
5edf387353 | ||
|
|
2989873a68 | ||
|
|
390f6fcf13 | ||
|
|
d10c2ef366 | ||
|
|
974aed9c04 | ||
|
|
cf535dbcbd | ||
|
|
a55e63b087 | ||
|
|
62e5c1b2c7 |
10
configure.ac
10
configure.ac
@@ -41,11 +41,11 @@ PKG_PROG_PKG_CONFIG([0.20])
|
||||
|
||||
PKG_CHECK_MODULES(TALLOC, [talloc >= 2.0.1])
|
||||
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.8.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.4.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.0)
|
||||
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.5.0)
|
||||
|
||||
PKG_CHECK_MODULES(SQLITE3, sqlite3)
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ BuildRequires: python3
|
||||
%if 0%{?suse_version}
|
||||
BuildRequires: systemd-rpm-macros
|
||||
%endif
|
||||
BuildRequires: pkgconfig(libosmoabis) >= 1.4.0
|
||||
BuildRequires: pkgconfig(libosmocore) >= 1.8.0
|
||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.8.0
|
||||
BuildRequires: pkgconfig(libosmogsm) >= 1.8.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.8.0
|
||||
BuildRequires: pkgconfig(libosmoabis) >= 1.5.0
|
||||
BuildRequires: pkgconfig(libosmocore) >= 1.9.0
|
||||
BuildRequires: pkgconfig(libosmoctrl) >= 1.9.0
|
||||
BuildRequires: pkgconfig(libosmogsm) >= 1.9.0
|
||||
BuildRequires: pkgconfig(libosmovty) >= 1.9.0
|
||||
BuildRequires: pkgconfig(sqlite3)
|
||||
BuildRequires: pkgconfig(talloc) >= 2.0.1
|
||||
# only needed for populate_hlr_db.pl
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
[Unit]
|
||||
Description=Osmocom Home Location Register (OsmoHLR)
|
||||
Documentation=https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
34
debian/changelog
vendored
34
debian/changelog
vendored
@@ -1,3 +1,37 @@
|
||||
osmo-hlr (1.7.0) unstable; urgency=medium
|
||||
|
||||
[ Oliver Smith ]
|
||||
* Run struct_endianness.py
|
||||
* tests/db/db_test.err: adjust to XOR-3G rename
|
||||
* debian: set compat level to 10
|
||||
* systemd: depend on networking-online.target
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* mslookup: Call osmo_fd_unregister() before closing and changing bfd->fd
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* tests/auc/Makefile.am: put object files to LDADD
|
||||
* tests/*/Makefile.am: move -I to AM_CPPFLAGS
|
||||
* lu_fsm: fix memleak in lu_fsm_wait_insert_data_result()
|
||||
* ussd: fix GSUP memleaks in rx_proc_ss_{req,error}()
|
||||
* gsup_server: fix msgb memleak in osmo_gsup_server_read_cb()
|
||||
* USSD: fix handling of ussd-DataCodingScheme != 0x0f
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* hlr: use talloc for memory allocation in osmo_gsup_create_insert_subscriber_data_msg
|
||||
* Add support for multiple APN profiles for subscriber data
|
||||
|
||||
[ Harald Welte ]
|
||||
* Introduce support for XOR-2G algorithm
|
||||
* cosmetic: gen_ts_55_205_test_sets/func_template.c: Use tab-indent
|
||||
* cosmetic: gen_ts_55_205_test_sets/main_template tabs istead of spaces
|
||||
* Port to new libosmogsm 'struct osmo_sub_auth_data2'
|
||||
* src/db.c: Switch from "const char *statements" to "const char * const"
|
||||
* db: extend database schema to support 256bit K and/or OP[c] values
|
||||
* Add VTY support for TUAK algorithm
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 12 Sep 2023 14:41:33 +0200
|
||||
|
||||
osmo-hlr (1.6.0) unstable; urgency=medium
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
|
||||
2
debian/compat
vendored
2
debian/compat
vendored
@@ -1 +1 @@
|
||||
9
|
||||
10
|
||||
|
||||
10
debian/control
vendored
10
debian/control
vendored
@@ -2,17 +2,17 @@ Source: osmo-hlr
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
|
||||
Build-Depends: debhelper (>= 9),
|
||||
Build-Depends: debhelper (>= 10),
|
||||
pkg-config,
|
||||
dh-autoreconf,
|
||||
autotools-dev,
|
||||
python3-minimal,
|
||||
libosmocore-dev (>= 1.8.0),
|
||||
libosmo-abis-dev (>= 1.4.0),
|
||||
libosmo-netif-dev (>= 1.3.0),
|
||||
libosmocore-dev (>= 1.9.0),
|
||||
libosmo-abis-dev (>= 1.5.0),
|
||||
libosmo-netif-dev (>= 1.4.0),
|
||||
libsqlite3-dev,
|
||||
sqlite3,
|
||||
osmo-gsm-manuals-dev (>= 1.4.0)
|
||||
osmo-gsm-manuals-dev (>= 1.5.0)
|
||||
Standards-Version: 3.9.6
|
||||
Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
|
||||
Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
|
||||
|
||||
@@ -24,3 +24,9 @@ hlr
|
||||
bind ip 127.0.0.1
|
||||
ussd route prefix *#100# internal own-msisdn
|
||||
ussd route prefix *#101# internal own-imsi
|
||||
ps
|
||||
pdp-profiles default
|
||||
profile 1
|
||||
apn internet
|
||||
profile 2
|
||||
apn *
|
||||
|
||||
@@ -6,7 +6,6 @@ noinst_HEADERS = \
|
||||
gsup_router.h \
|
||||
gsup_server.h \
|
||||
hlr.h \
|
||||
hlr_sms.h \
|
||||
hlr_ussd.h \
|
||||
hlr_vty.h \
|
||||
hlr_vty_subscr.h \
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
#include <osmocom/crypt/auth.h>
|
||||
|
||||
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
const uint8_t *rand_auts, const uint8_t *auts);
|
||||
|
||||
@@ -70,8 +70,8 @@ struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite3_log
|
||||
|
||||
/* obtain the authentication data for a given imsi */
|
||||
int db_get_auth_data(struct db_context *dbc, const char *imsi,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
int64_t *subscr_id);
|
||||
|
||||
int db_update_sqn(struct db_context *dbc, int64_t id,
|
||||
@@ -121,7 +121,7 @@ struct hlr_subscriber {
|
||||
* See https://sqlite.org/lang_datefunc.html, function datetime(). */
|
||||
#define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
/* Like struct osmo_sub_auth_data, but the keys are in hexdump representation.
|
||||
/* Like struct osmo_sub_auth_data2, but the keys are in hexdump representation.
|
||||
* This is useful because SQLite requires them in hexdump format, and callers
|
||||
* like the VTY and CTRL interface also have them available as hexdump to begin
|
||||
* with. In the binary format, a VTY command would first need to hexparse,
|
||||
|
||||
@@ -69,8 +69,6 @@ void osmo_gsup_server_destroy(struct osmo_gsup_server *gsups);
|
||||
int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup,
|
||||
uint8_t *apn_buf, size_t apn_buf_size);
|
||||
int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
|
||||
uint8_t *msisdn_enc, size_t msisdn_enc_size,
|
||||
uint8_t *apn_buf, size_t apn_buf_size,
|
||||
enum osmo_gsup_cn_domain cn_domain);
|
||||
enum osmo_gsup_cn_domain cn_domain, void *talloc_ctx);
|
||||
int osmo_gsup_forward_to_local_peer(struct osmo_gsup_server *server, const struct osmo_cni_peer_id *to_peer,
|
||||
struct osmo_gsup_req *req, struct osmo_gsup_message *modified_gsup);
|
||||
|
||||
@@ -58,6 +58,14 @@ struct hlr {
|
||||
struct hlr_euse *euse_default;
|
||||
enum gsm48_gmm_cause reject_cause;
|
||||
enum gsm48_gmm_cause no_proxy_reject_cause;
|
||||
/* PS: APN default configuration used by Subscription Data on ISR */
|
||||
struct {
|
||||
struct {
|
||||
bool enabled;
|
||||
struct osmo_gsup_pdp_info pdp_infos[OSMO_GSUP_MAX_NUM_PDP_INFO];
|
||||
size_t num_pdp_infos;
|
||||
} pdp_profile;
|
||||
} ps;
|
||||
|
||||
/* NCSS (call independent) session guard timeout value */
|
||||
int ncss_guard_timeout;
|
||||
@@ -66,10 +74,6 @@ struct hlr {
|
||||
|
||||
struct llist_head ss_sessions;
|
||||
|
||||
struct llist_head smsc_list;
|
||||
struct llist_head smsc_routes;
|
||||
struct hlr_smsc *smsc_default;
|
||||
|
||||
bool store_imei;
|
||||
|
||||
bool subscr_create_on_demand;
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
struct hlr_smsc {
|
||||
/* g_hlr->smsc_list */
|
||||
struct llist_head list;
|
||||
struct hlr *hlr;
|
||||
/* name (must match the IPA ID tag) */
|
||||
const char *name;
|
||||
/* human-readable description */
|
||||
const char *description;
|
||||
};
|
||||
|
||||
struct hlr_smsc *smsc_find(struct hlr *hlr, const char *name);
|
||||
struct hlr_smsc *smsc_alloc(struct hlr *hlr, const char *name);
|
||||
void smsc_del(struct hlr_smsc *smsc);
|
||||
|
||||
struct hlr_smsc_route {
|
||||
/* g_hlr->smsc_routes */
|
||||
struct llist_head list;
|
||||
const char *num_addr;
|
||||
struct hlr_smsc *smsc;
|
||||
};
|
||||
|
||||
struct hlr_smsc_route *smsc_route_find(struct hlr *hlr, const char *num_addr);
|
||||
struct hlr_smsc_route *smsc_route_alloc(struct hlr *hlr, const char *num_addr,
|
||||
struct hlr_smsc *smsc);
|
||||
void smsc_route_del(struct hlr_smsc_route *rt);
|
||||
|
||||
void forward_mo_sms(struct osmo_gsup_req *req);
|
||||
void forward_mt_sms(struct osmo_gsup_req *req);
|
||||
void rx_ready_for_sm_req(struct osmo_gsup_req *req);
|
||||
@@ -31,16 +31,19 @@ enum hlr_vty_node {
|
||||
HLR_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
GSUP_NODE,
|
||||
EUSE_NODE,
|
||||
SMSC_NODE,
|
||||
MSLOOKUP_NODE,
|
||||
MSLOOKUP_SERVER_NODE,
|
||||
MSLOOKUP_SERVER_MSC_NODE,
|
||||
MSLOOKUP_CLIENT_NODE,
|
||||
PS_NODE,
|
||||
PS_PDP_PROFILES_NODE,
|
||||
PS_PDP_PROFILES_PROFILE_NODE,
|
||||
};
|
||||
|
||||
|
||||
#define A38_XOR_MIN_KEY_LEN 12
|
||||
#define A38_XOR_MAX_KEY_LEN 16
|
||||
#define A38_XOR2G_KEY_LEN 16
|
||||
#define A38_COMP128_KEY_LEN 16
|
||||
#define MILENAGE_KEY_LEN 16
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ struct osmo_mdns_rfc_header {
|
||||
uint16_t nscount; /* Number of authority records */
|
||||
uint16_t arcount; /* Number of additional records */
|
||||
#elif OSMO_IS_BIG_ENDIAN
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
|
||||
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
|
||||
uint16_t id;
|
||||
uint8_t qr:1, opcode:4, aa:1, tc:1, rd:1;
|
||||
uint8_t ra:1, z:3, rcode:4;
|
||||
|
||||
@@ -71,9 +71,9 @@ CREATE TABLE auc_2g (
|
||||
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)
|
||||
k VARCHAR(64) NOT NULL, -- hex string: subscriber's secret key (128/256bit)
|
||||
op VARCHAR(64), -- hex string: operator's secret key (128/256bit)
|
||||
opc VARCHAR(64), -- hex string: derived from OP and K (128/256bit)
|
||||
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
|
||||
@@ -91,4 +91,4 @@ 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 = 6;
|
||||
PRAGMA user_version = 7;
|
||||
|
||||
@@ -52,7 +52,6 @@ osmo_hlr_SOURCES = \
|
||||
hlr_vty.c \
|
||||
hlr_vty_subscr.c \
|
||||
gsup_send.c \
|
||||
hlr_sms.c \
|
||||
hlr_ussd.c \
|
||||
proxy.c \
|
||||
dgsm.c \
|
||||
@@ -112,7 +111,7 @@ BOOTSTRAP_SQL = $(top_srcdir)/sql/hlr.sql
|
||||
db_bootstrap.h: $(BOOTSTRAP_SQL) $(srcdir)/db_sql2c.sed
|
||||
echo "/* DO NOT EDIT THIS FILE. It is generated from files in osmo-hlr.git/sql/ */" > "$@"
|
||||
echo "#pragma once" >> "$@"
|
||||
echo "static const char *stmt_bootstrap_sql[] = {" >> "$@"
|
||||
echo "static const char * const stmt_bootstrap_sql[] = {" >> "$@"
|
||||
cat "$(BOOTSTRAP_SQL)" \
|
||||
| sed -f "$(srcdir)/db_sql2c.sed" \
|
||||
>> "$@"
|
||||
|
||||
21
src/auc.c
21
src/auc.c
@@ -1,4 +1,4 @@
|
||||
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -32,8 +32,8 @@
|
||||
/* compute given number of vectors using either aud2g or aud2g or a combination
|
||||
* of both. Handles re-synchronization if rand_auts and auts are set */
|
||||
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
const uint8_t *rand_auts, const uint8_t *auts)
|
||||
{
|
||||
unsigned int i;
|
||||
@@ -93,10 +93,10 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
: "2G only",
|
||||
auts? ", with AUTS resync" : "");
|
||||
if (aud3g) {
|
||||
DBGP("3G: k = %s\n", hexb(aud3g->u.umts.k));
|
||||
DBGP("3G: k = %s\n", hex(aud3g->u.umts.k, aud3g->u.umts.k_len));
|
||||
DBGP("3G: %s = %s\n",
|
||||
aud3g->u.umts.opc_is_op? "OP" : "opc",
|
||||
hexb(aud3g->u.umts.opc));
|
||||
hex(aud3g->u.umts.opc, aud3g->u.umts.opc_len));
|
||||
DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n",
|
||||
aud3g->u.umts.ind, aud3g->u.umts.sqn);
|
||||
}
|
||||
@@ -115,6 +115,9 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
if (aud3g) {
|
||||
/* 3G or 3G + 2G case */
|
||||
|
||||
/* backwards-compatibiliy: We assume all RES are 8 bytes long */
|
||||
vec[i].res_len = 8;
|
||||
|
||||
/* Do AUTS only for the first vector or we would use
|
||||
* the same SQN for each following key. */
|
||||
if ((i == 0) && auts) {
|
||||
@@ -123,10 +126,10 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
DBGP("vector [%u]: resync: rand_auts = %s\n",
|
||||
i, hex(rand_auts, 16));
|
||||
|
||||
rc = osmo_auth_gen_vec_auts(vec+i, aud3g, auts,
|
||||
rc = osmo_auth_gen_vec_auts2(vec+i, aud3g, auts,
|
||||
rand_auts, rand);
|
||||
} else {
|
||||
rc = osmo_auth_gen_vec(vec+i, aud3g, rand);
|
||||
rc = osmo_auth_gen_vec2(vec+i, aud3g, rand);
|
||||
}
|
||||
if (rc < 0) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Error in 3G vector "
|
||||
@@ -154,7 +157,7 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
|
||||
DBGP("vector [%u]: calculating 2G separately\n", i);
|
||||
|
||||
rc = osmo_auth_gen_vec(&vtmp, aud2g, rand);
|
||||
rc = osmo_auth_gen_vec2(&vtmp, aud2g, rand);
|
||||
if (rc < 0) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector"
|
||||
"generation: [%u]: rc = %d\n", i, rc);
|
||||
@@ -165,7 +168,7 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
vec[i].auth_types |= OSMO_AUTH_TYPE_GSM;
|
||||
} else {
|
||||
/* 2G only case */
|
||||
rc = osmo_auth_gen_vec(vec+i, aud2g, rand);
|
||||
rc = osmo_auth_gen_vec2(vec+i, aud2g, rand);
|
||||
if (rc < 0) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
|
||||
"generation: [%u]: rc = %d\n", i, rc);
|
||||
|
||||
57
src/ctrl.c
57
src/ctrl.c
@@ -1,6 +1,6 @@
|
||||
/* OsmoHLR Control Interface implementation */
|
||||
|
||||
/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
/* (C) 2017-2023 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Max Suraev <msuraev@sysmocom.de>
|
||||
@@ -39,7 +39,7 @@
|
||||
#define SEL_BY_ID SEL_BY "id-"
|
||||
|
||||
extern bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
|
||||
int *minlen, int *maxlen);
|
||||
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc);
|
||||
|
||||
#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
|
||||
|
||||
@@ -166,7 +166,7 @@ static void print_subscr_info(struct ctrl_cmd *cmd,
|
||||
);
|
||||
}
|
||||
|
||||
static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
|
||||
static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *aud)
|
||||
{
|
||||
if (aud->algo == OSMO_AUTH_ALG_NONE)
|
||||
return;
|
||||
@@ -178,7 +178,7 @@ static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
|
||||
hexdump_buf(aud->u.gsm.ki));
|
||||
}
|
||||
|
||||
static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
|
||||
static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data2 *aud)
|
||||
{
|
||||
if (aud->algo == OSMO_AUTH_ALG_NONE)
|
||||
return;
|
||||
@@ -187,7 +187,7 @@ static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
|
||||
"\naud3g.k\t%s"
|
||||
,
|
||||
osmo_auth_alg_name(aud->algo),
|
||||
hexdump_buf(aud->u.umts.k));
|
||||
osmo_hexdump_nospc(aud->u.umts.k, aud->u.umts.k_len));
|
||||
/* hexdump uses a static string buffer, hence only one hexdump per
|
||||
* printf(). */
|
||||
ctrl_cmd_reply_printf(cmd,
|
||||
@@ -196,7 +196,7 @@ static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_d
|
||||
"\naud3g.sqn\t%" PRIu64
|
||||
,
|
||||
aud->u.umts.opc_is_op? "op" : "opc",
|
||||
hexdump_buf(aud->u.umts.opc),
|
||||
osmo_hexdump_nospc(aud->u.umts.opc, aud->u.umts.opc_len),
|
||||
aud->u.umts.ind_bitlen,
|
||||
aud->u.umts.sqn);
|
||||
}
|
||||
@@ -291,8 +291,8 @@ CTRL_CMD_DEFINE_RO(subscr_info_aud, "info-aud");
|
||||
static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
const char *imsi;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
int rc;
|
||||
@@ -327,8 +327,8 @@ CTRL_CMD_DEFINE_RO(subscr_info_all, "info-all");
|
||||
static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
int rc;
|
||||
@@ -426,20 +426,6 @@ static int set_subscr_cs_enabled(struct ctrl_cmd *cmd, void *data)
|
||||
return set_subscr_cs_ps_enabled(cmd, data, false);
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE_RO(subscr_imsi, "imsi");
|
||||
static int get_subscr_imsi(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
|
||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
||||
return CTRL_CMD_ERROR;
|
||||
|
||||
cmd->reply = talloc_strdup(cmd, subscr.imsi);
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE(subscr_msisdn, "msisdn");
|
||||
static int verify_subscr_msisdn(struct ctrl_cmd *cmd, const char *value, void *data)
|
||||
{
|
||||
@@ -506,8 +492,8 @@ static int get_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
|
||||
struct hlr_subscriber subscr;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g_unused;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g_unused;
|
||||
int rc;
|
||||
|
||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
||||
@@ -564,7 +550,7 @@ static int set_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
|
||||
}
|
||||
if (strcmp(tok, "none") == 0) {
|
||||
aud2g.algo = OSMO_AUTH_ALG_NONE;
|
||||
} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen)) {
|
||||
} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
|
||||
cmd->reply = "Unknown auth algorithm.";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
@@ -606,8 +592,8 @@ static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
struct hlr_subscriber subscr;
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
struct osmo_sub_auth_data aud2g_unused;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_sub_auth_data2 aud2g_unused;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
int rc;
|
||||
|
||||
if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
|
||||
@@ -632,9 +618,9 @@ static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
}
|
||||
|
||||
cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", osmo_auth_alg_name(aud3g.algo),
|
||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, sizeof(aud3g.u.umts.k)),
|
||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, aud3g.u.umts.k_len),
|
||||
aud3g.u.umts.opc_is_op ? "OP" : "OPC",
|
||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc)),
|
||||
osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, aud3g.u.umts.opc_len),
|
||||
aud3g.u.umts.ind_bitlen);
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
@@ -644,8 +630,8 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
struct hlr *hlr = data;
|
||||
const char *by_selector = cmd->node;
|
||||
char *tmp = NULL, *tok, *saveptr;
|
||||
int minlen = 0;
|
||||
int maxlen = 0;
|
||||
int minlen = 0, minlen_opc = 0;
|
||||
int maxlen = 0, maxlen_opc = 0;
|
||||
struct sub_auth_data_str aud3g = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.u.umts = {
|
||||
@@ -671,7 +657,7 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
}
|
||||
if (strcmp(tok, "none") == 0) {
|
||||
aud3g.algo = OSMO_AUTH_ALG_NONE;
|
||||
} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen)) {
|
||||
} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
|
||||
cmd->reply = "Unknown auth algorithm.";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
@@ -713,7 +699,7 @@ static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
|
||||
}
|
||||
|
||||
aud3g.u.umts.opc = tok;
|
||||
if (!osmo_is_hexstr(aud3g.u.umts.opc, MILENAGE_KEY_LEN * 2, MILENAGE_KEY_LEN * 2, true)) {
|
||||
if (!osmo_is_hexstr(aud3g.u.umts.opc, minlen_opc * 2, maxlen_opc * 2, true)) {
|
||||
cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC.");
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
@@ -775,7 +761,6 @@ static int hlr_ctrl_cmds_install(void)
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_all);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_ps_enabled);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_cs_enabled);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_imsi);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_msisdn);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud2g);
|
||||
rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud3g);
|
||||
|
||||
59
src/db.c
59
src/db.c
@@ -1,4 +1,4 @@
|
||||
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "db_bootstrap.h"
|
||||
|
||||
/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
|
||||
#define CURRENT_SCHEMA_VERSION 6
|
||||
#define CURRENT_SCHEMA_VERSION 7
|
||||
|
||||
#define SEL_COLUMNS \
|
||||
"id," \
|
||||
@@ -235,7 +235,7 @@ void db_close(struct db_context *dbc)
|
||||
talloc_free(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 * const *statements, size_t statements_count)
|
||||
{
|
||||
int rc = 0;
|
||||
int i;
|
||||
@@ -308,7 +308,7 @@ static int
|
||||
db_upgrade_v1(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char *statements[] = {
|
||||
const char * const statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL",
|
||||
"PRAGMA user_version = 1",
|
||||
};
|
||||
@@ -324,7 +324,7 @@ db_upgrade_v1(struct db_context *dbc)
|
||||
static int db_upgrade_v2(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char *statements[] = {
|
||||
const char * const statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14)",
|
||||
"PRAGMA user_version = 2",
|
||||
};
|
||||
@@ -437,7 +437,7 @@ static int db_upgrade_v3(struct db_context *dbc)
|
||||
"ms_purged_ps," \
|
||||
"last_lu_seen"
|
||||
|
||||
const char *statements[] = {
|
||||
const char * const statements[] = {
|
||||
"BEGIN TRANSACTION",
|
||||
"CREATE TEMPORARY TABLE subscriber_backup" SUBSCR_V3_CREATE,
|
||||
"INSERT INTO subscriber_backup SELECT " SUBSCR_V2_COLUMN_NAMES " FROM subscriber",
|
||||
@@ -460,7 +460,7 @@ static int db_upgrade_v3(struct db_context *dbc)
|
||||
static int db_upgrade_v4(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char *statements[] = {
|
||||
const char * const statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN last_lu_seen_ps TIMESTAMP default NULL",
|
||||
"PRAGMA user_version = 4",
|
||||
};
|
||||
@@ -476,7 +476,7 @@ static int db_upgrade_v4(struct db_context *dbc)
|
||||
static int db_upgrade_v5(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char *statements[] = {
|
||||
const char * const statements[] = {
|
||||
"ALTER TABLE subscriber ADD COLUMN vlr_via_proxy VARCHAR",
|
||||
"ALTER TABLE subscriber ADD COLUMN sgsn_via_proxy VARCHAR",
|
||||
"PRAGMA user_version = 5",
|
||||
@@ -493,7 +493,7 @@ static int db_upgrade_v5(struct db_context *dbc)
|
||||
static int db_upgrade_v6(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
const char *statements[] = {
|
||||
const char * const statements[] = {
|
||||
"CREATE TABLE ind (\n"
|
||||
" -- 3G auth IND pool to be used for this VLR\n"
|
||||
" ind INTEGER PRIMARY KEY,\n"
|
||||
@@ -513,6 +513,46 @@ static int db_upgrade_v6(struct db_context *dbc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int db_upgrade_v7(struct db_context *dbc)
|
||||
{
|
||||
int rc;
|
||||
/* SQLite doesn't allow us to change the column type in-place, so we
|
||||
* first rename the old table, create a new table and then copy
|
||||
* the data over before deleting the old table */
|
||||
#define CREATE_AUC_3G_V7 \
|
||||
"CREATE TABLE auc_3g (\n" \
|
||||
" subscriber_id INTEGER PRIMARY KEY, -- subscriber.id\n" \
|
||||
" algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value\n" \
|
||||
" k VARCHAR(64) NOT NULL, -- hex string: subscriber's secret key (128/256bit)\n" \
|
||||
" op VARCHAR(64), -- hex string: operator's secret key (128/256bit)\n" \
|
||||
" opc VARCHAR(64), -- hex string: derived from OP and K (128/256bit)\n" \
|
||||
" sqn INTEGER NOT NULL DEFAULT 0, -- sequence number of key usage\n" \
|
||||
" -- nr of index bits at lower SQN end\n" \
|
||||
" ind_bitlen INTEGER NOT NULL DEFAULT 5\n" \
|
||||
");"
|
||||
const char * const statements[] = {
|
||||
"BEGIN TRANSACTION",
|
||||
/* rename old table */
|
||||
"ALTER TABLE auc_3g RENAME TO old_auc_3g",
|
||||
/* create new table */
|
||||
CREATE_AUC_3G_V7,
|
||||
/* copy over old data */
|
||||
"INSERT INTO auc_3g SELECT subscriber_id, algo_id_3g, k, op, opc,sqn, ind_bitlen FROM old_auc_3g",
|
||||
/* delete old table */
|
||||
"DROP TABLE old_auc_3g",
|
||||
/* update user_version */
|
||||
"PRAGMA user_version = 7",
|
||||
"COMMIT",
|
||||
};
|
||||
|
||||
rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
|
||||
if (rc != SQLITE_DONE) {
|
||||
LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 7\n");
|
||||
return rc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
typedef int (*db_upgrade_func_t)(struct db_context *dbc);
|
||||
static db_upgrade_func_t db_upgrade_path[] = {
|
||||
db_upgrade_v1,
|
||||
@@ -521,6 +561,7 @@ static db_upgrade_func_t db_upgrade_path[] = {
|
||||
db_upgrade_v4,
|
||||
db_upgrade_v5,
|
||||
db_upgrade_v6,
|
||||
db_upgrade_v7,
|
||||
};
|
||||
|
||||
static int db_get_user_version(struct db_context *dbc)
|
||||
|
||||
45
src/db_auc.c
45
src/db_auc.c
@@ -1,4 +1,4 @@
|
||||
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -74,9 +74,9 @@ out:
|
||||
}
|
||||
|
||||
/* hexparse a specific column of a sqlite prepared statement into dst (with length check)
|
||||
* returns 0 for success, -EIO on error */
|
||||
static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int col, const char *col_name,
|
||||
const char *imsi)
|
||||
* returns byte length in case of success, -EIO on error */
|
||||
static int hexparse_stmt(uint8_t *dst, size_t dst_len_min, size_t dst_len_max, sqlite3_stmt *stmt,
|
||||
int col, const char *col_name, const char *imsi)
|
||||
{
|
||||
const uint8_t *text;
|
||||
size_t col_len;
|
||||
@@ -84,9 +84,15 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
|
||||
/* Bytes are stored as hex strings in database, hence divide length by two */
|
||||
col_len = sqlite3_column_bytes(stmt, col) / 2;
|
||||
|
||||
if (col_len != dst_len) {
|
||||
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected length %lu but has length %lu\n", col_name,
|
||||
dst_len, col_len);
|
||||
if (col_len < dst_len_min) {
|
||||
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected min length %lu but has length %lu\n", col_name,
|
||||
dst_len_min, col_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (col_len > dst_len_max) {
|
||||
LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected max length %lu but has length %lu\n", col_name,
|
||||
dst_len_max, col_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -96,10 +102,10 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (osmo_hexparse((void *)text, dst, dst_len) != col_len)
|
||||
if (osmo_hexparse((void *)text, dst, dst_len_max) != col_len)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
return col_len;
|
||||
}
|
||||
|
||||
/* obtain the authentication data for a given imsi
|
||||
@@ -107,8 +113,8 @@ static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int c
|
||||
* -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no auth data,
|
||||
* -EIO on db failure */
|
||||
int db_get_auth_data(struct db_context *dbc, const char *imsi,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
int64_t *subscr_id)
|
||||
{
|
||||
sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI];
|
||||
@@ -142,7 +148,8 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
|
||||
/* obtain result values using sqlite3_column_*() */
|
||||
if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) {
|
||||
/* we do have some 2G authentication data */
|
||||
if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), stmt, 2, "Ki", imsi))
|
||||
if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), sizeof(aud2g->u.gsm.ki),
|
||||
stmt, 2, "Ki", imsi) < 0)
|
||||
goto end_2g;
|
||||
aud2g->algo = sqlite3_column_int(stmt, 1);
|
||||
aud2g->type = OSMO_AUTH_TYPE_GSM;
|
||||
@@ -151,24 +158,30 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
|
||||
end_2g:
|
||||
if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
|
||||
/* we do have some 3G authentication data */
|
||||
if (hexparse_stmt(aud3g->u.umts.k, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi)) {
|
||||
rc = hexparse_stmt(aud3g->u.umts.k, 16, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi);
|
||||
if (rc < 0) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
aud3g->u.umts.k_len = rc;
|
||||
aud3g->algo = sqlite3_column_int(stmt, 3);
|
||||
|
||||
/* UMTS Subscribers can have either OP or OPC */
|
||||
if (sqlite3_column_text(stmt, 5)) {
|
||||
if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi)) {
|
||||
rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi);
|
||||
if (rc < 0) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
aud3g->u.umts.opc_len = rc;
|
||||
aud3g->u.umts.opc_is_op = 1;
|
||||
} else {
|
||||
if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi)) {
|
||||
rc = hexparse_stmt(aud3g->u.umts.opc, 16, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi);
|
||||
if (rc < 0) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
aud3g->u.umts.opc_len = rc;
|
||||
aud3g->u.umts.opc_is_op = 0;
|
||||
}
|
||||
aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7);
|
||||
@@ -194,7 +207,7 @@ int db_get_auc(struct db_context *dbc, const char *imsi,
|
||||
unsigned int num_vec, const uint8_t *rand_auts,
|
||||
const uint8_t *auts, bool separation_bit)
|
||||
{
|
||||
struct osmo_sub_auth_data aud2g, aud3g;
|
||||
struct osmo_sub_auth_data2 aud2g, aud3g;
|
||||
int64_t subscr_id;
|
||||
int ret = 0;
|
||||
int rc;
|
||||
|
||||
12
src/db_hlr.c
12
src/db_hlr.c
@@ -1,4 +1,4 @@
|
||||
/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
|
||||
/* (C) 2015-2023 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
@@ -238,8 +238,9 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
|
||||
case OSMO_AUTH_ALG_COMP128v1:
|
||||
case OSMO_AUTH_ALG_COMP128v2:
|
||||
case OSMO_AUTH_ALG_COMP128v3:
|
||||
case OSMO_AUTH_ALG_XOR:
|
||||
case OSMO_AUTH_ALG_XOR_2G:
|
||||
break;
|
||||
case OSMO_AUTH_ALG_XOR_3G:
|
||||
case OSMO_AUTH_ALG_MILENAGE:
|
||||
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
|
||||
" auth algo not suited for 2G: %s\n",
|
||||
@@ -267,11 +268,12 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
|
||||
switch (aud->algo) {
|
||||
case OSMO_AUTH_ALG_NONE:
|
||||
case OSMO_AUTH_ALG_MILENAGE:
|
||||
case OSMO_AUTH_ALG_XOR:
|
||||
case OSMO_AUTH_ALG_XOR_3G:
|
||||
break;
|
||||
case OSMO_AUTH_ALG_COMP128v1:
|
||||
case OSMO_AUTH_ALG_COMP128v2:
|
||||
case OSMO_AUTH_ALG_COMP128v3:
|
||||
case OSMO_AUTH_ALG_XOR_2G:
|
||||
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
|
||||
" auth algo not suited for 3G: %s\n",
|
||||
osmo_auth_alg_name(aud->algo));
|
||||
@@ -284,12 +286,12 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
|
||||
|
||||
if (aud->algo == OSMO_AUTH_ALG_NONE)
|
||||
break;
|
||||
if (!osmo_is_hexstr(aud->u.umts.k, 32, 32, true)) {
|
||||
if (!osmo_is_hexstr(aud->u.umts.k, 32, 64, true)) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
|
||||
" Invalid K: '%s'\n", aud->u.umts.k);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!osmo_is_hexstr(aud->u.umts.opc, 32, 32, true)) {
|
||||
if (!osmo_is_hexstr(aud->u.umts.opc, 32, 64, true)) {
|
||||
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
|
||||
" Invalid OP/OPC: '%s'\n", aud->u.umts.opc);
|
||||
return -EINVAL;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <osmocom/hlr/gsup_server.h>
|
||||
#include <osmocom/hlr/gsup_router.h>
|
||||
#include <osmocom/hlr/hlr.h>
|
||||
|
||||
#define LOG_GSUP_CONN(conn, level, fmt, args...) \
|
||||
LOGP(DLGSUP, level, "GSUP peer %s: " fmt, \
|
||||
@@ -179,11 +180,9 @@ static int osmo_gsup_server_read_cb(struct ipa_server_conn *conn,
|
||||
|
||||
if (hh->proto == IPAC_PROTO_IPACCESS) {
|
||||
rc = ipa_server_conn_ccm(conn, msg);
|
||||
if (rc < 0) {
|
||||
/* conn is already invalid here! */
|
||||
return -1;
|
||||
}
|
||||
msgb_free(msg);
|
||||
if (rc < 0) /* conn is already invalid here! */
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -446,19 +445,16 @@ int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup,
|
||||
* \param[out] gsup The gsup message to populate.
|
||||
* \param[in] imsi The subscriber's IMSI.
|
||||
* \param[in] msisdn The subscriber's MSISDN.
|
||||
* \param[out] msisdn_enc A buffer large enough to store the MSISDN in encoded form.
|
||||
* \param[in] msisdn_enc_size Size of the buffer (must be >= OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN).
|
||||
* \param[out] apn_buf A buffer large enough to store an APN (required if cn_domain is OSMO_GSUP_CN_DOMAIN_PS).
|
||||
* \param[in] apn_buf_size Size of APN buffer (must be >= APN_MAXLEN).
|
||||
* \param[in] cn_domain The CN Domain of the subscriber connection.
|
||||
* \param[in] talloc_ctx To allocation memory for dynamic fields (msisdn, apn) in the gsup field
|
||||
* \returns 0 on success, and negative on error.
|
||||
*/
|
||||
int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
|
||||
uint8_t *msisdn_enc, size_t msisdn_enc_size,
|
||||
uint8_t *apn_buf, size_t apn_buf_size,
|
||||
enum osmo_gsup_cn_domain cn_domain)
|
||||
enum osmo_gsup_cn_domain cn_domain,
|
||||
void *talloc_ctx)
|
||||
{
|
||||
int len;
|
||||
uint8_t *msisdn_buf = talloc_size(talloc_ctx, OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN);
|
||||
|
||||
OSMO_ASSERT(gsup);
|
||||
*gsup = (struct osmo_gsup_message){
|
||||
@@ -467,27 +463,29 @@ int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup,
|
||||
|
||||
osmo_strlcpy(gsup->imsi, imsi, sizeof(gsup->imsi));
|
||||
|
||||
if (msisdn_enc_size < OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN)
|
||||
return -ENOSPC;
|
||||
|
||||
OSMO_ASSERT(msisdn_enc);
|
||||
len = gsm48_encode_bcd_number(msisdn_enc, msisdn_enc_size, 0, msisdn);
|
||||
len = gsm48_encode_bcd_number(msisdn_buf, OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN, 0, msisdn);
|
||||
if (len < 1) {
|
||||
LOGP(DLGSUP, LOGL_ERROR, "%s: Error: cannot encode MSISDN '%s'\n", imsi, msisdn);
|
||||
return -ENOSPC;
|
||||
}
|
||||
gsup->msisdn_enc = msisdn_enc;
|
||||
gsup->msisdn_enc = msisdn_buf;
|
||||
gsup->msisdn_enc_len = len;
|
||||
|
||||
#pragma message "FIXME: deal with encoding the following data: gsup.hlr_enc"
|
||||
|
||||
gsup->cn_domain = cn_domain;
|
||||
if (gsup->cn_domain == OSMO_GSUP_CN_DOMAIN_PS) {
|
||||
OSMO_ASSERT(apn_buf_size >= APN_MAXLEN);
|
||||
OSMO_ASSERT(apn_buf);
|
||||
/* FIXME: PDP infos - use more fine-grained access control
|
||||
instead of wildcard APN */
|
||||
osmo_gsup_configure_wildcard_apn(gsup, apn_buf, apn_buf_size);
|
||||
if (g_hlr->ps.pdp_profile.enabled) {
|
||||
OSMO_ASSERT(g_hlr->ps.pdp_profile.num_pdp_infos <= ARRAY_SIZE(g_hlr->ps.pdp_profile.pdp_infos));
|
||||
OSMO_ASSERT(g_hlr->ps.pdp_profile.num_pdp_infos <= ARRAY_SIZE(gsup->pdp_infos));
|
||||
memcpy(gsup->pdp_infos,
|
||||
g_hlr->ps.pdp_profile.pdp_infos,
|
||||
sizeof(struct osmo_gsup_pdp_info) * g_hlr->ps.pdp_profile.num_pdp_infos);
|
||||
gsup->num_pdp_infos = g_hlr->ps.pdp_profile.num_pdp_infos;
|
||||
} else {
|
||||
uint8_t *apn_buf = talloc_size(talloc_ctx, APN_MAXLEN);
|
||||
osmo_gsup_configure_wildcard_apn(gsup, apn_buf, APN_MAXLEN);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
29
src/hlr.c
29
src/hlr.c
@@ -49,7 +49,6 @@
|
||||
#include <osmocom/hlr/rand.h>
|
||||
#include <osmocom/hlr/hlr_vty.h>
|
||||
#include <osmocom/hlr/hlr_ussd.h>
|
||||
#include <osmocom/hlr/hlr_sms.h>
|
||||
#include <osmocom/hlr/dgsm.h>
|
||||
#include <osmocom/hlr/proxy.h>
|
||||
#include <osmocom/hlr/lu_fsm.h>
|
||||
@@ -86,8 +85,6 @@ osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr)
|
||||
|
||||
llist_for_each_entry(co, &g_hlr->gs->clients, list) {
|
||||
struct osmo_gsup_message gsup = { };
|
||||
uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
|
||||
uint8_t apn[APN_MAXLEN];
|
||||
struct msgb *msg_out;
|
||||
uint8_t *peer;
|
||||
int peer_len;
|
||||
@@ -132,8 +129,7 @@ osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr)
|
||||
subscr->imsi, cn_domain == OSMO_GSUP_CN_DOMAIN_PS ? "PS" : "CS",
|
||||
osmo_quote_str(peer_compare, -1));
|
||||
|
||||
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, subscr->msisdn, msisdn_enc,
|
||||
sizeof(msisdn_enc), apn, sizeof(apn), cn_domain) != 0) {
|
||||
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi, subscr->msisdn, cn_domain, OTC_SELECT) != 0) {
|
||||
LOGP(DLGSUP, LOGL_ERROR,
|
||||
"IMSI='%s': Cannot notify GSUP client; could not create gsup message "
|
||||
"for %s:%u\n", subscr->imsi,
|
||||
@@ -423,9 +419,13 @@ static int rx_check_imei_req(struct osmo_gsup_req *req)
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
/* ThemWi change: report IMSI-IMEI correspondence in syslog */
|
||||
LOGP(DMAIN, LOGL_NOTICE, "IMEI REPORT: IMSI=%s has IMEI=%s\n",
|
||||
gsup->imsi, imei);
|
||||
/* Check if subscriber exists and print IMEI */
|
||||
LOGP(DMAIN, LOGL_INFO, "IMSI='%s': has IMEI = %s (consider setting 'store-imei')\n", gsup->imsi, imei);
|
||||
struct hlr_subscriber subscr;
|
||||
if (db_subscr_get_by_imsi(g_hlr->dbc, gsup->imsi, &subscr) < 0) {
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO, "IMSI unknown");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Accept all IMEIs */
|
||||
@@ -556,15 +556,6 @@ static int read_cb(struct osmo_gsup_conn *conn, struct msgb *msg)
|
||||
case OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST:
|
||||
rx_check_imei_req(req);
|
||||
break;
|
||||
case OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST:
|
||||
forward_mo_sms(req);
|
||||
break;
|
||||
case OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST:
|
||||
forward_mt_sms(req);
|
||||
break;
|
||||
case OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST:
|
||||
rx_ready_for_sm_req(req);
|
||||
break;
|
||||
default:
|
||||
LOGP(DMAIN, LOGL_DEBUG, "Unhandled GSUP message type %s\n",
|
||||
osmo_gsup_message_type_name(req->gsup.message_type));
|
||||
@@ -733,7 +724,7 @@ static void signal_hdlr(int signal)
|
||||
}
|
||||
|
||||
static const char vlr_copyright[] =
|
||||
"Copyright (C) 2016, 2017 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
|
||||
"Copyright (C) 2016-2023 by Harald Welte, sysmocom s.f.m.c. GmbH\r\n"
|
||||
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
|
||||
"This is free software: you are free to change and redistribute it.\r\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.\r\n";
|
||||
@@ -759,10 +750,8 @@ int main(int argc, char **argv)
|
||||
|
||||
g_hlr = talloc_zero(hlr_ctx, struct hlr);
|
||||
INIT_LLIST_HEAD(&g_hlr->euse_list);
|
||||
INIT_LLIST_HEAD(&g_hlr->smsc_list);
|
||||
INIT_LLIST_HEAD(&g_hlr->ss_sessions);
|
||||
INIT_LLIST_HEAD(&g_hlr->ussd_routes);
|
||||
INIT_LLIST_HEAD(&g_hlr->smsc_routes);
|
||||
INIT_LLIST_HEAD(&g_hlr->mslookup.server.local_site_services);
|
||||
g_hlr->db_file_path = talloc_strdup(g_hlr, HLR_DEFAULT_DB_FILE_PATH);
|
||||
g_hlr->mslookup.server.mdns.domain_suffix = talloc_strdup(g_hlr, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT);
|
||||
|
||||
277
src/hlr_sms.c
277
src/hlr_sms.c
@@ -1,277 +0,0 @@
|
||||
/* OsmoHLR SMS-over-GSUP routing implementation */
|
||||
|
||||
/* Author: Mychaela N. Falconia <falcon@freecalypso.org>, 2023 - however,
|
||||
* Mother Mychaela's contributions are NOT subject to copyright.
|
||||
* No rights reserved, all rights relinquished.
|
||||
*
|
||||
* Based on earlier unmerged work by Vadim Yanitskiy, 2019.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/gsup.h>
|
||||
#include <osmocom/gsm/gsm48_ie.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_11.h>
|
||||
|
||||
#include <osmocom/hlr/hlr.h>
|
||||
#include <osmocom/hlr/hlr_sms.h>
|
||||
#include <osmocom/hlr/gsup_server.h>
|
||||
#include <osmocom/hlr/gsup_router.h>
|
||||
#include <osmocom/hlr/logging.h>
|
||||
#include <osmocom/hlr/db.h>
|
||||
|
||||
/***********************************************************************
|
||||
* core data structures expressing config from VTY
|
||||
***********************************************************************/
|
||||
|
||||
struct hlr_smsc *smsc_find(struct hlr *hlr, const char *name)
|
||||
{
|
||||
struct hlr_smsc *smsc;
|
||||
|
||||
llist_for_each_entry(smsc, &hlr->smsc_list, list) {
|
||||
if (!strcmp(smsc->name, name))
|
||||
return smsc;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct hlr_smsc *smsc_alloc(struct hlr *hlr, const char *name)
|
||||
{
|
||||
struct hlr_smsc *smsc = smsc_find(hlr, name);
|
||||
if (smsc)
|
||||
return NULL;
|
||||
|
||||
smsc = talloc_zero(hlr, struct hlr_smsc);
|
||||
smsc->name = talloc_strdup(smsc, name);
|
||||
smsc->hlr = hlr;
|
||||
llist_add_tail(&smsc->list, &hlr->smsc_list);
|
||||
|
||||
return smsc;
|
||||
}
|
||||
|
||||
void smsc_del(struct hlr_smsc *smsc)
|
||||
{
|
||||
llist_del(&smsc->list);
|
||||
talloc_free(smsc);
|
||||
}
|
||||
|
||||
struct hlr_smsc_route *smsc_route_find(struct hlr *hlr, const char *num_addr)
|
||||
{
|
||||
struct hlr_smsc_route *rt;
|
||||
|
||||
llist_for_each_entry(rt, &hlr->smsc_routes, list) {
|
||||
if (!strcmp(rt->num_addr, num_addr))
|
||||
return rt;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct hlr_smsc_route *smsc_route_alloc(struct hlr *hlr, const char *num_addr,
|
||||
struct hlr_smsc *smsc)
|
||||
{
|
||||
struct hlr_smsc_route *rt;
|
||||
|
||||
if (smsc_route_find(hlr, num_addr))
|
||||
return NULL;
|
||||
|
||||
rt = talloc_zero(hlr, struct hlr_smsc_route);
|
||||
rt->num_addr = talloc_strdup(rt, num_addr);
|
||||
rt->smsc = smsc;
|
||||
llist_add_tail(&rt->list, &hlr->smsc_routes);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
void smsc_route_del(struct hlr_smsc_route *rt)
|
||||
{
|
||||
llist_del(&rt->list);
|
||||
talloc_free(rt);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* forwarding of MO SMS to SMSCs based on SM-RP-DA
|
||||
***********************************************************************/
|
||||
|
||||
static const struct hlr_smsc *find_smsc_route(const char *smsc_addr)
|
||||
{
|
||||
const struct hlr_smsc_route *rt;
|
||||
|
||||
rt = smsc_route_find(g_hlr, smsc_addr);
|
||||
if (rt)
|
||||
return rt->smsc;
|
||||
return g_hlr->smsc_default;
|
||||
}
|
||||
|
||||
static void respond_with_sm_rp_cause(struct osmo_gsup_req *req,
|
||||
uint8_t sm_rp_cause)
|
||||
{
|
||||
struct osmo_gsup_message rsp_msg = { };
|
||||
|
||||
rsp_msg.sm_rp_cause = &sm_rp_cause;
|
||||
osmo_gsup_req_respond(req, &rsp_msg, true, true);
|
||||
}
|
||||
|
||||
/* Short Message from MSC/VLR towards SMSC */
|
||||
void forward_mo_sms(struct osmo_gsup_req *req)
|
||||
{
|
||||
/* The length limit on the SMSC address is 20 digits, stated
|
||||
* indirectly in GSM 04.11 section 8.2.5.2. */
|
||||
uint8_t gsm48_decode_buffer[11];
|
||||
char smsc_addr[21];
|
||||
const struct hlr_smsc *smsc;
|
||||
struct osmo_cni_peer_id dest_peer;
|
||||
|
||||
/* Make sure SM-RP-DA (SMSC address) is present */
|
||||
if (req->gsup.sm_rp_da == NULL || !req->gsup.sm_rp_da_len) {
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO,
|
||||
"missing SM-RP-DA");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->gsup.sm_rp_da_type != OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR) {
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_INV_MAND_INFO,
|
||||
"SM-RP-DA type is not SMSC");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enforce the length constrainst on SM-RP-DA, as specified in
|
||||
* GSM 04.11 section 8.2.5.2. Also enforce absence of ToN/NPI
|
||||
* extension octets at the same time. */
|
||||
if (req->gsup.sm_rp_da_len < 2 || req->gsup.sm_rp_da_len > 11 ||
|
||||
!(req->gsup.sm_rp_da[0] & 0x80)) {
|
||||
/* This form of bogosity originates from the MS,
|
||||
* not from OsmoMSC or any other Osmocom network elements! */
|
||||
LOGP(DLSMS, LOGL_NOTICE,
|
||||
"Rx '%s' (IMSI-%s) contains invalid SM-RP-DA from MS\n",
|
||||
osmo_gsup_message_type_name(req->gsup.message_type),
|
||||
req->gsup.imsi);
|
||||
respond_with_sm_rp_cause(req, GSM411_RP_CAUSE_SEMANT_INC_MSG);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Decode SMSC address from SM-RP-DA */
|
||||
gsm48_decode_buffer[0] = req->gsup.sm_rp_da_len - 1;
|
||||
memcpy(gsm48_decode_buffer + 1, req->gsup.sm_rp_da + 1,
|
||||
req->gsup.sm_rp_da_len - 1);
|
||||
gsm48_decode_bcd_number2(smsc_addr, sizeof(smsc_addr),
|
||||
gsm48_decode_buffer,
|
||||
req->gsup.sm_rp_da_len, 0);
|
||||
|
||||
/* Look for a route to this SMSC */
|
||||
smsc = find_smsc_route(smsc_addr);
|
||||
if (smsc == NULL) {
|
||||
LOGP(DLSMS, LOGL_NOTICE,
|
||||
"Failed to find a route for '%s' (IMSI-%s, SMSC-Addr-%s)\n",
|
||||
osmo_gsup_message_type_name(req->gsup.message_type),
|
||||
req->gsup.imsi, smsc_addr);
|
||||
respond_with_sm_rp_cause(req,
|
||||
GSM411_RP_CAUSE_MO_NUM_UNASSIGNED);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We got the IPA name of our SMSC - forward the message */
|
||||
osmo_cni_peer_id_set(&dest_peer, OSMO_CNI_PEER_ID_IPA_NAME,
|
||||
(const uint8_t *) smsc->name,
|
||||
strlen(smsc->name) + 1);
|
||||
osmo_gsup_forward_to_local_peer(req->cb_data, &dest_peer, req, NULL);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* forwarding of MT SMS from SMSCs to MSC/VLR based on IMSI
|
||||
***********************************************************************/
|
||||
|
||||
void forward_mt_sms(struct osmo_gsup_req *req)
|
||||
{
|
||||
struct hlr_subscriber subscr;
|
||||
struct osmo_cni_peer_id dest_peer;
|
||||
int rc;
|
||||
|
||||
rc = db_subscr_get_by_imsi(g_hlr->dbc, req->gsup.imsi, &subscr);
|
||||
if (rc < 0) {
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMSI_UNKNOWN,
|
||||
"IMSI unknown");
|
||||
return;
|
||||
}
|
||||
/* is this subscriber currently attached to a VLR? */
|
||||
if (!subscr.vlr_number[0]) {
|
||||
osmo_gsup_req_respond_err(req, GMM_CAUSE_IMPL_DETACHED,
|
||||
"subscriber not attached to a VLR");
|
||||
return;
|
||||
}
|
||||
osmo_cni_peer_id_set(&dest_peer, OSMO_CNI_PEER_ID_IPA_NAME,
|
||||
(const uint8_t *) subscr.vlr_number,
|
||||
strlen(subscr.vlr_number) + 1);
|
||||
osmo_gsup_forward_to_local_peer(req->cb_data, &dest_peer, req, NULL);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* READY-FOR-SM handling
|
||||
*
|
||||
* An MSC indicates that an MS is ready to receive messages. If one
|
||||
* or more SMSCs have previously tried to send MT SMS to this MS and
|
||||
* failed, we should pass this READY-FOR-SM message to them so they
|
||||
* can resend their queued SMS right away. But which SMSC do we
|
||||
* forward the message to? 3GPP specs call for a complicated system
|
||||
* where the HLR remembers which SMSCs have tried and failed to deliver
|
||||
* MT SMS, and those SMSCs then get notified - but that design is too
|
||||
* much complexity for the current state of Osmocom. So we keep it
|
||||
* simple: we iterate over all configured SMSCs and forward a copy
|
||||
* of the READY-FOR-SM.req message to each.
|
||||
*
|
||||
* Routing of responses is another problem: the MSC that sent
|
||||
* READY-FOR-SM.req expects only one response, and one can even argue
|
||||
* that the operation is a "success" from the perspective of the MS
|
||||
* irrespective of whether each given SMSC handled the notification
|
||||
* successfully or not. Hence our approach: we always return success
|
||||
* to the MS, and when we forward copies of READY-FOR-SM.req to SMSCs,
|
||||
* we list the HLR as the message source - this way SMSC responses
|
||||
* will terminate at this HLR and won't be forwarded to the MSC.
|
||||
***********************************************************************/
|
||||
|
||||
static void forward_req_copy_to_smsc(const struct osmo_gsup_req *req,
|
||||
const struct hlr_smsc *smsc)
|
||||
{
|
||||
const char *my_ipa_name = g_hlr->gsup_unit_name.serno;
|
||||
struct osmo_gsup_message forward = req->gsup;
|
||||
struct osmo_ipa_name smsc_ipa_name;
|
||||
|
||||
/* set the source to this HLR */
|
||||
forward.source_name = (const uint8_t *) my_ipa_name;
|
||||
forward.source_name_len = strlen(my_ipa_name) + 1;
|
||||
|
||||
/* send it off */
|
||||
LOG_GSUP_REQ(req, LOGL_INFO, "Forwarding source-reset copy to %s\n",
|
||||
smsc->name);
|
||||
osmo_ipa_name_set(&smsc_ipa_name, (const uint8_t *) smsc->name,
|
||||
strlen(smsc->name) + 1);
|
||||
osmo_gsup_enc_send_to_ipa_name(g_hlr->gs, &smsc_ipa_name, &forward);
|
||||
}
|
||||
|
||||
void rx_ready_for_sm_req(struct osmo_gsup_req *req)
|
||||
{
|
||||
struct hlr_smsc *smsc;
|
||||
|
||||
/* fan request msg out to all SMSCs */
|
||||
llist_for_each_entry(smsc, &g_hlr->smsc_list, list)
|
||||
forward_req_copy_to_smsc(req, smsc);
|
||||
|
||||
/* send OK response to the MSC and the MS */
|
||||
osmo_gsup_req_respond_msgt(req, OSMO_GSUP_MSGT_READY_FOR_SM_RESULT,
|
||||
true);
|
||||
}
|
||||
@@ -122,9 +122,40 @@ void ussd_route_del(struct hlr_ussd_route *rt)
|
||||
talloc_free(rt);
|
||||
}
|
||||
|
||||
static struct hlr_ussd_route *ussd_route_lookup_7bit(struct hlr *hlr, const char *ussd_code)
|
||||
static struct hlr_ussd_route *ussd_route_lookup_for_req(struct hlr *hlr, const struct ss_request *req)
|
||||
{
|
||||
const uint8_t cgroup = req->ussd_data_dcs >> 4;
|
||||
const uint8_t lang = req->ussd_data_dcs & 0x0f;
|
||||
char ussd_code[GSM0480_USSD_7BIT_STRING_LEN];
|
||||
struct hlr_ussd_route *rt;
|
||||
|
||||
ussd_code[0] = '\0';
|
||||
|
||||
/* We support only the Coding Group 0 (GSM 7-bit default alphabeet). In fact,
|
||||
* the USSD request is usually limited to [*#0-9], so we don't really need to
|
||||
* support other coding groups and languages. */
|
||||
switch (cgroup) {
|
||||
case 0:
|
||||
/* The Language is usually set to '1111'B (unspecified), but some UEs
|
||||
* are known to indicate '0000'B (German). */
|
||||
if (lang != 0x0f) {
|
||||
LOGP(DSS, LOGL_NOTICE, "USSD DataCodingScheme (0x%02x): "
|
||||
"the Language is usually set to 15 (unspecified), "
|
||||
"but the request indicates %u - ignoring this\n",
|
||||
req->ussd_data_dcs, lang);
|
||||
/* do not abort, attempt to decode as if it was '1111'B */
|
||||
}
|
||||
|
||||
gsm_7bit_decode_n_ussd(&ussd_code[0], sizeof(ussd_code),
|
||||
req->ussd_data, (req->ussd_data_len * 8) / 7);
|
||||
break;
|
||||
default:
|
||||
LOGP(DSS, LOGL_ERROR, "USSD DataCodingScheme (0x%02x): "
|
||||
"Coding Group %u is not supported, expecting Coding Group 0\n",
|
||||
req->ussd_data_dcs, cgroup);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
llist_for_each_entry(rt, &hlr->ussd_routes, list) {
|
||||
if (!strncmp(ussd_code, rt->prefix, strlen(rt->prefix))) {
|
||||
LOGP(DSS, LOGL_DEBUG, "Found %s '%s' (prefix '%s') for USSD "
|
||||
@@ -355,7 +386,7 @@ static int handle_ussd_own_msisdn(struct ss_session *ss,
|
||||
if (strlen(subscr.msisdn) == 0)
|
||||
snprintf(buf, sizeof(buf), "You have no MSISDN!");
|
||||
else
|
||||
snprintf(buf, sizeof(buf), "Your phone number is %s", subscr.msisdn);
|
||||
snprintf(buf, sizeof(buf), "Your extension is %s", subscr.msisdn);
|
||||
ss_tx_to_ms_ussd_7bit(ss, req->invoke_id, buf);
|
||||
break;
|
||||
case -ENOENT:
|
||||
@@ -603,7 +634,7 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
|
||||
} else {
|
||||
/* VLR->EUSE: MO USSD. VLR is known ('conn'), EUSE is to be resolved */
|
||||
struct hlr_ussd_route *rt;
|
||||
rt = ussd_route_lookup_7bit(hlr, (const char *) req.ussd_text);
|
||||
rt = ussd_route_lookup_for_req(hlr, &req);
|
||||
if (rt) {
|
||||
if (rt->is_external) {
|
||||
ss->is_external = true;
|
||||
@@ -631,7 +662,8 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
|
||||
if (!ss) {
|
||||
LOGP(DSS, LOGL_ERROR, "%s/0x%08x: CONTINUE for unknown SS session\n",
|
||||
gsup->imsi, gsup->session_id);
|
||||
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_INV_MAND_INFO, "CONTINUE for unknown SS session");
|
||||
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_MSGT_INCOMP_P_STATE,
|
||||
"CONTINUE for unknown SS session");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -652,6 +684,8 @@ void rx_proc_ss_req(struct osmo_gsup_req *gsup_req)
|
||||
if (!ss) {
|
||||
LOGP(DSS, LOGL_ERROR, "%s/0x%08x: END for unknown SS session\n",
|
||||
gsup->imsi, gsup->session_id);
|
||||
osmo_gsup_req_respond_err(gsup_req, GMM_CAUSE_MSGT_INCOMP_P_STATE,
|
||||
"END for unknown SS session");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -682,4 +716,5 @@ void rx_proc_ss_error(struct osmo_gsup_req *req)
|
||||
{
|
||||
LOGP(DSS, LOGL_NOTICE, "%s/0x%08x: Process SS ERROR (%s)\n", req->gsup.imsi, req->gsup.session_id,
|
||||
osmo_gsup_session_state_name(req->gsup.session_state));
|
||||
osmo_gsup_req_free(req);
|
||||
}
|
||||
|
||||
390
src/hlr_vty.c
390
src/hlr_vty.c
@@ -26,9 +26,12 @@
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/stats.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
@@ -41,7 +44,6 @@
|
||||
#include <osmocom/hlr/hlr_vty.h>
|
||||
#include <osmocom/hlr/hlr_vty_subscr.h>
|
||||
#include <osmocom/hlr/hlr_ussd.h>
|
||||
#include <osmocom/hlr/hlr_sms.h>
|
||||
#include <osmocom/hlr/gsup_server.h>
|
||||
|
||||
static const struct value_string gsm48_gmm_cause_vty_names[] = {
|
||||
@@ -104,6 +106,182 @@ DEFUN(cfg_gsup,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct cmd_node ps_node = {
|
||||
PS_NODE,
|
||||
"%s(config-hlr-ps)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
DEFUN(cfg_ps,
|
||||
cfg_ps_cmd,
|
||||
"ps",
|
||||
"Configure the PS options")
|
||||
{
|
||||
vty->node = PS_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct cmd_node ps_pdp_profiles_node = {
|
||||
PS_PDP_PROFILES_NODE,
|
||||
"%s(config-hlr-ps-pdp-profiles)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
DEFUN(cfg_ps_pdp_profiles,
|
||||
cfg_ps_pdp_profiles_cmd,
|
||||
"pdp-profiles default",
|
||||
"Define a PDP profile set.\n"
|
||||
"Define the global default profile.\n")
|
||||
{
|
||||
g_hlr->ps.pdp_profile.enabled = true;
|
||||
|
||||
vty->node = PS_PDP_PROFILES_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_ps_pdp_profiles,
|
||||
cfg_no_ps_pdp_profiles_cmd,
|
||||
"no pdp-profiles default",
|
||||
NO_STR
|
||||
"Delete PDP profile.\n"
|
||||
"Unique identifier for this PDP profile set.\n")
|
||||
{
|
||||
g_hlr->ps.pdp_profile.enabled = false;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct cmd_node ps_pdp_profiles_profile_node = {
|
||||
PS_PDP_PROFILES_PROFILE_NODE,
|
||||
"%s(config-hlr-ps-pdp-profile)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
|
||||
/* context_id == 0 means the slot is free */
|
||||
struct osmo_gsup_pdp_info *get_pdp_profile(uint8_t context_id)
|
||||
{
|
||||
for (int i = 0; i < OSMO_GSUP_MAX_NUM_PDP_INFO; i++) {
|
||||
struct osmo_gsup_pdp_info *info = &g_hlr->ps.pdp_profile.pdp_infos[i];
|
||||
if (info->context_id == context_id)
|
||||
return info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct osmo_gsup_pdp_info *create_pdp_profile(uint8_t context_id)
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info = get_pdp_profile(0);
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->context_id = context_id;
|
||||
info->have_info = 1;
|
||||
|
||||
g_hlr->ps.pdp_profile.num_pdp_infos++;
|
||||
return info;
|
||||
}
|
||||
|
||||
void destroy_pdp_profile(struct osmo_gsup_pdp_info *info)
|
||||
{
|
||||
info->context_id = 0;
|
||||
if (info->apn_enc)
|
||||
talloc_free((void *) info->apn_enc);
|
||||
|
||||
g_hlr->ps.pdp_profile.num_pdp_infos--;
|
||||
memset(info, 0, sizeof(*info));
|
||||
}
|
||||
|
||||
DEFUN(cfg_ps_pdp_profiles_profile,
|
||||
cfg_ps_pdp_profiles_profile_cmd,
|
||||
"profile <1-10>",
|
||||
"Configure a PDP profile\n"
|
||||
"Unique PDP context identifier. The lowest profile will be used as default context.\n")
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info;
|
||||
uint8_t context_id = atoi(argv[0]);
|
||||
|
||||
info = get_pdp_profile(context_id);
|
||||
if (!info) {
|
||||
info = create_pdp_profile(context_id);
|
||||
if (!info) {
|
||||
vty_out(vty, "Failed to create profile %d!%s", context_id, VTY_NEWLINE);
|
||||
return CMD_ERR_INCOMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
vty->node = PS_PDP_PROFILES_PROFILE_NODE;
|
||||
vty->index = info;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_ps_pdp_profiles_profile,
|
||||
cfg_no_ps_pdp_profiles_profile_cmd,
|
||||
"no profile <1-10>",
|
||||
NO_STR
|
||||
"Delete a PDP profile\n"
|
||||
"Unique PDP context identifier. The lowest profile will be used as default context.\n")
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info;
|
||||
uint8_t context_id = atoi(argv[0]);
|
||||
|
||||
info = get_pdp_profile(context_id);
|
||||
if (info)
|
||||
destroy_pdp_profile(info);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ps_pdp_profile_apn, cfg_ps_pdp_profile_apn_cmd,
|
||||
"apn ID",
|
||||
"Configure the APN.\n"
|
||||
"APN name or * for wildcard apn.\n")
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info = vty->index;
|
||||
const char *apn_name = argv[0];
|
||||
|
||||
/* apn encoded takes one more byte than strlen() */
|
||||
size_t apn_enc_len = strlen(apn_name) + 1;
|
||||
uint8_t *apn_enc;
|
||||
int ret;
|
||||
|
||||
if (apn_enc_len > APN_MAXLEN) {
|
||||
vty_out(vty, "APN name is too long '%s'. Max is %d!%s", apn_name, APN_MAXLEN, VTY_NEWLINE);
|
||||
return CMD_ERR_INCOMPLETE;
|
||||
}
|
||||
|
||||
info->apn_enc = apn_enc = (uint8_t *) talloc_zero_size(g_hlr, apn_enc_len);
|
||||
ret = info->apn_enc_len = osmo_apn_from_str(apn_enc, apn_enc_len, apn_name);
|
||||
if (ret < 0) {
|
||||
talloc_free(apn_enc);
|
||||
info->apn_enc = NULL;
|
||||
info->apn_enc_len = 0;
|
||||
vty_out(vty, "Invalid APN name %s!", apn_name);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_ps_pdp_profile_apn, cfg_no_ps_pdp_profile_apn_cmd,
|
||||
"no apn",
|
||||
NO_STR
|
||||
"Delete the APN.\n")
|
||||
{
|
||||
struct osmo_gsup_pdp_info *info = vty->index;
|
||||
if (info->apn_enc) {
|
||||
talloc_free((void *) info->apn_enc);
|
||||
info->apn_enc = NULL;
|
||||
info->apn_enc_len = 0;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int config_write_hlr(struct vty *vty)
|
||||
{
|
||||
vty_out(vty, "hlr%s", VTY_NEWLINE);
|
||||
@@ -150,6 +328,37 @@ static int config_write_hlr_gsup(struct vty *vty)
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_hlr_ps(struct vty *vty)
|
||||
{
|
||||
vty_out(vty, " ps%s", VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_hlr_ps_pdp_profiles(struct vty *vty)
|
||||
{
|
||||
char apn[APN_MAXLEN + 1] = {};
|
||||
|
||||
if (!g_hlr->ps.pdp_profile.enabled)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
vty_out(vty, " pdp-profiles default%s", VTY_NEWLINE);
|
||||
for (int i = 0; i < g_hlr->ps.pdp_profile.num_pdp_infos; i++) {
|
||||
struct osmo_gsup_pdp_info *pdp_info = &g_hlr->ps.pdp_profile.pdp_infos[i];
|
||||
if (!pdp_info->context_id)
|
||||
continue;
|
||||
|
||||
vty_out(vty, " profile %d%s", pdp_info->context_id, VTY_NEWLINE);
|
||||
if (!pdp_info->have_info)
|
||||
continue;
|
||||
|
||||
if (pdp_info->apn_enc && pdp_info->apn_enc_len) {
|
||||
osmo_apn_to_str(apn, pdp_info->apn_enc, pdp_info->apn_enc_len);
|
||||
vty_out(vty, " apn %s%s", apn, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void show_one_conn(struct vty *vty, const struct osmo_gsup_conn *conn)
|
||||
{
|
||||
const struct ipa_server_conn *isc = conn->conn;
|
||||
@@ -213,6 +422,8 @@ DEFUN(cfg_hlr_gsup_ipa_name,
|
||||
* USSD Entity
|
||||
***********************************************************************/
|
||||
|
||||
#include <osmocom/hlr/hlr_ussd.h>
|
||||
|
||||
#define USSD_STR "USSD Configuration\n"
|
||||
#define UROUTE_STR "Routing Configuration\n"
|
||||
#define PREFIX_STR "Prefix-Matching Route\n" "USSD Prefix\n"
|
||||
@@ -399,160 +610,6 @@ DEFUN(cfg_ncss_guard_timeout, cfg_ncss_guard_timeout_cmd,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Routing of SM-RL to GSUP-attached SMSCs
|
||||
***********************************************************************/
|
||||
|
||||
#define SMSC_STR "Configuration of GSUP routing to SMSCs\n"
|
||||
|
||||
struct cmd_node smsc_node = {
|
||||
SMSC_NODE,
|
||||
"%s(config-hlr-smsc)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
DEFUN(cfg_smsc_entity, cfg_smsc_entity_cmd,
|
||||
"smsc entity NAME",
|
||||
SMSC_STR
|
||||
"Configure a particular external SMSC\n"
|
||||
"IPA name of the external SMSC\n")
|
||||
{
|
||||
struct hlr_smsc *smsc;
|
||||
const char *id = argv[0];
|
||||
|
||||
smsc = smsc_find(g_hlr, id);
|
||||
if (!smsc) {
|
||||
smsc = smsc_alloc(g_hlr, id);
|
||||
if (!smsc)
|
||||
return CMD_WARNING;
|
||||
}
|
||||
vty->index = smsc;
|
||||
vty->index_sub = &smsc->description;
|
||||
vty->node = SMSC_NODE;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_smsc_entity, cfg_no_smsc_entity_cmd,
|
||||
"no smsc entity NAME",
|
||||
NO_STR SMSC_STR "Remove a particular external SMSC\n"
|
||||
"IPA name of the external SMSC\n")
|
||||
{
|
||||
struct hlr_smsc *smsc = smsc_find(g_hlr, argv[0]);
|
||||
if (!smsc) {
|
||||
vty_out(vty, "%% Cannot remove non-existent SMSC %s%s",
|
||||
argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
if (g_hlr->smsc_default == smsc) {
|
||||
vty_out(vty,
|
||||
"%% Cannot remove SMSC %s, it is the default route%s",
|
||||
argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
smsc_del(smsc);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_smsc_route, cfg_smsc_route_cmd,
|
||||
"smsc route NUMBER NAME",
|
||||
SMSC_STR
|
||||
"Configure GSUP route to a particular SMSC\n"
|
||||
"Numeric address of this SMSC, must match EF.SMSP programming in SIMs\n"
|
||||
"IPA name of the external SMSC\n")
|
||||
{
|
||||
struct hlr_smsc *smsc = smsc_find(g_hlr, argv[1]);
|
||||
struct hlr_smsc_route *rt = smsc_route_find(g_hlr, argv[0]);
|
||||
if (rt) {
|
||||
vty_out(vty,
|
||||
"%% Cannot add [another?] route for SMSC address %s%s",
|
||||
argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
if (!smsc) {
|
||||
vty_out(vty, "%% Cannot find SMSC '%s'%s", argv[1],
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
smsc_route_alloc(g_hlr, argv[0], smsc);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_smsc_route, cfg_no_smsc_route_cmd,
|
||||
"no smsc route NUMBER",
|
||||
NO_STR SMSC_STR "Remove GSUP route to a particular SMSC\n"
|
||||
"Numeric address of the SMSC\n")
|
||||
{
|
||||
struct hlr_smsc_route *rt = smsc_route_find(g_hlr, argv[0]);
|
||||
if (!rt) {
|
||||
vty_out(vty, "%% Cannot find route for SMSC address %s%s",
|
||||
argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
smsc_route_del(rt);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_smsc_defroute, cfg_smsc_defroute_cmd,
|
||||
"smsc default-route NAME",
|
||||
SMSC_STR
|
||||
"Configure default SMSC route for unknown SMSC numeric addresses\n"
|
||||
"IPA name of the external SMSC\n")
|
||||
{
|
||||
struct hlr_smsc *smsc;
|
||||
|
||||
smsc = smsc_find(g_hlr, argv[0]);
|
||||
if (!smsc) {
|
||||
vty_out(vty, "%% Cannot find SMSC %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (g_hlr->smsc_default != smsc) {
|
||||
vty_out(vty, "Switching default route from %s to %s%s",
|
||||
g_hlr->smsc_default ? g_hlr->smsc_default->name : "<none>",
|
||||
smsc->name, VTY_NEWLINE);
|
||||
g_hlr->smsc_default = smsc;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_smsc_defroute, cfg_no_smsc_defroute_cmd,
|
||||
"no smsc default-route",
|
||||
NO_STR SMSC_STR
|
||||
"Remove default SMSC route for unknown SMSC numeric addresses\n")
|
||||
{
|
||||
g_hlr->smsc_default = NULL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void dump_one_smsc(struct vty *vty, struct hlr_smsc *smsc)
|
||||
{
|
||||
vty_out(vty, " smsc entity %s%s", smsc->name, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
static int config_write_smsc(struct vty *vty)
|
||||
{
|
||||
struct hlr_smsc *smsc;
|
||||
struct hlr_smsc_route *rt;
|
||||
|
||||
llist_for_each_entry(smsc, &g_hlr->smsc_list, list)
|
||||
dump_one_smsc(vty, smsc);
|
||||
|
||||
llist_for_each_entry(rt, &g_hlr->smsc_routes, list) {
|
||||
vty_out(vty, " smsc route %s %s%s", rt->num_addr,
|
||||
rt->smsc->name, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
if (g_hlr->smsc_default)
|
||||
vty_out(vty, " smsc default-route %s%s",
|
||||
g_hlr->smsc_default->name, VTY_NEWLINE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFUN(cfg_reject_cause, cfg_reject_cause_cmd,
|
||||
"reject-cause TYPE CAUSE", "") /* Dynamically Generated */
|
||||
@@ -691,6 +748,20 @@ void hlr_vty_init(void *hlr_ctx)
|
||||
install_element(GSUP_NODE, &cfg_hlr_gsup_bind_ip_cmd);
|
||||
install_element(GSUP_NODE, &cfg_hlr_gsup_ipa_name_cmd);
|
||||
|
||||
/* PS */
|
||||
install_node(&ps_node, config_write_hlr_ps);
|
||||
install_element(HLR_NODE, &cfg_ps_cmd);
|
||||
|
||||
install_node(&ps_pdp_profiles_node, config_write_hlr_ps_pdp_profiles);
|
||||
install_element(PS_NODE, &cfg_ps_pdp_profiles_cmd);
|
||||
install_element(PS_NODE, &cfg_no_ps_pdp_profiles_cmd);
|
||||
|
||||
install_node(&ps_pdp_profiles_profile_node, NULL);
|
||||
install_element(PS_PDP_PROFILES_NODE, &cfg_ps_pdp_profiles_profile_cmd);
|
||||
install_element(PS_PDP_PROFILES_NODE, &cfg_no_ps_pdp_profiles_profile_cmd);
|
||||
install_element(PS_PDP_PROFILES_PROFILE_NODE, &cfg_ps_pdp_profile_apn_cmd);
|
||||
install_element(PS_PDP_PROFILES_PROFILE_NODE, &cfg_no_ps_pdp_profile_apn_cmd);
|
||||
|
||||
install_element(HLR_NODE, &cfg_database_cmd);
|
||||
|
||||
install_element(HLR_NODE, &cfg_euse_cmd);
|
||||
@@ -702,15 +773,6 @@ void hlr_vty_init(void *hlr_ctx)
|
||||
install_element(HLR_NODE, &cfg_ussd_defaultroute_cmd);
|
||||
install_element(HLR_NODE, &cfg_ussd_no_defaultroute_cmd);
|
||||
install_element(HLR_NODE, &cfg_ncss_guard_timeout_cmd);
|
||||
|
||||
install_node(&smsc_node, config_write_smsc);
|
||||
install_element(HLR_NODE, &cfg_smsc_entity_cmd);
|
||||
install_element(HLR_NODE, &cfg_no_smsc_entity_cmd);
|
||||
install_element(HLR_NODE, &cfg_smsc_route_cmd);
|
||||
install_element(HLR_NODE, &cfg_no_smsc_route_cmd);
|
||||
install_element(HLR_NODE, &cfg_smsc_defroute_cmd);
|
||||
install_element(HLR_NODE, &cfg_no_smsc_defroute_cmd);
|
||||
|
||||
install_element(HLR_NODE, &cfg_reject_cause_cmd);
|
||||
install_element(HLR_NODE, &cfg_store_imei_cmd);
|
||||
install_element(HLR_NODE, &cfg_no_store_imei_cmd);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* OsmoHLR subscriber management VTY implementation */
|
||||
/* (C) 2017 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
/* (C) 2017-2023 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
|
||||
@@ -77,8 +77,8 @@ static void dump_last_lu_seen(struct vty *vty, const char *domain_label, time_t
|
||||
static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
||||
{
|
||||
int rc;
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
|
||||
vty_out(vty, " ID: %"PRIu64"%s", subscr->id, VTY_NEWLINE);
|
||||
|
||||
@@ -137,12 +137,12 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
||||
|
||||
if (aud2g.type != OSMO_AUTH_TYPE_NONE && aud2g.type != OSMO_AUTH_TYPE_GSM) {
|
||||
vty_out(vty, "%% Error: 2G auth data is not of type 'GSM'%s", VTY_NEWLINE);
|
||||
aud2g = (struct osmo_sub_auth_data){};
|
||||
aud2g = (struct osmo_sub_auth_data2){};
|
||||
}
|
||||
|
||||
if (aud3g.type != OSMO_AUTH_TYPE_NONE && aud3g.type != OSMO_AUTH_TYPE_UMTS) {
|
||||
vty_out(vty, "%% Error: 3G auth data is not of type 'UMTS'%s", VTY_NEWLINE);
|
||||
aud3g = (struct osmo_sub_auth_data){};
|
||||
aud3g = (struct osmo_sub_auth_data2){};
|
||||
}
|
||||
|
||||
if (aud2g.algo != OSMO_AUTH_ALG_NONE && aud2g.type != OSMO_AUTH_TYPE_NONE) {
|
||||
@@ -154,9 +154,10 @@ static void subscr_dump_full_vty(struct vty *vty, struct hlr_subscriber *subscr)
|
||||
|
||||
if (aud3g.algo != OSMO_AUTH_ALG_NONE && aud3g.type != OSMO_AUTH_TYPE_NONE) {
|
||||
vty_out(vty, " 3G auth: %s%s", osmo_auth_alg_name(aud3g.algo), VTY_NEWLINE);
|
||||
vty_out(vty, " K=%s%s", hexdump_buf(aud3g.u.umts.k), VTY_NEWLINE);
|
||||
vty_out(vty, " K=%s%s",
|
||||
osmo_hexdump_nospc(aud3g.u.umts.k, aud3g.u.umts.k_len), VTY_NEWLINE);
|
||||
vty_out(vty, " %s=%s%s", aud3g.u.umts.opc_is_op? "OP" : "OPC",
|
||||
hexdump_buf(aud3g.u.umts.opc), VTY_NEWLINE);
|
||||
osmo_hexdump_nospc(aud3g.u.umts.opc, aud3g.u.umts.opc_len), VTY_NEWLINE);
|
||||
vty_out(vty, " IND-bitlen=%u", aud3g.u.umts.ind_bitlen);
|
||||
if (aud3g.u.umts.sqn)
|
||||
vty_out(vty, " last-SQN=%"PRIu64, aud3g.u.umts.sqn);
|
||||
@@ -460,20 +461,27 @@ static bool is_hexkey_valid(struct vty *vty, const char *label,
|
||||
return false;
|
||||
}
|
||||
|
||||
#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor)"
|
||||
#define AUTH_ALG_TYPES_2G "(comp128v1|comp128v2|comp128v3|xor-2g)"
|
||||
#define AUTH_ALG_TYPES_2G_HELP \
|
||||
"Use COMP128v1 algorithm\n" \
|
||||
"Use COMP128v2 algorithm\n" \
|
||||
"Use COMP128v3 algorithm\n" \
|
||||
"Use XOR algorithm\n"
|
||||
"Use XOR-2G algorithm\n"
|
||||
|
||||
#define AUTH_ALG_TYPES_3G "milenage"
|
||||
#define AUTH_ALG_TYPES_3G "(milenage|tuak)"
|
||||
#define AUTH_ALG_TYPES_3G_HELP \
|
||||
"Use Milenage algorithm\n"
|
||||
"Use Milenage algorithm\n" \
|
||||
"Use TUAK algorithm\n"
|
||||
|
||||
bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
|
||||
int *minlen, int *maxlen)
|
||||
int *minlen, int *maxlen, int *minlen_opc, int *maxlen_opc)
|
||||
{
|
||||
/* Default: no OP[c]. True for all 2G algorithms, and 3G-XOR. Overridden below for real 3G AKA algorithms. */
|
||||
if (minlen_opc)
|
||||
*minlen_opc = 0;
|
||||
if (maxlen_opc)
|
||||
*maxlen_opc = 0;
|
||||
|
||||
if (!strcasecmp(alg_str, "none")) {
|
||||
*algo = OSMO_AUTH_ALG_NONE;
|
||||
*minlen = *maxlen = 0;
|
||||
@@ -486,13 +494,28 @@ bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
|
||||
} else if (!strcasecmp(alg_str, "comp128v3")) {
|
||||
*algo = OSMO_AUTH_ALG_COMP128v3;
|
||||
*minlen = *maxlen = A38_COMP128_KEY_LEN;
|
||||
} else if (!strcasecmp(alg_str, "xor")) {
|
||||
*algo = OSMO_AUTH_ALG_XOR;
|
||||
} else if (!strcasecmp(alg_str, "xor-3g")) {
|
||||
*algo = OSMO_AUTH_ALG_XOR_3G;
|
||||
*minlen = A38_XOR_MIN_KEY_LEN;
|
||||
*maxlen = A38_XOR_MAX_KEY_LEN;
|
||||
} else if (!strcasecmp(alg_str, "xor-2g")) {
|
||||
*algo = OSMO_AUTH_ALG_XOR_2G;
|
||||
*minlen = *maxlen = A38_XOR2G_KEY_LEN;
|
||||
} else if (!strcasecmp(alg_str, "milenage")) {
|
||||
*algo = OSMO_AUTH_ALG_MILENAGE;
|
||||
*minlen = *maxlen = MILENAGE_KEY_LEN;
|
||||
if (minlen_opc)
|
||||
*minlen_opc = MILENAGE_KEY_LEN;
|
||||
if (maxlen_opc)
|
||||
*maxlen_opc = MILENAGE_KEY_LEN;
|
||||
} else if (!strcasecmp(alg_str, "tuak")) {
|
||||
*algo = OSMO_AUTH_ALG_TUAK;
|
||||
*minlen = 16;
|
||||
*maxlen = 32;
|
||||
if (minlen_opc)
|
||||
*minlen_opc = 32;
|
||||
if (maxlen_opc)
|
||||
*maxlen_opc = 32;
|
||||
} else
|
||||
return false;
|
||||
return true;
|
||||
@@ -548,7 +571,7 @@ DEFUN(subscriber_aud2g,
|
||||
.u.gsm.ki = ki,
|
||||
};
|
||||
|
||||
if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen)) {
|
||||
if (!auth_algo_parse(alg_type, &aud2g.algo, &minlen, &maxlen, NULL, NULL)) {
|
||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -607,21 +630,21 @@ DEFUN(subscriber_aud3g,
|
||||
SUBSCR_UPDATE_HELP
|
||||
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
|
||||
AUTH_ALG_TYPES_3G_HELP
|
||||
"Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
|
||||
"Set OP key\n" "Set OPC key\n" "OP or OPC as 32 hexadecimal characters\n"
|
||||
"Set Encryption Key K\n" "K as 32/64 hexadecimal characters\n"
|
||||
"Set OP key\n" "Set OPC key\n" "OP or OPC as 32/64 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 minlen = 0, minlen_opc = 0;
|
||||
int maxlen = 0, maxlen_opc = 0;
|
||||
int rc;
|
||||
const char *id_type = argv[0];
|
||||
const char *id = argv[1];
|
||||
const char *alg_type = AUTH_ALG_TYPES_3G;
|
||||
const char *k = argv[2];
|
||||
bool opc_is_op = (strcasecmp("op", argv[3]) == 0);
|
||||
const char *op_opc = argv[4];
|
||||
int ind_bitlen = argc > 6? atoi(argv[6]) : 5;
|
||||
const char *alg_type = argv[2];
|
||||
const char *k = argv[3];
|
||||
bool opc_is_op = (strcasecmp("op", argv[4]) == 0);
|
||||
const char *op_opc = argv[5];
|
||||
int ind_bitlen = argc > 7 ? atoi(argv[7]) : 5;
|
||||
struct sub_auth_data_str aud3g = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.u.umts = {
|
||||
@@ -632,7 +655,7 @@ DEFUN(subscriber_aud3g,
|
||||
},
|
||||
};
|
||||
|
||||
if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen)) {
|
||||
if (!auth_algo_parse(alg_type, &aud3g.algo, &minlen, &maxlen, &minlen_opc, &maxlen_opc)) {
|
||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", alg_type, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
@@ -640,8 +663,7 @@ DEFUN(subscriber_aud3g,
|
||||
if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
|
||||
return CMD_WARNING;
|
||||
|
||||
if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc,
|
||||
MILENAGE_KEY_LEN, MILENAGE_KEY_LEN))
|
||||
if (!is_hexkey_valid(vty, opc_is_op ? "OP" : "OPC", aud3g.u.umts.opc, minlen_opc, maxlen_opc))
|
||||
return CMD_WARNING;
|
||||
|
||||
if (get_subscr_by_argv(vty, id_type, id, &subscr))
|
||||
@@ -659,11 +681,11 @@ DEFUN(subscriber_aud3g,
|
||||
|
||||
DEFUN(subscriber_aud3g_xor,
|
||||
subscriber_aud3g_xor_cmd,
|
||||
SUBSCR_UPDATE "aud3g xor k K"
|
||||
SUBSCR_UPDATE "aud3g xor-3g k K"
|
||||
" [ind-bitlen] [<0-28>]",
|
||||
SUBSCR_UPDATE_HELP
|
||||
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
|
||||
"Use XOR algorithm\n"
|
||||
"Use XOR-3G algorithm\n"
|
||||
"Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
|
||||
"Set IND bit length\n" "IND bit length value (default: 5)\n")
|
||||
{
|
||||
@@ -685,8 +707,8 @@ DEFUN(subscriber_aud3g_xor,
|
||||
},
|
||||
};
|
||||
|
||||
if (!auth_algo_parse("xor", &aud3g.algo, &minlen, &maxlen)) {
|
||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor", VTY_NEWLINE);
|
||||
if (!auth_algo_parse("xor-3g", &aud3g.algo, &minlen, &maxlen, NULL, NULL)) {
|
||||
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor-3g", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
|
||||
@@ -241,13 +241,11 @@ static void lu_fsm_wait_insert_data_result_onenter(struct osmo_fsm_inst *fi, uin
|
||||
struct lu *lu = fi->priv;
|
||||
struct hlr_subscriber *subscr = &lu->subscr;
|
||||
struct osmo_gsup_message gsup;
|
||||
uint8_t msisdn_enc[OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN];
|
||||
uint8_t apn[APN_MAXLEN];
|
||||
|
||||
if (osmo_gsup_create_insert_subscriber_data_msg(&gsup, subscr->imsi,
|
||||
subscr->msisdn, msisdn_enc, sizeof(msisdn_enc),
|
||||
apn, sizeof(apn),
|
||||
lu->is_ps? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS)) {
|
||||
subscr->msisdn,
|
||||
lu->is_ps ? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS,
|
||||
OTC_SELECT)) {
|
||||
lu_failure(lu, GMM_CAUSE_NET_FAIL, "cannot encode Insert Subscriber Data message");
|
||||
return;
|
||||
}
|
||||
@@ -277,6 +275,7 @@ void lu_fsm_wait_insert_data_result(struct osmo_fsm_inst *fi, uint32_t event, vo
|
||||
|
||||
case OSMO_GSUP_MSGT_INSERT_DATA_ERROR:
|
||||
lu_failure(lu, GMM_CAUSE_NET_FAIL, "Rx %s", osmo_gsup_message_type_name(req->gsup.message_type));
|
||||
osmo_gsup_req_free(req);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# This is _NOT_ the library release version, it's an API version.
|
||||
# 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
|
||||
LIBVERSION=1:0:0
|
||||
LIBVERSION=1:1:0
|
||||
|
||||
AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include
|
||||
AM_CFLAGS = -fPIC -Wall $(PCSC_CFLAGS) $(TALLOC_CFLAGS) $(LIBOSMOCORE_CFLAGS)
|
||||
|
||||
@@ -419,9 +419,9 @@ static void socket_client_close(struct socket_client *c)
|
||||
{
|
||||
struct osmo_fd *ofd = &c->ofd;
|
||||
|
||||
osmo_fd_unregister(ofd);
|
||||
close(ofd->fd);
|
||||
ofd->fd = -1;
|
||||
osmo_fd_unregister(ofd);
|
||||
|
||||
llist_del(&c->entry);
|
||||
talloc_free(c);
|
||||
@@ -561,9 +561,9 @@ void socket_close(void)
|
||||
llist_for_each_entry_safe(c, n, &globals.socket_clients, entry)
|
||||
socket_client_close(c);
|
||||
if (osmo_fd_is_registered(&globals.socket_ofd)) {
|
||||
osmo_fd_unregister(&globals.socket_ofd);
|
||||
close(globals.socket_ofd.fd);
|
||||
globals.socket_ofd.fd = -1;
|
||||
osmo_fd_unregister(&globals.socket_ofd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@ SUBDIRS = gen_ts_55_205_test_sets
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(NULL)
|
||||
@@ -30,8 +30,8 @@ auc_test_SOURCES = \
|
||||
$(NULL)
|
||||
|
||||
auc_test_LDADD = \
|
||||
$(top_srcdir)/src/auc.c \
|
||||
$(top_srcdir)/src/logging.c \
|
||||
$(top_builddir)/src/auc.o \
|
||||
$(top_builddir)/src/logging.o \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(NULL)
|
||||
@@ -41,8 +41,8 @@ auc_ts_55_205_test_sets_SOURCES = \
|
||||
$(NULL)
|
||||
|
||||
auc_ts_55_205_test_sets_LDADD = \
|
||||
$(top_srcdir)/src/auc.c \
|
||||
$(top_srcdir)/src/logging.c \
|
||||
$(top_builddir)/src/auc.o \
|
||||
$(top_builddir)/src/logging.o \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
@@ -116,14 +116,14 @@ int rand_get(uint8_t *rand, unsigned int len)
|
||||
/* Subscriber with 2G-only (COMP128v1) authentication data */
|
||||
static void test_gen_vectors_2g_only(void)
|
||||
{
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data){
|
||||
aud2g = (struct osmo_sub_auth_data2){
|
||||
.type = OSMO_AUTH_TYPE_GSM,
|
||||
.algo = OSMO_AUTH_ALG_COMP128v1,
|
||||
};
|
||||
@@ -131,7 +131,7 @@ static void test_gen_vectors_2g_only(void)
|
||||
osmo_hexparse("EB215756028D60E3275E613320AEC880",
|
||||
aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data){ 0 };
|
||||
aud3g = (struct osmo_sub_auth_data2){ 0 };
|
||||
|
||||
next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
|
||||
|
||||
@@ -179,14 +179,14 @@ static void test_gen_vectors_2g_only(void)
|
||||
* reflects the default configuration of sysmoUSIM-SJS1 */
|
||||
static void test_gen_vectors_2g_plus_3g(void)
|
||||
{
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data){
|
||||
aud2g = (struct osmo_sub_auth_data2){
|
||||
.type = OSMO_AUTH_TYPE_GSM,
|
||||
.algo = OSMO_AUTH_ALG_COMP128v1,
|
||||
};
|
||||
@@ -194,9 +194,11 @@ static void test_gen_vectors_2g_plus_3g(void)
|
||||
osmo_hexparse("EB215756028D60E3275E613320AEC880",
|
||||
aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data){
|
||||
aud3g = (struct osmo_sub_auth_data2){
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
.u.umts.sqn = 31,
|
||||
};
|
||||
|
||||
@@ -292,8 +294,8 @@ void _test_gen_vectors_3g_only__expect_vecs(struct osmo_auth_vector vecs[3])
|
||||
* tuples are suitable for both 2G and 3G authentication */
|
||||
static void test_gen_vectors_3g_only(void)
|
||||
{
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
struct osmo_auth_vector vecs[3];
|
||||
uint8_t auts[14];
|
||||
@@ -302,11 +304,13 @@ static void test_gen_vectors_3g_only(void)
|
||||
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data){ 0 };
|
||||
aud2g = (struct osmo_sub_auth_data2){ 0 };
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data){
|
||||
aud3g = (struct osmo_sub_auth_data2){
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
.u.umts.sqn = 31,
|
||||
};
|
||||
|
||||
@@ -466,18 +470,20 @@ static void test_gen_vectors_3g_only(void)
|
||||
* 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_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data){ 0 };
|
||||
aud2g = (struct osmo_sub_auth_data2){ 0 };
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data){
|
||||
aud3g = (struct osmo_sub_auth_data2){
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_XOR,
|
||||
.algo = OSMO_AUTH_ALG_XOR_3G,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
.u.umts.sqn = 0,
|
||||
};
|
||||
|
||||
@@ -517,39 +523,43 @@ void test_gen_vectors_bad_args(void)
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
struct osmo_sub_auth_data aud2g = {
|
||||
struct osmo_sub_auth_data2 aud2g = {
|
||||
.type = OSMO_AUTH_TYPE_GSM,
|
||||
.algo = OSMO_AUTH_ALG_COMP128v1,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data aud3g = {
|
||||
struct osmo_sub_auth_data2 aud3g = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data aud2g_noalg = {
|
||||
struct osmo_sub_auth_data2 aud2g_noalg = {
|
||||
.type = OSMO_AUTH_TYPE_GSM,
|
||||
.algo = OSMO_AUTH_ALG_NONE,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data aud3g_noalg = {
|
||||
struct osmo_sub_auth_data2 aud3g_noalg = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_NONE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data aud_notype = {
|
||||
struct osmo_sub_auth_data2 aud_notype = {
|
||||
.type = OSMO_AUTH_TYPE_NONE,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
};
|
||||
|
||||
struct osmo_sub_auth_data no_aud = {
|
||||
struct osmo_sub_auth_data2 no_aud = {
|
||||
.type = OSMO_AUTH_TYPE_NONE,
|
||||
.algo = OSMO_AUTH_ALG_NONE,
|
||||
};
|
||||
|
||||
struct {
|
||||
struct osmo_sub_auth_data *aud2g;
|
||||
struct osmo_sub_auth_data *aud3g;
|
||||
struct osmo_sub_auth_data2 *aud2g;
|
||||
struct osmo_sub_auth_data2 *aud3g;
|
||||
uint8_t *rand_auts;
|
||||
uint8_t *auts;
|
||||
const char *label;
|
||||
|
||||
@@ -24,43 +24,46 @@
|
||||
|
||||
static void {func_name}(void)
|
||||
{{
|
||||
struct osmo_sub_auth_data aud2g;
|
||||
struct osmo_sub_auth_data aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
struct osmo_sub_auth_data2 aud2g;
|
||||
struct osmo_sub_auth_data2 aud3g;
|
||||
struct osmo_auth_vector vec;
|
||||
int rc;
|
||||
|
||||
comment_start();
|
||||
comment_start();
|
||||
|
||||
aud2g = (struct osmo_sub_auth_data){{ 0 }};
|
||||
aud2g = (struct osmo_sub_auth_data2){{ 0 }};
|
||||
|
||||
aud3g = (struct osmo_sub_auth_data){{
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
aud3g = (struct osmo_sub_auth_data2){{
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
.u.umts.k_len = 16,
|
||||
.u.umts.opc_len = 16,
|
||||
.u.umts.sqn = 31,
|
||||
}};
|
||||
}};
|
||||
|
||||
osmo_hexparse("{Ki}",
|
||||
aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
|
||||
osmo_hexparse("{OPc}",
|
||||
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
|
||||
osmo_hexparse("{Ki}",
|
||||
aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
|
||||
osmo_hexparse("{OPc}",
|
||||
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
|
||||
|
||||
osmo_hexparse("{RAND}",
|
||||
fake_rand, sizeof(fake_rand));
|
||||
osmo_hexparse("{RAND}",
|
||||
fake_rand, sizeof(fake_rand));
|
||||
|
||||
vec = (struct osmo_auth_vector){{ {{0}} }};
|
||||
vec = (struct osmo_auth_vector){{ {{0}} }};
|
||||
vec.res_len = 8;
|
||||
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
|
||||
rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
|
||||
VERBOSE_ASSERT(rc, == 1, "%d");
|
||||
rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
|
||||
VERBOSE_ASSERT(rc, == 1, "%d");
|
||||
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
|
||||
|
||||
VEC_IS(&vec,
|
||||
" rand: {RAND}\n"
|
||||
" ck: {MIL3G-CK}\n"
|
||||
" ik: {MIL3G-IK}\n"
|
||||
" res: {MIL3G-RES}0000000000000000\n"
|
||||
" kc: {Kc}\n"
|
||||
" sres: {SRES#1}\n"
|
||||
);
|
||||
VEC_IS(&vec,
|
||||
" rand: {RAND}\n"
|
||||
" ck: {MIL3G-CK}\n"
|
||||
" ik: {MIL3G-IK}\n"
|
||||
" res: {MIL3G-RES}0000000000000000\n"
|
||||
" kc: {Kc}\n"
|
||||
" sres: {SRES#1}\n"
|
||||
);
|
||||
|
||||
comment_end();
|
||||
}}
|
||||
|
||||
@@ -55,7 +55,7 @@ char *vec_str(const struct osmo_auth_vector *vec)
|
||||
if (pos >= end) \
|
||||
return buf; \
|
||||
pos += snprintf(pos, sizeof(buf) - (pos - buf), \
|
||||
" " #what ": %s\n", \
|
||||
" " #what ": %s\n", \
|
||||
osmo_hexdump_nospc((void*)&vec->what, sizeof(vec->what)))
|
||||
|
||||
append(rand);
|
||||
@@ -71,7 +71,7 @@ char *vec_str(const struct osmo_auth_vector *vec)
|
||||
|
||||
#define VEC_IS(vec, expect) do { \
|
||||
char *_is = vec_str(vec); \
|
||||
if (strcmp(_is, expect)) { \
|
||||
if (strcmp(_is, expect)) { \
|
||||
fprintf(stderr, "MISMATCH! expected ==\n%s\n", \
|
||||
expect); \
|
||||
char *a = _is; \
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
AM_CFLAGS = \
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_builddir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
|
||||
@@ -122,16 +122,16 @@ static void _fill_invalid(void *dest, size_t size)
|
||||
/* Not linking the real auc_compute_vectors(), just returning num_vec.
|
||||
* This gets called by db_get_auc(), but we're only interested in its rc. */
|
||||
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
|
||||
struct osmo_sub_auth_data *aud2g,
|
||||
struct osmo_sub_auth_data *aud3g,
|
||||
struct osmo_sub_auth_data2 *aud2g,
|
||||
struct osmo_sub_auth_data2 *aud3g,
|
||||
const uint8_t *rand_auts, const uint8_t *auts)
|
||||
{ return num_vec; }
|
||||
|
||||
static struct db_context *dbc = NULL;
|
||||
static void *ctx = NULL;
|
||||
static struct hlr_subscriber g_subscr;
|
||||
static struct osmo_sub_auth_data g_aud2g;
|
||||
static struct osmo_sub_auth_data g_aud3g;
|
||||
static struct osmo_sub_auth_data2 g_aud2g;
|
||||
static struct osmo_sub_auth_data2 g_aud3g;
|
||||
static int g_rc;
|
||||
static int64_t g_id;
|
||||
|
||||
@@ -180,18 +180,21 @@ void dump_subscr(struct hlr_subscriber *subscr)
|
||||
#undef Pb
|
||||
}
|
||||
|
||||
void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
|
||||
void dump_aud(const char *label, struct osmo_sub_auth_data2 *aud)
|
||||
{
|
||||
if (aud->type == OSMO_AUTH_TYPE_NONE) {
|
||||
fprintf(stderr, "%s: none\n", label);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: struct osmo_sub_auth_data {\n", label);
|
||||
fprintf(stderr, "%s: struct osmo_sub_auth_data2 {\n", label);
|
||||
#define Pf(name, fmt) \
|
||||
Pfo(name, fmt, aud)
|
||||
#define Phex(name) \
|
||||
Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, sizeof(aud->name)))
|
||||
#define Phexl(name, len) \
|
||||
Pfv(name, "'%s'", osmo_hexdump_nospc(aud->name, aud->len))
|
||||
|
||||
|
||||
Pfv(type, "%s", osmo_sub_auth_type_name(aud->type));
|
||||
Pfv(algo, "%s", osmo_auth_alg_name(aud->algo));
|
||||
@@ -200,9 +203,9 @@ void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
|
||||
Phex(u.gsm.ki);
|
||||
break;
|
||||
case OSMO_AUTH_TYPE_UMTS:
|
||||
Phex(u.umts.opc);
|
||||
Phexl(u.umts.opc, u.umts.opc_len);
|
||||
Pf(u.umts.opc_is_op, "%u");
|
||||
Phex(u.umts.k);
|
||||
Phexl(u.umts.k, u.umts.k_len);
|
||||
Phex(u.umts.amf);
|
||||
if (aud->u.umts.sqn) {
|
||||
Pf(u.umts.sqn, "%"PRIu64);
|
||||
@@ -219,6 +222,7 @@ void dump_aud(const char *label, struct osmo_sub_auth_data *aud)
|
||||
|
||||
#undef Pf
|
||||
#undef Phex
|
||||
#undef Phexl
|
||||
}
|
||||
|
||||
void db_raw_sql(struct db_context *dbc, const char *sql)
|
||||
@@ -586,7 +590,7 @@ static void test_subscr_aud(void)
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")),
|
||||
0);
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
@@ -604,7 +608,7 @@ static void test_subscr_aud(void)
|
||||
-ENOENT);
|
||||
|
||||
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")),
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")),
|
||||
0);
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
@@ -707,12 +711,12 @@ static void test_subscr_aud(void)
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR, "f000000000000f00000000000f000000f00000000")),
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f000000000000f00000000000f000000f00000000")),
|
||||
-EINVAL);
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
ASSERT_RC(db_subscr_update_aud_by_id(dbc, id,
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR, "f00")),
|
||||
mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f00")),
|
||||
-EINVAL);
|
||||
ASSERT_SEL_AUD(imsi0, 0, id);
|
||||
|
||||
|
||||
@@ -824,7 +824,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "01234567
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v1,
|
||||
.u.gsm.ki = '0123456789abcdef0123456789abcdef',
|
||||
@@ -841,7 +841,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v1, "01234567
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v1,
|
||||
.u.gsm.ki = '0123456789abcdef0123456789abcdef',
|
||||
@@ -853,7 +853,7 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v2, "BeadedBe
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v2,
|
||||
.u.gsm.ki = 'beadedbeeaced1ebbeddefacedfacade',
|
||||
@@ -865,21 +865,21 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_COMP128v3, "DeafBedd
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'deafbeddedbabeacceededfadeddecaf',
|
||||
}
|
||||
3G: none
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")) --> 0
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")) --> 0
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = XOR,
|
||||
.algo = XOR-2G,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: none
|
||||
@@ -900,14 +900,14 @@ DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_NONE, NULL)) --> -ENOENT
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "CededEffacedAceFacedBadFadedBeef")) --> 0
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "CededEffacedAceFacedBadFadedBeef")) --> 0
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = XOR,
|
||||
.algo = XOR-2G,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: none
|
||||
@@ -932,7 +932,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -954,7 +954,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -970,7 +970,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'deaf0ff1ced0d0dabbedd1ced1cef00d',
|
||||
@@ -985,7 +985,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1001,7 +1001,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
|
||||
@@ -1033,7 +1033,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'cededeffacedacefacedbadfadedbeef',
|
||||
@@ -1069,12 +1069,12 @@ db_subscr_update_aud_by_id(dbc, id, mk_aud_3g(OSMO_AUTH_ALG_MILENAGE, "BeefedCaf
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1097,12 +1097,12 @@ DAUC Cannot update auth tokens: Unknown auth algo: 99999
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1112,17 +1112,17 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
.u.umts.ind_bitlen = 5,
|
||||
}
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "f000000000000f00000000000f000000f00000000")) --> -EINVAL
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f000000000000f00000000000f000000f00000000")) --> -EINVAL
|
||||
DAUC Cannot update auth tokens: Invalid KI: 'f000000000000f00000000000f000000f00000000'
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1132,17 +1132,17 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
.u.umts.ind_bitlen = 5,
|
||||
}
|
||||
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR, "f00")) --> -EINVAL
|
||||
db_subscr_update_aud_by_id(dbc, id, mk_aud_2g(OSMO_AUTH_ALG_XOR_2G, "f00")) --> -EINVAL
|
||||
DAUC Cannot update auth tokens: Invalid KI: 'f00'
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1157,12 +1157,12 @@ DAUC Cannot update auth tokens: auth algo not suited for 2G: MILENAGE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1177,12 +1177,12 @@ DAUC Cannot update auth tokens: Invalid OP/OPC: '0f000000000000f00000000000f0000
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1197,12 +1197,12 @@ DAUC Cannot update auth tokens: Invalid K: '000000000000f00000000000f000000'
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1217,12 +1217,12 @@ DAUC Cannot update auth tokens: Invalid ind_bitlen: 29
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1237,12 +1237,12 @@ DAUC Cannot update auth tokens: Invalid OP/OPC: 'X000000000000f00000000000f00000
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1257,12 +1257,12 @@ DAUC Cannot update auth tokens: Invalid K: 'f000000000000 f00000000000 f000000'
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
|
||||
2G: struct osmo_sub_auth_data {
|
||||
2G: struct osmo_sub_auth_data2 {
|
||||
.type = GSM,
|
||||
.algo = COMP128v3,
|
||||
.u.gsm.ki = 'cededeffacedacefacedbadfadedbeef',
|
||||
}
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1338,7 +1338,7 @@ sqlite3_prepare_v2(dbc->db, sql, -1, &stmt, NULL) --> SQLITE_OK
|
||||
sqlite3_step(stmt) --> SQLITE_DONE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -ENOKEY
|
||||
DAUC IMSI='123456789000000': Error reading Ki, expected length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': Error reading Ki, expected min length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': No 3G Auth Data
|
||||
|
||||
|
||||
@@ -1359,7 +1359,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
DAUC IMSI='123456789000000': Error reading K, expected length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': Error reading K, expected min length 16 but has length 15
|
||||
|
||||
|
||||
|
||||
@@ -1374,7 +1374,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
DAUC IMSI='123456789000000': Error reading OP, expected length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': Error reading OP, expected min length 16 but has length 15
|
||||
|
||||
|
||||
|
||||
@@ -1389,7 +1389,7 @@ sqlite3_step(stmt) --> SQLITE_DONE
|
||||
|
||||
db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> -5
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
DAUC IMSI='123456789000000': Error reading OPC, expected length 16 but has length 15
|
||||
DAUC IMSI='123456789000000': Error reading OPC, expected min length 16 but has length 15
|
||||
|
||||
|
||||
|
||||
@@ -1458,7 +1458,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1477,7 +1477,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1495,7 +1495,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1513,7 +1513,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1534,7 +1534,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1550,7 +1550,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1568,7 +1568,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
@@ -1586,7 +1586,7 @@ db_get_auth_data(dbc, imsi0, &g_aud2g, &g_aud3g, &g_id) --> 0
|
||||
DAUC IMSI='123456789000000': No 2G Auth Data
|
||||
|
||||
2G: none
|
||||
3G: struct osmo_sub_auth_data {
|
||||
3G: struct osmo_sub_auth_data2 {
|
||||
.type = UMTS,
|
||||
.algo = MILENAGE,
|
||||
.u.umts.opc = 'beefedcafefaceacedaddeddecadefee',
|
||||
|
||||
@@ -43,5 +43,5 @@ OsmoHLR# subscriber imsi 5555555 create
|
||||
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 aud2g xor-2g ki 55555555555555555555555555555555
|
||||
OsmoHLR# subscriber imsi 5555555 update aud3g milenage k 55555555555555555555555555555555 opc 55555555555555555555555555555555
|
||||
|
||||
@@ -12,7 +12,7 @@ Table auc_2g contents:
|
||||
algo_id_2g|ki|subscriber_id
|
||||
1|BeefedCafeFaceAcedAddedDecadeFee|1
|
||||
2|33333333333333333333333333333333|4
|
||||
4|55555555555555555555555555555555|6
|
||||
6|55555555555555555555555555555555|6
|
||||
|
||||
Table: auc_3g
|
||||
name|type|notnull|dflt_value|pk
|
||||
@@ -86,6 +86,7 @@ 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 5
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 6
|
||||
DDB Database <PATH>test.db' has been upgraded to HLR DB schema version 7
|
||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
|
||||
|
||||
Resulting db:
|
||||
@@ -100,15 +101,15 @@ Table auc_2g contents:
|
||||
algo_id_2g|ki|subscriber_id
|
||||
1|BeefedCafeFaceAcedAddedDecadeFee|1
|
||||
2|33333333333333333333333333333333|4
|
||||
4|55555555555555555555555555555555|6
|
||||
6|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
|
||||
k|VARCHAR(64)|1||0
|
||||
op|VARCHAR(64)|0||0
|
||||
opc|VARCHAR(64)|0||0
|
||||
sqn|INTEGER|1|0|0
|
||||
subscriber_id|INTEGER|0||1
|
||||
|
||||
@@ -179,5 +180,5 @@ 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 6
|
||||
DDB Database <PATH>test.db' has HLR DB schema version 7
|
||||
DMAIN Cmdline option --db-check: Database was opened successfully, quitting.
|
||||
|
||||
@@ -61,7 +61,7 @@ CREATE TABLE auc_2g (
|
||||
);
|
||||
INSERT INTO auc_2g VALUES(1,1,'BeefedCafeFaceAcedAddedDecadeFee');
|
||||
INSERT INTO auc_2g VALUES(4,2,'33333333333333333333333333333333');
|
||||
INSERT INTO auc_2g VALUES(6,4,'55555555555555555555555555555555');
|
||||
INSERT INTO auc_2g VALUES(6,6,'55555555555555555555555555555555');
|
||||
CREATE TABLE auc_3g (
|
||||
subscriber_id INTEGER PRIMARY KEY, -- subscriber.id
|
||||
algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
-I$(top_srcdir)/include \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(LIBOSMOABIS_CFLAGS) \
|
||||
|
||||
@@ -53,6 +53,7 @@ OsmoHLR(config-hlr)# ?
|
||||
OsmoHLR(config-hlr)# list
|
||||
...
|
||||
gsup
|
||||
ps
|
||||
database PATH
|
||||
euse NAME
|
||||
no euse NAME
|
||||
@@ -112,6 +113,12 @@ hlr
|
||||
ipa-name unnamed-HLR
|
||||
ussd route prefix *#100# internal own-msisdn
|
||||
ussd route prefix *#101# internal own-imsi
|
||||
ps
|
||||
pdp-profiles default
|
||||
profile 1
|
||||
apn internet
|
||||
profile 2
|
||||
apn *
|
||||
end
|
||||
|
||||
OsmoHLR# configure terminal
|
||||
@@ -448,3 +455,44 @@ mslookup
|
||||
client
|
||||
mdns bind 239.192.23.42 4266
|
||||
...
|
||||
OsmoHLR(config-mslookup-server)# end
|
||||
OsmoHLR# configure terminal
|
||||
|
||||
OsmoHLR(config)# hlr
|
||||
OsmoHLR(config-hlr)# ps?
|
||||
ps Configure the PS options
|
||||
|
||||
OsmoHLR(config-hlr)# ps
|
||||
|
||||
OsmoHLR(config-hlr-ps)# list
|
||||
...
|
||||
pdp-profiles default
|
||||
no pdp-profiles default
|
||||
...
|
||||
OsmoHLR(config-hlr-ps)# no pdp-profiles default
|
||||
|
||||
|
||||
OsmoHLR(config-hlr-ps)# pdp-profiles default
|
||||
OsmoHLR(config-hlr-ps-pdp-profiles)# ?
|
||||
...
|
||||
profile Configure a PDP profile
|
||||
...
|
||||
OsmoHLR(config-hlr-ps-pdp-profiles)# profile 1
|
||||
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# ?
|
||||
...
|
||||
apn Configure the APN.
|
||||
...
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# apn internet
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# exit
|
||||
OsmoHLR(config-hlr-ps-pdp-profiles)# profile 2
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# apn *
|
||||
OsmoHLR(config-hlr-ps-pdp-profile)# show running-config
|
||||
...
|
||||
ps
|
||||
pdp-profiles default
|
||||
profile 1
|
||||
apn internet
|
||||
profile 2
|
||||
apn *
|
||||
...
|
||||
|
||||
@@ -674,11 +674,11 @@ lmsi 00000000
|
||||
GET 112 subscriber.by-imsi-901991234567891.aud2g
|
||||
GET_REPLY 112 subscriber.by-imsi-901991234567891.aud2g none
|
||||
|
||||
SET 113 subscriber.by-imsi-901991234567891.aud2g xor,c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
SET 113 subscriber.by-imsi-901991234567891.aud2g xor-2g,c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
SET_REPLY 113 subscriber.by-imsi-901991234567891.aud2g OK
|
||||
|
||||
GET 114 subscriber.by-imsi-901991234567891.aud2g
|
||||
GET_REPLY 114 subscriber.by-imsi-901991234567891.aud2g XOR,c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
GET_REPLY 114 subscriber.by-imsi-901991234567891.aud2g XOR-2G,c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
|
||||
SET 115 subscriber.by-imsi-901991234567891.aud2g none
|
||||
SET_REPLY 115 subscriber.by-imsi-901991234567891.aud2g OK
|
||||
|
||||
@@ -8,10 +8,10 @@ OsmoHLR# list
|
||||
subscriber (imsi|msisdn|id|imei) IDENT delete
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update msisdn (none|MSISDN)
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud2g none
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor) ki KI
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor-2g) ki KI
|
||||
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 xor k K [ind-bitlen] [<0-28>]
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud3g (milenage|tuak) k K (op|opc) OP_C [ind-bitlen] [<0-28>]
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update aud3g xor-3g k K [ind-bitlen] [<0-28>]
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update imei (none|IMEI)
|
||||
subscriber (imsi|msisdn|id|imei) IDENT update network-access-mode (none|cs|ps|cs+ps)
|
||||
show mslookup services
|
||||
@@ -144,7 +144,7 @@ OsmoHLR# subscriber imsi 123456789023000 update aud2g ?
|
||||
comp128v1 Use COMP128v1 algorithm
|
||||
comp128v2 Use COMP128v2 algorithm
|
||||
comp128v3 Use COMP128v3 algorithm
|
||||
xor Use XOR algorithm
|
||||
xor-2g Use XOR-2G algorithm
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ?
|
||||
ki Set Ki Encryption Key
|
||||
@@ -155,12 +155,12 @@ OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki ?
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki val ?
|
||||
<cr>
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g xor ki Deaf0ff1ceD0d0DabbedD1ced1ceF00d
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g xor-2g ki Deaf0ff1ceD0d0DabbedD1ced1ceF00d
|
||||
OsmoHLR# subscriber imsi 123456789023000 show
|
||||
ID: 101
|
||||
IMSI: 123456789023000
|
||||
MSISDN: 423
|
||||
2G auth: XOR
|
||||
2G auth: XOR-2G
|
||||
KI=deaf0ff1ced0d0dabbedd1ced1cef00d
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud2g comp128v1 ki BeefedCafeFaceAcedAddedDecadeFee
|
||||
@@ -241,7 +241,7 @@ OsmoHLR# subscriber id 101 show
|
||||
2G auth: COMP128v3
|
||||
KI=c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
|
||||
OsmoHLR# subscriber id 101 update aud2g xor ki CoiffedCicadaeAcidifiedAcaciaBoa
|
||||
OsmoHLR# subscriber id 101 update aud2g xor-2g ki CoiffedCicadaeAcidifiedAcaciaBoa
|
||||
% Invalid value for KI: 'CoiffedCicadaeAcidifiedAcaciaBoa'
|
||||
OsmoHLR# subscriber id 101 show
|
||||
ID: 101
|
||||
@@ -250,7 +250,7 @@ OsmoHLR# subscriber id 101 show
|
||||
2G auth: COMP128v3
|
||||
KI=c01ffedc1cadaeac1d1f1edacac1ab0a
|
||||
|
||||
OsmoHLR# subscriber id 101 update aud2g xor ki C01ffedC1cadaeAc1d1f1edAcac1aB0aX
|
||||
OsmoHLR# subscriber id 101 update aud2g xor-2g ki C01ffedC1cadaeAc1d1f1edAcac1aB0aX
|
||||
% Invalid value for KI: 'C01ffedC1cadaeAc1d1f1edAcac1aB0aX'
|
||||
OsmoHLR# subscriber id 101 show
|
||||
ID: 101
|
||||
@@ -269,20 +269,21 @@ OsmoHLR# subscriber id 101 show
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g ?
|
||||
none Delete 3G authentication data
|
||||
milenage Use Milenage algorithm
|
||||
xor Use XOR algorithm
|
||||
tuak Use TUAK algorithm
|
||||
xor-3g Use XOR-3G algorithm
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage ?
|
||||
k Set Encryption Key K
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k ?
|
||||
K K as 32 hexadecimal characters
|
||||
K K as 32/64 hexadecimal characters
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d ?
|
||||
op Set OP key
|
||||
opc Set OPC key
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc ?
|
||||
OP_C OP or OPC as 32 hexadecimal characters
|
||||
OP_C OP or OPC as 32/64 hexadecimal characters
|
||||
|
||||
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage k Deaf0ff1ceD0d0DabbedD1ced1ceF00d opc CededEffacedAceFacedBadFadedBeef ?
|
||||
[ind-bitlen] Set IND bit length
|
||||
|
||||
@@ -130,7 +130,7 @@ ERROR 54 Value failed verification.
|
||||
SET 55 subscriber.by-imsi-901990000000003.aud2g foobar,2134
|
||||
ERROR 55 Unknown auth algorithm.
|
||||
|
||||
SET 56 subscriber.by-imsi-901990000000003.aud2g xor,2134
|
||||
SET 56 subscriber.by-imsi-901990000000003.aud2g xor-2g,2134
|
||||
ERROR 56 Invalid KI.
|
||||
|
||||
SET 57 subscriber.by-imsi-901990000000003.aud3g foobar
|
||||
@@ -139,17 +139,17 @@ ERROR 57 Value failed verification.
|
||||
SET 58 subscriber.by-imsi-901990000000003.aud3g foobar,2134
|
||||
ERROR 58 Unknown auth algorithm.
|
||||
|
||||
SET 60 subscriber.by-imsi-901990000000003.aud3g milenage,2134
|
||||
ERROR 60 Invalid KI.
|
||||
SET 59 subscriber.by-imsi-901990000000003.aud3g milenage,2134
|
||||
ERROR 59 Invalid KI.
|
||||
|
||||
SET 61 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,AAA
|
||||
SET 60 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,AAA
|
||||
ERROR 60 Invalid format.
|
||||
|
||||
SET 61 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC
|
||||
ERROR 61 Invalid format.
|
||||
|
||||
SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC
|
||||
ERROR 62 Invalid format.
|
||||
SET 62 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,zzz
|
||||
ERROR 62 Invalid OP/OPC.
|
||||
|
||||
SET 63 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,zzz
|
||||
ERROR 63 Invalid OP/OPC.
|
||||
|
||||
SET 64 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,
|
||||
ERROR 64 Invalid format.
|
||||
SET 63 subscriber.by-imsi-901990000000003.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,
|
||||
ERROR 63 Invalid format.
|
||||
|
||||
Reference in New Issue
Block a user