Change in osmo-hlr[master]: D-GSM 2/n: implement mDNS method of mslookup server

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Fri May 1 14:37:35 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hlr/+/16257 )

Change subject: D-GSM 2/n: implement mDNS method of mslookup server
......................................................................

D-GSM 2/n: implement mDNS method of mslookup server

Implement the mslookup server's mDNS responder, to actually service remote
mslookup requests:
- VTY mslookup/server config with service names,
- the mslookup_mdns_server listening for mslookup requests,

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: I5cae6459090588b4dd292be90a5e8903432669d2
---
M include/osmocom/hlr/Makefile.am
M include/osmocom/hlr/hlr.h
M include/osmocom/hlr/hlr_vty.h
M include/osmocom/hlr/mslookup_server.h
A include/osmocom/hlr/mslookup_server_mdns.h
M src/Makefile.am
A src/dgsm_vty.c
M src/hlr.c
A src/mslookup_server_mdns.c
M tests/test_nodes.vty
M tests/test_subscriber.vty
11 files changed, 605 insertions(+), 1 deletion(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved



diff --git a/include/osmocom/hlr/Makefile.am b/include/osmocom/hlr/Makefile.am
index 5c96ec8..b24f084 100644
--- a/include/osmocom/hlr/Makefile.am
+++ b/include/osmocom/hlr/Makefile.am
@@ -11,6 +11,7 @@
 	logging.h \
 	lu_fsm.h \
 	mslookup_server.h \
+	mslookup_server_mdns.h \
 	rand.h \
 	timestamp.h \
 	$(NULL)
diff --git a/include/osmocom/hlr/hlr.h b/include/osmocom/hlr/hlr.h
index 1269994..8f26704 100644
--- a/include/osmocom/hlr/hlr.h
+++ b/include/osmocom/hlr/hlr.h
@@ -26,6 +26,7 @@
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/gsm/ipa.h>
 #include <osmocom/core/tdef.h>
+#include <osmocom/core/sockaddr_str.h>
 
 #define HLR_DEFAULT_DB_FILE_PATH "hlr.db"
 
@@ -69,9 +70,20 @@
 	unsigned int subscr_create_on_demand_rand_msisdn_len;
 
 	struct {
+		bool allow_startup;
 		struct {
+			/* Whether the mslookup server should be active in general (all lookup methods) */
+			bool enable;
 			uint32_t local_attach_max_age;
 			struct llist_head local_site_services;
+			struct {
+				/* Whether the mDNS method of the mslookup server should be active. */
+				bool enable;
+				/* The mDNS bind address and domain suffix as set by the VTY, not necessarily in use. */
+				struct osmo_sockaddr_str bind_addr;
+				char *domain_suffix;
+				struct osmo_mslookup_server_mdns *running;
+			} mdns;
 		} server;
 	} mslookup;
 };
diff --git a/include/osmocom/hlr/hlr_vty.h b/include/osmocom/hlr/hlr_vty.h
index acd6510..0ba9821 100644
--- a/include/osmocom/hlr/hlr_vty.h
+++ b/include/osmocom/hlr/hlr_vty.h
@@ -31,8 +31,12 @@
 	HLR_NODE = _LAST_OSMOVTY_NODE + 1,
 	GSUP_NODE,
 	EUSE_NODE,
+	MSLOOKUP_NODE,
+	MSLOOKUP_SERVER_NODE,
+	MSLOOKUP_SERVER_MSC_NODE,
 };
 
 int hlr_vty_is_config_node(struct vty *vty, int node);
 int hlr_vty_go_parent(struct vty *vty);
 void hlr_vty_init(void);
+void dgsm_vty_init(void);
diff --git a/include/osmocom/hlr/mslookup_server.h b/include/osmocom/hlr/mslookup_server.h
index 5425328..440c451 100644
--- a/include/osmocom/hlr/mslookup_server.h
+++ b/include/osmocom/hlr/mslookup_server.h
@@ -19,6 +19,9 @@
 
 #pragma once
 
