aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-11-20 03:35:37 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2020-04-30 19:22:24 +0200
commit76328bdc9165ef7355528c86d655d3b5086607d6 (patch)
tree920859c8d7fc4d7c1d5059d976681fcb190f3f17 /include/osmocom
parent407925dcab8bdff8e3d6c2cf4ed7b73b7d69141e (diff)
D-GSM 3/n: implement roaming by mslookup in osmo-hlr
Add mslookup client to find remote home HLRs of unknown IMSIs, and proxy/forward GSUP for those to the right remote HLR instances. Add remote_hlr.c to manage one GSUP client per remote HLR GSUP address. Add proxy.c to keep state about remotely handled IMSIs (remote GSUP address, MSISDN, and probably more in future patches). The mslookup_server that determines whether a given MSISDN is attached locally now also needs to look in the proxy record: it is always the osmo-hlr immediately peering for the MSC that should respond to mslookup service address queries like SIP and SMPP. (Only gsup.hlr service is always answered by the home HLR.) Add dgsm.c to set up an mdns mslookup client, ask for IMSI homes, and to decide which GSUP is handled locally and which needs to go to a remote HLR. Add full VTY config and VTY tests. For a detailed overview of the D-GSM and mslookup related files, please see the elaborate comment at the top of mslookup.c (already added in an earlier patch). Change-Id: I2fe453553c90e6ee527ed13a13089900efd488aa
Diffstat (limited to 'include/osmocom')
-rw-r--r--include/osmocom/hlr/Makefile.am3
-rw-r--r--include/osmocom/hlr/dgsm.h46
-rw-r--r--include/osmocom/hlr/gsup_server.h5
-rw-r--r--include/osmocom/hlr/hlr.h25
-rw-r--r--include/osmocom/hlr/hlr_vty.h1
-rw-r--r--include/osmocom/hlr/logging.h1
-rw-r--r--include/osmocom/hlr/mslookup_server.h4
-rw-r--r--include/osmocom/hlr/proxy.h95
-rw-r--r--include/osmocom/hlr/remote_hlr.h59
9 files changed, 239 insertions, 0 deletions
diff --git a/include/osmocom/hlr/Makefile.am b/include/osmocom/hlr/Makefile.am
index b24f084..aceda4a 100644
--- a/include/osmocom/hlr/Makefile.am
+++ b/include/osmocom/hlr/Makefile.am
@@ -2,6 +2,7 @@ noinst_HEADERS = \
auc.h \
ctrl.h \
db.h \
+ dgsm.h \
gsup_router.h \
gsup_server.h \
hlr.h \
@@ -12,6 +13,8 @@ noinst_HEADERS = \
lu_fsm.h \
mslookup_server.h \
mslookup_server_mdns.h \
+ proxy.h \
rand.h \
+ remote_hlr.h \
timestamp.h \
$(NULL)
diff --git a/include/osmocom/hlr/dgsm.h b/include/osmocom/hlr/dgsm.h
new file mode 100644
index 0000000..cc8f3d2
--- /dev/null
+++ b/include/osmocom/hlr/dgsm.h
@@ -0,0 +1,46 @@
+/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <osmocom/mslookup/mslookup.h>
+#include <osmocom/hlr/gsup_server.h>
+#include <osmocom/hlr/logging.h>
+#include <osmocom/gsupclient/cni_peer_id.h>
+#include <osmocom/gsupclient/gsup_req.h>
+
+#define LOG_DGSM(imsi, level, fmt, args...) \
+ LOGP(DDGSM, level, "(IMSI-%s) " fmt, imsi, ##args)
+
+struct vty;
+struct remote_hlr;
+struct hlr_subscriber;
+
+extern void *dgsm_ctx;
+
+void dgsm_init(void *ctx);
+void dgsm_start(void *ctx);
+void dgsm_stop();
+
+bool dgsm_check_forward_gsup_msg(struct osmo_gsup_req *req);
+
+void dgsm_vty_init();
+void dgsm_mdns_client_config_apply(void);
+
+bool hlr_subscr_lu_age(const struct hlr_subscriber *subscr, uint32_t *age_p);
diff --git a/include/osmocom/hlr/gsup_server.h b/include/osmocom/hlr/gsup_server.h
index 774f750..ce7556e 100644
--- a/include/osmocom/hlr/gsup_server.h
+++ b/include/osmocom/hlr/gsup_server.h
@@ -27,6 +27,9 @@ struct osmo_gsup_server {
struct ipa_server_link *link;
osmo_gsup_read_cb_t read_cb;
struct llist_head routes;
+
+ /* Proxy requests from this server's clients to remote GSUP servers. */
+ struct proxy *proxy;
};
@@ -71,3 +74,5 @@ int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup,
uint8_t *msisdn_enc, size_t msisdn_enc_size,
uint8_t *apn_buf, size_t apn_buf_size,
enum osmo_gsup_cn_domain cn_domain);
+int osmo_gsup_forward_to_local_peer(struct osmo_gsup_server *server, const struct osmo_cni_peer_id *to_peer,
+ struct osmo_gsup_req *req, struct osmo_gsup_message *modified_gsup);
diff --git a/include/osmocom/hlr/hlr.h b/include/osmocom/hlr/hlr.h
index 8f26704..e8df5cd 100644
--- a/include/osmocom/hlr/hlr.h
+++ b/include/osmocom/hlr/hlr.h
@@ -28,6 +28,8 @@
#include <osmocom/core/tdef.h>
#include <osmocom/core/sockaddr_str.h>
+#include <osmocom/hlr/dgsm.h>
+
#define HLR_DEFAULT_DB_FILE_PATH "hlr.db"
struct hlr_euse;
@@ -85,6 +87,29 @@ struct hlr {
struct osmo_mslookup_server_mdns *running;
} mdns;
} server;
+
+ /* The mslookup client in osmo-hlr is used to find out which remote HLRs service a locally unknown IMSI.
+ * (It may also be used to resolve recipients for SMS-over-GSUP in the future.) */
+ struct {
+ /* Whether to proxy/forward to remote HLRs */
+ bool enable;
+
+ /* If this is set, all GSUP for unknown IMSIs is forwarded directly to this GSUP address,
+ * unconditionally. */
+ struct osmo_sockaddr_str gsup_gateway_proxy;
+
+ /* mslookup client request handling */
+ unsigned int result_timeout_milliseconds;
+
+ struct osmo_mslookup_client *client;
+ struct {
+ /* Whether to use mDNS for IMSI MS Lookup */
+ bool enable;
+ struct osmo_sockaddr_str query_addr;
+ char *domain_suffix;
+ struct osmo_mslookup_client_method *running;
+ } mdns;
+ } client;
} mslookup;
};
diff --git a/include/osmocom/hlr/hlr_vty.h b/include/osmocom/hlr/hlr_vty.h
index 0ba9821..c026d91 100644
--- a/include/osmocom/hlr/hlr_vty.h
+++ b/include/osmocom/hlr/hlr_vty.h
@@ -34,6 +34,7 @@ enum hlr_vty_node {
MSLOOKUP_NODE,
MSLOOKUP_SERVER_NODE,
MSLOOKUP_SERVER_MSC_NODE,
+ MSLOOKUP_CLIENT_NODE,
};
int hlr_vty_is_config_node(struct vty *vty, int node);
diff --git a/include/osmocom/hlr/logging.h b/include/osmocom/hlr/logging.h
index 4e0a25c..a8081af 100644
--- a/include/osmocom/hlr/logging.h
+++ b/include/osmocom/hlr/logging.h
@@ -10,6 +10,7 @@ enum {
DSS,
DMSLOOKUP,
DLU,
+ DDGSM,
};
extern const struct log_info hlr_log_info;
diff --git a/include/osmocom/hlr/mslookup_server.h b/include/osmocom/hlr/mslookup_server.h
index 440c451..7c80f2a 100644
--- a/include/osmocom/hlr/mslookup_server.h
+++ b/include/osmocom/hlr/mslookup_server.h
@@ -66,3 +66,7 @@ struct mslookup_server_msc_cfg *mslookup_server_msc_get(const struct osmo_ipa_na
const struct mslookup_service_host *mslookup_server_get_local_gsup_addr();
void mslookup_server_rx(const struct osmo_mslookup_query *query,
struct osmo_mslookup_result *result);
+
+bool subscriber_has_done_lu_here(const struct osmo_mslookup_query *query,
+ uint32_t *lu_age_p, struct osmo_ipa_name *local_msc_name,
+ char *ret_imsi, size_t ret_imsi_len);
diff --git a/include/osmocom/hlr/proxy.h b/include/osmocom/hlr/proxy.h
new file mode 100644
index 0000000..0169038
--- /dev/null
+++ b/include/osmocom/hlr/proxy.h
@@ -0,0 +1,95 @@
+/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <time.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+#include <osmocom/core/sockaddr_str.h>
+#include <osmocom/gsupclient/cni_peer_id.h>
+#include <osmocom/hlr/timestamp.h>
+
+struct osmo_gsup_req;
+struct remote_hlr;
+
+struct proxy {
+ struct llist_head subscr_list;
+ struct llist_head pending_gsup_reqs;
+
+ /* When messages arrive back from a remote HLR that this is the proxy for, reach the VLR to forward the response
+ * to via this osmo_gsup_server. */
+ struct osmo_gsup_server *gsup_server_to_vlr;
+
+ /* How long to keep proxy entries without a refresh, in seconds. */
+ uint32_t fresh_time;
+
+ /* How often to garbage collect the proxy cache, period in seconds.
+ * To change this and take effect immediately, rather use proxy_set_gc_period(). */
+ uint32_t gc_period;
+
+ struct osmo_timer_list gc_timer;
+};
+
+struct proxy_subscr_domain_state {
+ struct osmo_ipa_name vlr_name;
+ timestamp_t last_lu;
+
+ /* The name from which an Update Location Request was received. Copied to vlr_name as soon as the LU is
+ * completed successfully. */
+ struct osmo_ipa_name vlr_name_preliminary;
+
+ /* Set if this is a middle proxy, i.e. a proxy behind another proxy.
+ * That is mostly to know whether the MS is attached at a local MSC/SGSN or further away.
+ * It could be a boolean, but store the full name for logging. Set only at successful LU acceptance. */
+ struct osmo_ipa_name vlr_via_proxy;
+};
+
+struct proxy_subscr {
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
+ char msisdn[GSM23003_MSISDN_MAX_DIGITS+1];
+ struct osmo_sockaddr_str remote_hlr_addr;
+ struct proxy_subscr_domain_state cs, ps;
+};
+
+void proxy_init(struct osmo_gsup_server *gsup_server_to_vlr);
+void proxy_del(struct proxy *proxy);
+void proxy_set_gc_period(struct proxy *proxy, uint32_t gc_period);
+
+/* The API to access / modify proxy entries keeps the implementation opaque, to make sure that we can easily move proxy
+ * storage to SQLite db. */
+int proxy_subscr_get_by_imsi(struct proxy_subscr *dst, struct proxy *proxy, const char *imsi);
+int proxy_subscr_get_by_msisdn(struct proxy_subscr *dst, struct proxy *proxy, const char *msisdn);
+void proxy_subscrs_get_by_remote_hlr(struct proxy *proxy, const struct osmo_sockaddr_str *remote_hlr_addr,
+ bool (*yield)(struct proxy *proxy, const struct proxy_subscr *subscr, void *data),
+ void *data);
+int proxy_subscr_create_or_update(struct proxy *proxy, const struct proxy_subscr *proxy_subscr);
+int proxy_subscr_del(struct proxy *proxy, const char *imsi);
+
+int proxy_subscr_forward_to_remote_hlr(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
+ struct osmo_gsup_req *req);
+void proxy_subscr_forward_to_remote_hlr_resolved(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
+ struct remote_hlr *remote_hlr, struct osmo_gsup_req *req);
+
+int proxy_subscr_forward_to_vlr(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
+ const struct osmo_gsup_message *gsup, struct remote_hlr *from_remote_hlr);
+
+void proxy_subscr_remote_hlr_resolved(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
+ const struct osmo_sockaddr_str *remote_hlr_addr);
+void proxy_subscr_remote_hlr_up(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
+ struct remote_hlr *remote_hlr);
diff --git a/include/osmocom/hlr/remote_hlr.h b/include/osmocom/hlr/remote_hlr.h
new file mode 100644
index 0000000..6a4e8a1
--- /dev/null
+++ b/include/osmocom/hlr/remote_hlr.h
@@ -0,0 +1,59 @@
+/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/sockaddr_str.h>
+
+struct osmo_gsup_client;
+struct osmo_gsup_message;
+struct osmo_gsup_req;
+struct msgb;
+
+#define LOG_REMOTE_HLR(remote_hlr, level, fmt, args...) \
+ LOGP(DDGSM, level, "(Proxy HLR-" OSMO_SOCKADDR_STR_FMT ") " fmt, \
+ OSMO_SOCKADDR_STR_FMT_ARGS((remote_hlr) ? &(remote_hlr)->addr : NULL), ##args)
+
+#define LOG_REMOTE_HLR_MSG(remote_hlr, gsup_msg, level, fmt, args...) \
+ LOG_REMOTE_HLR(remote_hlr, level, "%s: " fmt, osmo_gsup_message_type_name((gsup_msg)->message_type), ##args)
+
+/* GSUP client link for proxying to a remote HLR. */
+struct remote_hlr {
+ struct llist_head entry;
+ struct osmo_sockaddr_str addr;
+ struct osmo_gsup_client *gsupc;
+ struct llist_head pending_up_callbacks;
+};
+
+/*! Receive a remote_hlr address when connecting succeeded, or remote_hlr == NULL on error.
+ * \param addr GSUP IP address and port for which the connection was requested.
+ * \param remote_hlr The connected remote_hlr ready for sending, or NULL if connecting failed.
+ * \param data Same a passed to remote_hlr_get_or_connect(). */
+typedef void (*remote_hlr_connect_result_cb_t)(const struct osmo_sockaddr_str *addr, struct remote_hlr *remote_hlr, void *data);
+
+struct remote_hlr *remote_hlr_get_or_connect(const struct osmo_sockaddr_str *addr, bool connect,
+ remote_hlr_connect_result_cb_t connect_result_cb, void *data);
+void remote_hlr_destroy(struct remote_hlr *remote_hlr);
+int remote_hlr_msgb_send(struct remote_hlr *remote_hlr, struct msgb *msg);
+void remote_hlr_gsup_forward_to_remote_hlr(struct remote_hlr *remote_hlr, struct osmo_gsup_req *req,
+ struct osmo_gsup_message *modified_gsup);
+
+bool remote_hlr_is_up(struct remote_hlr *remote_hlr);