+#include <osmocom/gsupclient/cni_peer_id.h>
+#include <osmocom/mslookup/mslookup.h>
+
 struct osmo_mslookup_query;
 struct osmo_mslookup_result;
 
diff --git a/include/osmocom/hlr/mslookup_server_mdns.h b/include/osmocom/hlr/mslookup_server_mdns.h
new file mode 100644
index 0000000..ef16e88
--- /dev/null
+++ b/include/osmocom/hlr/mslookup_server_mdns.h
@@ -0,0 +1,36 @@
+/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info at 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/sockaddr_str.h>
+#include <osmocom/mslookup/mdns_sock.h>
+
+struct osmo_mslookup_server_mdns {
+	struct osmo_mslookup_server *mslookup;
+	struct osmo_sockaddr_str bind_addr;
+	char *domain_suffix;
+	struct osmo_mdns_sock *sock;
+};
+
+struct osmo_mslookup_server_mdns *osmo_mslookup_server_mdns_start(void *ctx, const struct osmo_sockaddr_str *bind_addr,
+								  const char *domain_suffix);
+void osmo_mslookup_server_mdns_stop(struct osmo_mslookup_server_mdns *server);
+void mslookup_server_mdns_config_apply();
diff --git a/src/Makefile.am b/src/Makefile.am
index 571eaef..ceaa093 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -54,8 +54,10 @@
 	gsup_send.c \
 	hlr_ussd.c \
 	lu_fsm.c \
-	mslookup_server.c \
 	timestamp.c \
+	mslookup_server.c \
+	mslookup_server_mdns.c \
+	dgsm_vty.c \
 	$(NULL)
 
 osmo_hlr_LDADD = \
diff --git a/src/dgsm_vty.c b/src/dgsm_vty.c
new file mode 100644
index 0000000..facd2b7
--- /dev/null
+++ b/src/dgsm_vty.c
@@ -0,0 +1,382 @@
+/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info at sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/mslookup/mslookup_client_mdns.h>
+#include <osmocom/mslookup/mdns.h>
+#include <osmocom/hlr/hlr_vty.h>
+#include <osmocom/hlr/mslookup_server.h>
+#include <osmocom/hlr/mslookup_server_mdns.h>
+#include <osmocom/gsupclient/cni_peer_id.h>
+
+struct cmd_node mslookup_node = {
+	MSLOOKUP_NODE,
+	"%s(config-mslookup)# ",
+	1,
+};
+
+DEFUN(cfg_mslookup,
+      cfg_mslookup_cmd,
+      "mslookup",
+      "Configure Distributed GSM mslookup")
+{
+	vty->node = MSLOOKUP_NODE;
+	return CMD_SUCCESS;
+}
+
+static int mslookup_server_mdns_bind(struct vty *vty, int argc, const char **argv)
+{
+	const char *ip_str = argc > 0? argv[0] : g_hlr->mslookup.server.mdns.bind_addr.ip;
+	const char *port_str = argc > 1? argv[1] : NULL;
+	uint16_t port_nr = port_str ? atoi(port_str) : g_hlr->mslookup.server.mdns.bind_addr.port;
+	struct osmo_sockaddr_str addr;
+	if (osmo_sockaddr_str_from_str(&addr, ip_str, port_nr)
+	    || !osmo_sockaddr_str_is_nonzero(&addr)) {
+		vty_out(vty, "%% mslookup server: Invalid mDNS bind address: %s %u%s",
+			ip_str, port_nr, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	g_hlr->mslookup.server.mdns.bind_addr = addr;
+	g_hlr->mslookup.server.mdns.enable = true;
+	g_hlr->mslookup.server.enable = true;
+	mslookup_server_mdns_config_apply();
+	return CMD_SUCCESS;
+}
+
+#define MDNS_STR "Multicast DNS related configuration\n"
+#define MDNS_IP46_STR "multicast IPv4 address like " OSMO_MSLOOKUP_MDNS_IP4 \
+			" or IPv6 address like " OSMO_MSLOOKUP_MDNS_IP6 "\n"
+#define MDNS_PORT_STR "mDNS UDP Port number\n"
+#define MDNS_DOMAIN_SUFFIX_STR "mDNS domain suffix (default: " OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT "). This is appended" \
+				 " and stripped from mDNS packets during encoding/decoding, so we don't collide with" \
+				 " top-level domains administrated by IANA\n"
+#define IP46_STR "IPv4 address like 1.2.3.4 or IPv6 address like a:b:c:d::1\n"
+#define PORT_STR "Service-specific port number\n"
+
+struct cmd_node mslookup_server_node = {
+	MSLOOKUP_SERVER_NODE,
+	"%s(config-mslookup-server)# ",
+	1,
+};
+
+DEFUN(cfg_mslookup_server,
+      cfg_mslookup_server_cmd,
+      "server",
+      "Enable and configure Distributed GSM mslookup server")
+{
+	vty->node = MSLOOKUP_SERVER_NODE;
+	g_hlr->mslookup.server.enable = true;
+	mslookup_server_mdns_config_apply();
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mslookup_no_server,
+      cfg_mslookup_no_server_cmd,
+      "no server",
+      NO_STR "Disable Distributed GSM mslookup server")
+{
+	g_hlr->mslookup.server.enable = false;
+	mslookup_server_mdns_config_apply();
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mslookup_server_mdns_bind,
+      cfg_mslookup_server_mdns_bind_cmd,
+      "mdns bind [IP] [<1-65535>]",
+      MDNS_STR
+      "Configure where the mDNS server listens for mslookup requests\n"
+      MDNS_IP46_STR MDNS_PORT_STR)
+{
+	return mslookup_server_mdns_bind(vty, argc, argv);
+}
+
+DEFUN(cfg_mslookup_server_mdns_domain_suffix,
+      cfg_mslookup_server_mdns_domain_suffix_cmd,
+      "mdns domain-suffix DOMAIN_SUFFIX",
+      MDNS_STR
+      MDNS_DOMAIN_SUFFIX_STR
+      MDNS_DOMAIN_SUFFIX_STR)
+{
+	osmo_talloc_replace_string(g_hlr, &g_hlr->mslookup.server.mdns.domain_suffix, argv[0]);
+	mslookup_server_mdns_config_apply();
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mslookup_server_no_mdns_bind,
+      cfg_mslookup_server_no_mdns_bind_cmd,
+      "no mdns bind",
+      NO_STR "Disable server for mDNS mslookup (do not answer remote requests)\n")
+{
+	g_hlr->mslookup.server.mdns.enable = false;
+	mslookup_server_mdns_config_apply();
+	return CMD_SUCCESS;
+}
+
+struct cmd_node mslookup_server_msc_node = {
+	MSLOOKUP_SERVER_MSC_NODE,
+	"%s(config-mslookup-server-msc)# ",
+	1,
+};
+
+DEFUN(cfg_mslookup_server_msc,
+      cfg_mslookup_server_msc_cmd,
+      "msc ipa-name .IPA_NAME",
+      "Configure services for individual local MSCs\n"
+      "Identify locally connected MSC by IPA Unit Name\n"
+      "IPA Unit Name of the local MSC to configure\n")
+{
+	struct osmo_ipa_name msc_name;
+	struct mslookup_server_msc_cfg *msc;
+	osmo_ipa_name_set_str(&msc_name, argv_concat(argv, argc, 0));
+
+	msc = mslookup_server_msc_get(&msc_name, true);
+	if (!msc) {
+		vty_out(vty, "%% Error creating MSC %s%s", osmo_ipa_name_to_str(&msc_name), VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	vty->node = MSLOOKUP_SERVER_MSC_NODE;
+	vty->index = msc;
+	return CMD_SUCCESS;
+}
+
+#define SERVICE_NAME_STR \
+	"mslookup service name, e.g. sip.voice or smpp.sms\n"
+
+static struct mslookup_server_msc_cfg *msc_from_node(struct vty *vty)
+{
+	switch (vty->node) {
+	case MSLOOKUP_SERVER_NODE:
+		/* On the mslookup.server node, set services on the wildcard msc, without a particular name. */
+		return mslookup_server_msc_get(&mslookup_server_msc_wildcard, true);
+	case MSLOOKUP_SERVER_MSC_NODE:
+		return vty->index;
+	default:
+		return NULL;
+	}
+}
+
+DEFUN(cfg_mslookup_server_msc_service,
+      cfg_mslookup_server_msc_service_cmd,
+      "service NAME at IP <1-65535>",
+      "Configure addresses of local services, as sent in replies to remote mslookup requests.\n"
+      SERVICE_NAME_STR "at\n" IP46_STR PORT_STR)
+{
+	/* If this command is run on the 'server' node, it produces an empty unit name and serves as wildcard for all
+	 * MSCs. If on a 'server' / 'msc' node, set services only for that MSC Unit Name. */
+	struct mslookup_server_msc_cfg *msc = msc_from_node(vty);
+	const char *service = argv[0];
+	const char *ip_str = argv[1];
+	const char *port_str = argv[2];
+	struct osmo_sockaddr_str addr;
+
+	if (!msc) {
+		vty_out(vty, "%% Error: no MSC object on this node%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (osmo_sockaddr_str_from_str(&addr, ip_str, atoi(port_str))
+	    || !osmo_sockaddr_str_is_nonzero(&addr)) {
+		vty_out(vty, "%% mslookup server: Invalid address for service %s: %s %s%s",
+			service, ip_str, port_str, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (mslookup_server_msc_service_set(msc, service, &addr)) {
+		vty_out(vty, "%% mslookup server: Error setting service %s to %s %s%s",
+			service, ip_str, port_str, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	return CMD_SUCCESS;
+}
+
+#define NO_SERVICE_AND_NAME_STR NO_STR "Remove one or more service address entries\n" SERVICE_NAME_STR
+
+DEFUN(cfg_mslookup_server_msc_no_service,
+      cfg_mslookup_server_msc_no_service_cmd,
+      "no service NAME",
+      NO_SERVICE_AND_NAME_STR)
+{
+	/* If this command is run on the 'server' node, it produces an empty unit name and serves as wildcard for all
+	 * MSCs. If on a 'server' / 'msc' node, set services only for that MSC Unit Name. */
+	struct mslookup_server_msc_cfg *msc = msc_from_node(vty);
+	const char *service = argv[0];
+
+	if (!msc) {
+		vty_out(vty, "%% Error: no MSC object on this node%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (mslookup_server_msc_service_del(msc, service, NULL) < 1) {
+		vty_out(vty, "%% mslookup server: cannot remove service '%s'%s",
+			service, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_mslookup_server_msc_no_service_addr,
+      cfg_mslookup_server_msc_no_service_addr_cmd,
+      "no service NAME at IP <1-65535>",
+      NO_SERVICE_AND_NAME_STR "at\n" IP46_STR PORT_STR)
+{
+	/* If this command is run on the 'server' node, it produces an empty unit name and serves as wildcard for all
+	 * MSCs. If on a 'server' / 'msc' node, set services only for that MSC Unit Name. */
+	struct mslookup_server_msc_cfg *msc = msc_from_node(vty);
+	const char *service = argv[0];
+	const char *ip_str = argv[1];
+	const char *port_str = argv[2];
+	struct osmo_sockaddr_str addr;
+
+	if (!msc) {
+		vty_out(vty, "%% Error: no MSC object on this node%s", VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (osmo_sockaddr_str_from_str(&addr, ip_str, atoi(port_str))
+	    || !osmo_sockaddr_str_is_nonzero(&addr)) {
+		vty_out(vty, "%% mslookup server: Invalid address for 'no service' %s: %s %s%s",
+			service, ip_str, port_str, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+
+	if (mslookup_server_msc_service_del(msc, service, &addr) < 1) {
+		vty_out(vty, "%% mslookup server: cannot remove service '%s' to %s %s%s",
+			service, ip_str, port_str, VTY_NEWLINE);
+		return CMD_WARNING;
+	}
+	return CMD_SUCCESS;
+}
+
+void config_write_msc_services(struct vty *vty, const char *indent, struct mslookup_server_msc_cfg *msc)
+{
+	struct mslookup_service_host *e;
+
+	llist_for_each_entry(e, &msc->service_hosts, entry) {
+		if (osmo_sockaddr_str_is_nonzero(&e->host_v4))
+			vty_out(vty, "%sservice %s at %s %u%s", indent, e->service, e->host_v4.ip, e->host_v4.port,
+				VTY_NEWLINE);
+		if (osmo_sockaddr_str_is_nonzero(&e->host_v6))
+			vty_out(vty, "%sservice %s at %s %u%s", indent, e->service, e->host_v6.ip, e->host_v6.port,
+				VTY_NEWLINE);
+	}
+}
+
+int config_write_mslookup(struct vty *vty)
+{
+	if (!g_hlr->mslookup.server.enable
+	    && llist_empty(&g_hlr->mslookup.server.local_site_services))
+		return CMD_SUCCESS;
+
+	vty_out(vty, "mslookup%s", VTY_NEWLINE);
+
+	if (g_hlr->mslookup.server.enable || !llist_empty(&g_hlr->mslookup.server.local_site_services)) {
+		struct mslookup_server_msc_cfg *msc;
+
+		vty_out(vty, " server%s", VTY_NEWLINE);
+
+		if (g_hlr->mslookup.server.mdns.enable) {
+			vty_out(vty, "  mdns bind");
+			if (osmo_sockaddr_str_is_nonzero(&g_hlr->mslookup.server.mdns.bind_addr)) {
+				vty_out(vty, " %s %u",
+					g_hlr->mslookup.server.mdns.bind_addr.ip,
+					g_hlr->mslookup.server.mdns.bind_addr.port);
+			}
+			vty_out(vty, "%s", VTY_NEWLINE);
+		}
+		if (strcmp(g_hlr->mslookup.server.mdns.domain_suffix, OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT))
+			vty_out(vty, "  mdns domain-suffix %s%s",
+				g_hlr->mslookup.server.mdns.domain_suffix,
+				VTY_NEWLINE);
+
+		msc = mslookup_server_msc_get(&mslookup_server_msc_wildcard, false);
+		if (msc)
+			config_write_msc_services(vty, " ", msc);
+
+		llist_for_each_entry(msc, &g_hlr->mslookup.server.local_site_services, entry) {
+			if (!osmo_ipa_name_cmp(&mslookup_server_msc_wildcard, &msc->name))
+				continue;
+			vty_out(vty, " msc %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE);
+			config_write_msc_services(vty, "  ", msc);
+		}
+
+		/* If the server is disabled, still output the above to not lose the service config. */
+		if (!g_hlr->mslookup.server.enable)
+			vty_out(vty, " no server%s", VTY_NEWLINE);
+	}
+
+	return CMD_SUCCESS;
+}
+
+DEFUN(do_mslookup_show_services,
+      do_mslookup_show_services_cmd,
+      "show mslookup services",
+      SHOW_STR "Distributed GSM / mslookup related information\n"
+      "List configured service addresses as sent to remote mslookup requests\n")
+{
+	struct mslookup_server_msc_cfg *msc;
+	const struct mslookup_service_host *local_hlr = mslookup_server_get_local_gsup_addr();
+
+	vty_out(vty, "Local GSUP HLR address returned in mslookup responses for local IMSIs:");
+	if (osmo_sockaddr_str_is_nonzero(&local_hlr->host_v4))
+		vty_out(vty, " " OSMO_SOCKADDR_STR_FMT,
+			OSMO_SOCKADDR_STR_FMT_ARGS(&local_hlr->host_v4));
+	if (osmo_sockaddr_str_is_nonzero(&local_hlr->host_v6))
+		vty_out(vty, " " OSMO_SOCKADDR_STR_FMT,
+			OSMO_SOCKADDR_STR_FMT_ARGS(&local_hlr->host_v6));
+	vty_out(vty, "%s", VTY_NEWLINE);
+
+	msc = mslookup_server_msc_get(&mslookup_server_msc_wildcard, false);
+	if (msc)
+		config_write_msc_services(vty, "", msc);
+
+	llist_for_each_entry(msc, &g_hlr->mslookup.server.local_site_services, entry) {
+		if (!osmo_ipa_name_cmp(&mslookup_server_msc_wildcard, &msc->name))
+			continue;
+		vty_out(vty, "msc ipa-name %s%s", osmo_ipa_name_to_str(&msc->name), VTY_NEWLINE);
+		config_write_msc_services(vty, " ", msc);
+	}
+	return CMD_SUCCESS;
+}
+
+void dgsm_vty_init(void)
+{
+	install_element(CONFIG_NODE, &cfg_mslookup_cmd);
+
+	install_node(&mslookup_node, config_write_mslookup);
+	install_element(MSLOOKUP_NODE, &cfg_mslookup_server_cmd);
+	install_element(MSLOOKUP_NODE, &cfg_mslookup_no_server_cmd);
+
+	install_node(&mslookup_server_node, NULL);
+	install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_mdns_bind_cmd);
+	install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_mdns_domain_suffix_cmd);
+	install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_no_mdns_bind_cmd);
+	install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_service_cmd);
+	install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_no_service_cmd);
+	install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_no_service_addr_cmd);
+	install_element(MSLOOKUP_SERVER_NODE, &cfg_mslookup_server_msc_cmd);
+
+	install_node(&mslookup_server_msc_node, NULL);
+	install_element(MSLOOKUP_SERVER_MSC_NODE, &cfg_mslookup_server_msc_service_cmd);
+	install_element(MSLOOKUP_SERVER_MSC_NODE, &cfg_mslookup_server_msc_no_service_cmd);
+	install_element(MSLOOKUP_SERVER_MSC_NODE, &cfg_mslookup_server_msc_no_service_addr_cmd);
+
+	install_element_ve(&do_mslookup_show_services_cmd);
+}
diff --git a/src/hlr.c b/src/hlr.c
index 2cabab4..5e015b3 100644
--- a/src/hlr.c
+++ b/src/hlr.c
@@ -48,6 +48,7 @@
 #include <osmocom/hlr/hlr_vty.h>
 #include <osmocom/hlr/hlr_ussd.h>
 #include <osmocom/hlr/lu_fsm.h>
+#include <osmocom/mslookup/mdns.h>
 
 struct hlr *g_hlr;
 static void *hlr_ctx = NULL;
@@ -697,6 +698,7 @@
 	INIT_LLIST_HEAD(&g_hlr->ussd_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);
 
 	/* Init default (call independent) SS session guard timeout value */
 	g_hlr->ncss_guard_timeout = NCSS_GUARD_TIMEOUT_DEFAULT;
@@ -712,6 +714,7 @@
 	ctrl_vty_init(hlr_ctx);
 	handle_options(argc, argv);
 	hlr_vty_init();
+	dgsm_vty_init();
 
 	rc = vty_read_config_file(cmdline_opts.config_file, NULL);
 	if (rc < 0) {
diff --git a/src/mslookup_server_mdns.c b/src/mslookup_server_mdns.c
new file mode 100644
index 0000000..0e94074
--- /dev/null
+++ b/src/mslookup_server_mdns.c
@@ -0,0 +1,157 @@
+/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info at sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <osmocom/mslookup/mslookup.h>
+#include <osmocom/mslookup/mdns.h>
+#include <osmocom/hlr/logging.h>
+#include <osmocom/hlr/hlr.h>
+#include <osmocom/hlr/mslookup_server.h>
+#include <osmocom/hlr/mslookup_server_mdns.h>
+
+static void osmo_mslookup_server_mdns_tx(struct osmo_mslookup_server_mdns *server,
+					 uint16_t packet_id,
+					 const struct osmo_mslookup_query *query,
+					 const struct osmo_mslookup_result *result)
+{
+	struct msgb *msg;
+	const char *errmsg = NULL;
+	void *ctx = talloc_named_const(server, 0, __func__);
+
+	msg = osmo_mdns_result_encode(ctx, packet_id, query, result, server->domain_suffix);
+	if (!msg)
+		errmsg = "Error encoding mDNS answer packet";
+	else if (osmo_mdns_sock_send(server->sock, msg))
+		errmsg = "Error sending mDNS answer";
+	if (errmsg)
+		LOGP(DMSLOOKUP, LOGL_ERROR, "%s: mDNS: %s\n", osmo_mslookup_result_name_c(ctx, query, result), errmsg);
+	talloc_free(ctx);
+}
+
+static void osmo_mslookup_server_mdns_handle_request(uint16_t packet_id,
+						     struct osmo_mslookup_server_mdns *server,
+						     const struct osmo_mslookup_query *query)
+{
+	struct osmo_mslookup_result result;
+
+	mslookup_server_rx(query, &result);
+	/* Error logging already happens in mslookup_server_rx() */
+	if (result.rc != OSMO_MSLOOKUP_RC_RESULT)
+		return;
+
+	osmo_mslookup_server_mdns_tx(server, packet_id, query, &result);
+}
+
+static int osmo_mslookup_server_mdns_rx(struct osmo_fd *osmo_fd, unsigned int what)
+{
+	struct osmo_mslookup_server_mdns *server = osmo_fd->data;
+	struct osmo_mslookup_query *query;
+	uint16_t packet_id;
+	int n;
+	uint8_t buffer[1024];
+	void *ctx;
+
+	/* Parse the message and print it */
+	n = read(osmo_fd->fd, buffer, sizeof(buffer));
+	if (n < 0)
+		return n;
+
+	ctx = talloc_named_const(server, 0, __func__);
+	query = osmo_mdns_query_decode(ctx, buffer, n, &packet_id, server->domain_suffix);
+	if (!query) {
+		talloc_free(ctx);
+		return -1;
+	}
+
+	osmo_mslookup_id_name_buf((char *)buffer, sizeof(buffer), &query->id);
+	LOGP(DMSLOOKUP, LOGL_DEBUG, "mDNS rx request: %s.%s\n", query->service, buffer);
+	osmo_mslookup_server_mdns_handle_request(packet_id, server, query);
+	talloc_free(ctx);
+	return n;
+}
+
+struct osmo_mslookup_server_mdns *osmo_mslookup_server_mdns_start(void *ctx, const struct osmo_sockaddr_str *bind_addr,
+								  const char *domain_suffix)
+{
+	struct osmo_mslookup_server_mdns *server = talloc_zero(ctx, struct osmo_mslookup_server_mdns);
+	OSMO_ASSERT(server);
+	*server = (struct osmo_mslookup_server_mdns){
+		.bind_addr = *bind_addr,
+		.domain_suffix = talloc_strdup(server, domain_suffix)
+	};
+
+	server->sock = osmo_mdns_sock_init(server,
+					   bind_addr->ip, bind_addr->port,
+					   osmo_mslookup_server_mdns_rx,
+					   server, 0);
+	if (!server->sock) {
+		LOGP(DMSLOOKUP, LOGL_ERROR,
+		     "mslookup mDNS server: error initializing multicast bind on " OSMO_SOCKADDR_STR_FMT "\n",
+		     OSMO_SOCKADDR_STR_FMT_ARGS(bind_addr));
+		talloc_free(server);
+		return NULL;
+	}
+
+	return server;
+}
+
+void osmo_mslookup_server_mdns_stop(struct osmo_mslookup_server_mdns *server)
+{
+	if (!server)
+		return;
+	osmo_mdns_sock_cleanup(server->sock);
+	talloc_free(server);
+}
+
+void mslookup_server_mdns_config_apply()
+{
+	/* Check whether to start/stop/restart mDNS server */
+	bool should_run;
+	bool should_stop;
+
+	should_run = g_hlr->mslookup.allow_startup
+		&& g_hlr->mslookup.server.enable && g_hlr->mslookup.server.mdns.enable;
+	should_stop = g_hlr->mslookup.server.mdns.running
+		&& (!should_run
+		    || osmo_sockaddr_str_cmp(&g_hlr->mslookup.server.mdns.bind_addr,
+					     &g_hlr->mslookup.server.mdns.running->bind_addr)
+		    || strcmp(g_hlr->mslookup.server.mdns.domain_suffix,
+			      g_hlr->mslookup.server.mdns.running->domain_suffix));
+
+	if (should_stop) {
+		osmo_mslookup_server_mdns_stop(g_hlr->mslookup.server.mdns.running);
+		g_hlr->mslookup.server.mdns.running = NULL;
+		LOGP(DMSLOOKUP, LOGL_NOTICE, "Stopped mslookup mDNS server\n");
+	}
+
+	if (should_run && !g_hlr->mslookup.server.mdns.running) {
+		g_hlr->mslookup.server.mdns.running =
+			osmo_mslookup_server_mdns_start(g_hlr, &g_hlr->mslookup.server.mdns.bind_addr,
+							g_hlr->mslookup.server.mdns.domain_suffix);
+		if (!g_hlr->mslookup.server.mdns.running)
+			LOGP(DMSLOOKUP, LOGL_ERROR, "Failed to start mslookup mDNS server on " OSMO_SOCKADDR_STR_FMT "\n",
+			     OSMO_SOCKADDR_STR_FMT_ARGS(&g_hlr->mslookup.server.mdns.bind_addr));
+		else
+			LOGP(DMSLOOKUP, LOGL_NOTICE, "Started mslookup mDNS server, receiving mDNS requests at multicast "
+			     OSMO_SOCKADDR_STR_FMT "\n",
+			     OSMO_SOCKADDR_STR_FMT_ARGS(&g_hlr->mslookup.server.mdns.running->bind_addr));
+	}
+}
diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty
index c056e4d..ee351e3 100644
--- a/tests/test_nodes.vty
+++ b/tests/test_nodes.vty
@@ -15,6 +15,7 @@
   show gsup-connections
   subscriber (imsi|msisdn|id|imei) IDENT show
   show subscriber (imsi|msisdn|id|imei) IDENT
+  show mslookup services
 
 OsmoHLR> enable
 OsmoHLR# ?
@@ -25,9 +26,11 @@
 OsmoHLR(config)# ?
 ...
   hlr       Configure the HLR
+  mslookup  Configure Distributed GSM mslookup
 OsmoHLR(config)# list
 ...
   hlr
+  mslookup
 
 OsmoHLR(config)# hlr
 OsmoHLR(config-hlr)# ?
diff --git a/tests/test_subscriber.vty b/tests/test_subscriber.vty
index 8e9026d..fb5da0e 100644
--- a/tests/test_subscriber.vty
+++ b/tests/test_subscriber.vty
@@ -13,6 +13,7 @@
   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 imei (none|IMEI)
   subscriber (imsi|msisdn|id|imei) IDENT update network-access-mode (none|cs|ps|cs+ps)
+  show mslookup services
 
 OsmoHLR# subscriber?
   subscriber  Subscriber management commands

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-hlr/+/16257
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-hlr
Gerrit-Branch: master
Gerrit-Change-Id: I5cae6459090588b4dd292be90a5e8903432669d2
Gerrit-Change-Number: 16257
Gerrit-PatchSet: 25
Gerrit-Owner: neels <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: keith <keith at rhizomatica.org>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: neels <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: osmith <osmith at sysmocom.de>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200501/fcb48f2b/attachment.htm>


More information about the gerrit-log mailing list