Change in libosmo-sccp[master]: ss7: Support multiple addresses in SCTP connections

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/.

pespin gerrit-no-reply at lists.osmocom.org
Fri Oct 11 19:32:19 UTC 2019


pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-sccp/+/15785 )


Change subject: ss7: Support multiple addresses in SCTP connections
......................................................................

ss7: Support multiple addresses in SCTP connections

After this patch, Several "local-ip" and "remote-ip" lines are accepted
under "listen" and "asp" VTY nodes, allowing to configure an SCTP
connection with multiple connections, hence allowing control of SCTP
multi-homing features.
libosmo-sccp clients such as osmo-bsc and osmo-msc also gain support for
this feature with this commit.

Related: OS#3608
Depends: libosmocore.git Ic8681d9e093216c99c6bca4be81c31ef83688ed1
Depends: libosmo-netif.git I0fe62f518e195db4e34f3b0ad1762bb57ba9d92a
Change-Id: Ibd15de7a4e00dbec78ff2e2dd6a686b0f3af22de
---
M include/osmocom/sigtran/osmo_ss7.h
M src/osmo_ss7.c
M src/osmo_ss7_vty.c
M src/sccp_user.c
4 files changed, 169 insertions(+), 38 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/85/15785/1

diff --git a/include/osmocom/sigtran/osmo_ss7.h b/include/osmocom/sigtran/osmo_ss7.h
index b1d4dab..f472b44 100644
--- a/include/osmocom/sigtran/osmo_ss7.h
+++ b/include/osmocom/sigtran/osmo_ss7.h
@@ -8,6 +8,7 @@
 #include <osmocom/core/fsm.h>
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/prim.h>
+#include <osmocom/core/socket.h>
 
 extern struct llist_head osmo_ss7_instances;
 
@@ -342,7 +343,8 @@
  ***********************************************************************/
 
 struct osmo_ss7_asp_peer {
-	char *host;
+	char *host[OSMO_SOCK_MAX_ADDRS];
+	size_t host_cnt;
 	uint16_t port;
 };
 
@@ -403,6 +405,8 @@
 	} cfg;
 };
 
+int osmo_ss7_asp_peer_snprintf(char* buf, size_t buf_len, struct osmo_ss7_asp_peer *peer);
+
 struct osmo_ss7_asp *
 osmo_ss7_asp_find_by_name(struct osmo_ss7_instance *inst, const char *name);
 struct osmo_ss7_asp
@@ -468,7 +472,9 @@
 
 int
 osmo_ss7_xua_server_set_local_host(struct osmo_xua_server *xs, const char *local_host);
-
+int
+osmo_ss7_xua_server_set_local_hosts(struct osmo_xua_server *xs, const char **local_hosts, size_t local_host_cnt);
+int osmo_ss7_xua_server_add_local_host(struct osmo_xua_server *xs, const char *local_host);
 void osmo_ss7_xua_server_destroy(struct osmo_xua_server *xs);
 
 struct osmo_sccp_instance *
diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c
index 1312cf3..e8a0646 100644
--- a/src/osmo_ss7.c
+++ b/src/osmo_ss7.c
@@ -1070,6 +1070,37 @@
  * SS7 Application Server Process
  ***********************************************************************/
 
+int osmo_ss7_asp_peer_snprintf(char* buf, size_t buf_len, struct osmo_ss7_asp_peer *peer)
+{
+	int len = 0, offset = 0, rem = buf_len;
+	int ret, i;
+	char *after;
+
+	if (buf_len < 3)
+		return -EINVAL;
+
+	if (peer->host_cnt != 1) {
+		ret = snprintf(buf, rem, "(");
+		if (ret < 0)
+			return ret;
+		OSMO_SNPRINTF_RET(ret, rem, offset, len);
+	}
+	for (i = 0; i < peer->host_cnt; i++) {
+		if (peer->host_cnt == 1)
+			after = "";
+		else
+			after = (i == (peer->host_cnt - 1)) ? ")" : "|";
+		ret = snprintf(buf + offset, rem, "%s%s", peer->host[i] ? : "0.0.0.0", after);
+		OSMO_SNPRINTF_RET(ret, rem, offset, len);
+	}
+	ret = snprintf(buf + offset, rem, ":%u", peer->port);
+	if (ret < 0)
+		return ret;
+	OSMO_SNPRINTF_RET(ret, rem, offset, len);
+
+	return len;
+}
+
 struct osmo_ss7_asp *
 osmo_ss7_asp_find_by_name(struct osmo_ss7_instance *inst, const char *name)
 {
@@ -1108,6 +1139,7 @@
 	char hostbuf_l[64], hostbuf_r[64];
 	uint16_t local_port, remote_port;
 	int rc;
+	int i;
 
 	OSMO_ASSERT(ss7_initialized);
 	/* convert local and remote IP to string */
@@ -1134,11 +1166,26 @@
 	llist_for_each_entry(inst, &osmo_ss7_instances, list) {
 		struct osmo_ss7_asp *asp;
 		llist_for_each_entry(asp, &inst->asp_list, list) {
-			if (asp->cfg.local.port == local_port &&
-			    (!asp->cfg.remote.port ||asp->cfg.remote.port == remote_port) &&
-			    (!asp->cfg.local.host || !strcmp(asp->cfg.local.host, hostbuf_l)) &&
-			    (!asp->cfg.remote.host || !strcmp(asp->cfg.remote.host, hostbuf_r)))
-				return asp;
+			if (asp->cfg.local.port != local_port)
+				continue;
+			if (asp->cfg.remote.port && asp->cfg.remote.port != remote_port)
+				continue;
+
+			for (i = 0; i < asp->cfg.local.host_cnt; i++) {
+				if (!asp->cfg.local.host[i] || !strcmp(asp->cfg.local.host[i], hostbuf_l))
+					break;
+			}
+			if (i == asp->cfg.local.host_cnt)
+				continue; /* didn't match any local.host */
+
+			for (i = 0; i < asp->cfg.remote.host_cnt; i++) {
+				if (!asp->cfg.remote.host[i] || !strcmp(asp->cfg.remote.host[i], hostbuf_r))
+					break;
+			}
+			if (i == asp->cfg.remote.host_cnt)
+				continue; /* didn't match any remote.host */
+
+			return asp;
 		}
 	}
 
@@ -1255,9 +1302,9 @@
 			return -1;
 		}
 		osmo_stream_cli_set_nodelay(asp->client, true);
-		osmo_stream_cli_set_addr(asp->client, asp->cfg.remote.host);
+		osmo_stream_cli_set_addrs(asp->client, (const char**)asp->cfg.remote.host, asp->cfg.remote.host_cnt);
 		osmo_stream_cli_set_port(asp->client, asp->cfg.remote.port);
-		osmo_stream_cli_set_local_addr(asp->client, asp->cfg.local.host);
+		osmo_stream_cli_set_local_addrs(asp->client, (const char**)asp->cfg.local.host, asp->cfg.local.host_cnt);
 		osmo_stream_cli_set_local_port(asp->client, asp->cfg.local.port);
 		osmo_stream_cli_set_proto(asp->client, asp_proto_to_ip_proto(asp->cfg.proto));
 		osmo_stream_cli_set_reconnect_timeout(asp->client, 5);
@@ -1704,8 +1751,11 @@
 				LOGP(DLSS7, LOGL_INFO, "%s: created dynamicASP %s\n",
 					sock_name, asp->cfg.name);
 				asp->cfg.is_server = true;
+				asp->cfg.local.host[0] = NULL;
+				asp->cfg.remote.host_cnt = 1;
 				asp->cfg.remote.port = atoi(portbuf);
-				asp->cfg.remote.host = talloc_strdup(asp, hostbuf);
+				asp->cfg.remote.host[0] = talloc_strdup(asp, hostbuf);
+				asp->cfg.remote.host_cnt = 1;
 				asp->dyn_allocated = true;
 				asp->server = srv;
 				osmo_ss7_asp_restart(asp);
@@ -1837,17 +1887,17 @@
 
 	oxs->cfg.proto = proto;
 	oxs->cfg.local.port = local_port;
-	oxs->cfg.local.host = talloc_strdup(oxs, local_host);
 
 	oxs->server = osmo_stream_srv_link_create(oxs);
 	osmo_stream_srv_link_set_data(oxs->server, oxs);
 	osmo_stream_srv_link_set_accept_cb(oxs->server, xua_accept_cb);
 
 	osmo_stream_srv_link_set_nodelay(oxs->server, true);
-	osmo_stream_srv_link_set_addr(oxs->server, oxs->cfg.local.host);
 	osmo_stream_srv_link_set_port(oxs->server, oxs->cfg.local.port);
 	osmo_stream_srv_link_set_proto(oxs->server, asp_proto_to_ip_proto(proto));
 
+	osmo_ss7_xua_server_set_local_host(oxs, local_host);
+
 	LOGP(DLSS7, LOGL_INFO, "Created %s server on %s:%" PRIu16 "\n",
 		get_value_string(osmo_ss7_asp_protocol_vals, proto), local_host, local_port);
 
@@ -1868,20 +1918,74 @@
 int
 osmo_ss7_xua_server_bind(struct osmo_xua_server *xs)
 {
-	LOGP(DLSS7, LOGL_INFO, "(Re)binding %s Server to %s:%u\n",
-		get_value_string(osmo_ss7_asp_protocol_vals, xs->cfg.proto),
-		xs->cfg.local.host, xs->cfg.local.port);
+	char buf[512];
+	int rc;
+	const char *proto = get_value_string(osmo_ss7_asp_protocol_vals, xs->cfg.proto);
+
+	rc = osmo_ss7_asp_peer_snprintf(buf, sizeof(buf), &xs->cfg.local);
+	if (rc < 0) {
+		LOGP(DLSS7, LOGL_INFO, "Failed parsing %s Server osmo_ss7_asp_peer\n", proto);
+	} else {
+		LOGP(DLSS7, LOGL_INFO, "(Re)binding %s Server to %s\n",
+		     proto, buf);
+	}
 	return osmo_stream_srv_link_open(xs->server);
 }
 
 int
 osmo_ss7_xua_server_set_local_host(struct osmo_xua_server *xs, const char *local_host)
 {
+	osmo_ss7_xua_server_set_local_hosts(xs, &local_host, 1);
+	return 0;
+}
+
+int
+osmo_ss7_xua_server_set_local_hosts(struct osmo_xua_server *xs, const char **local_hosts, size_t local_host_cnt)
+{
+	int i = 0;
 	OSMO_ASSERT(ss7_initialized);
-	osmo_talloc_replace_string(xs, &xs->cfg.local.host, local_host);
 
-	osmo_stream_srv_link_set_addr(xs->server, xs->cfg.local.host);
+	if (local_host_cnt > ARRAY_SIZE(xs->cfg.local.host))
+		return -EINVAL;
 
+	for (; i < local_host_cnt; i++)
+		osmo_talloc_replace_string(xs, &xs->cfg.local.host[i], local_hosts[i]);
+	for (; i < xs->cfg.local.host_cnt; i++) {
+			talloc_free(xs->cfg.local.host[i]);
+			xs->cfg.local.host[i] = NULL;
+	}
+
+	xs->cfg.local.host_cnt = local_host_cnt;
+
+	osmo_stream_srv_link_set_addrs(xs->server, (const char **)xs->cfg.local.host, xs->cfg.local.host_cnt);
+
+	return 0;
+}
+
+int
+osmo_ss7_xua_server_add_local_host(struct osmo_xua_server *xs, const char *local_host)
+{
+	int i;
+	bool new_is_any = !local_host || !strcmp(local_host, "0.0.0.0");
+	bool iter_is_any;
+
+	/* Makes no sense to have INET_ANY and specific addresses in the set */
+	for (; i < xs->cfg.local.host_cnt; i++) {
+			iter_is_any = !xs->cfg.local.host[i] ||
+				      !strcmp(xs->cfg.local.host[i], "0.0.0.0");
+			if (new_is_any && iter_is_any)
+				return -EINVAL;
+			if (!new_is_any && iter_is_any)
+				return -EINVAL;
+	}
+	/* Makes no sense to have INET_ANY many times */
+	if (new_is_any && xs->cfg.local.host_cnt)
+		return -EINVAL;
+
+	osmo_talloc_replace_string(xs, &xs->cfg.local.host[xs->cfg.local.host_cnt], local_host);
+	xs->cfg.local.host_cnt++;
+
+	osmo_stream_srv_link_set_addrs(xs->server, (const char **)xs->cfg.local.host, xs->cfg.local.host_cnt);
 	return 0;
 }
 
diff --git a/src/osmo_ss7_vty.c b/src/osmo_ss7_vty.c
index 56263ee..d384843 100644
--- a/src/osmo_ss7_vty.c
+++ b/src/osmo_ss7_vty.c
@@ -436,6 +436,8 @@
 		xs = osmo_ss7_xua_server_create(inst, proto, port, NULL);
 		if (!xs)
 			return CMD_SUCCESS;
+		/* Drop first dummy address created automatically by _create(): */
+		osmo_ss7_xua_server_set_local_hosts(xs, NULL, 0);
 	}
 
 	vty->node = L_CS7_XUA_NODE;
@@ -469,7 +471,7 @@
 {
 	struct osmo_xua_server *xs = vty->index;
 
-	osmo_ss7_xua_server_set_local_host(xs, argv[0]);
+	osmo_ss7_xua_server_add_local_host(xs, argv[0]);
 
 	return CMD_SUCCESS;
 }
@@ -492,21 +494,26 @@
 
 static void write_one_xua(struct vty *vty, struct osmo_xua_server *xs)
 {
+	int i;
 	vty_out(vty, " listen %s %u%s",
 		get_value_string(osmo_ss7_asp_protocol_vals, xs->cfg.proto),
 		xs->cfg.local.port, VTY_NEWLINE);
-	if (xs->cfg.local.host)
-		vty_out(vty, "  local-ip %s%s", xs->cfg.local.host, VTY_NEWLINE);
+
+	for (i = 0; i < xs->cfg.local.host_cnt; i++) {
+		if (xs->cfg.local.host)
+			vty_out(vty, "  local-ip %s%s", xs->cfg.local.host[i], VTY_NEWLINE);
+	}
 	if (xs->cfg.accept_dyn_reg)
 		vty_out(vty, "  accept-asp-connections dynamic-permitted%s", VTY_NEWLINE);
 }
 
 static void vty_dump_xua_server(struct vty *vty, struct osmo_xua_server *xs)
 {
-	vty_out(vty, "xUA server for %s on %s:%u%s",
-		get_value_string(osmo_ss7_asp_protocol_vals, xs->cfg.proto),
-		xs->cfg.local.host ? xs->cfg.local.host : "0.0.0.0",
-		xs->cfg.local.port, VTY_NEWLINE);
+	char buf[512];
+	const char *proto = get_value_string(osmo_ss7_asp_protocol_vals, xs->cfg.proto);
+	if (osmo_ss7_asp_peer_snprintf(buf, sizeof(buf), &xs->cfg.local) < 0)
+		snprintf(buf, sizeof(buf), "<error>");
+	vty_out(vty, "xUA server for %s on %s%s", proto, buf, VTY_NEWLINE);
 }
 
 DEFUN(show_cs7_xua, show_cs7_xua_cmd,
@@ -604,7 +611,8 @@
 	"Local IP Address from which to contact of ASP\n")
 {
 	struct osmo_ss7_asp *asp = vty->index;
-	osmo_talloc_replace_string(asp, &asp->cfg.local.host, argv[0]);
+	osmo_talloc_replace_string(asp, &asp->cfg.local.host[asp->cfg.local.host_cnt], argv[0]);
+	asp->cfg.local.host_cnt++;
 	return CMD_SUCCESS;
 }
 
@@ -614,7 +622,8 @@
 	"Remote IP Address of ASP\n")
 {
 	struct osmo_ss7_asp *asp = vty->index;
-	osmo_talloc_replace_string(asp, &asp->cfg.remote.host, argv[0]);
+	osmo_talloc_replace_string(asp, &asp->cfg.remote.host[asp->cfg.remote.host_cnt], argv[0]);
+	asp->cfg.remote.host_cnt++;
 	return CMD_SUCCESS;
 }
 
@@ -652,6 +661,7 @@
 {
 	struct osmo_ss7_instance *inst;
 	struct osmo_ss7_asp *asp;
+	char buf[512];
 	int id = atoi(argv[0]);
 
 	inst = osmo_ss7_instance_find(id);
@@ -661,21 +671,23 @@
 	}
 
 	vty_out(vty, "                                                          Effect Primary%s", VTY_NEWLINE);
-	vty_out(vty, "ASP Name      AS Name       State          Type  Rmt Port Remote IP Addr  SCTP%s", VTY_NEWLINE);
-	vty_out(vty, "------------  ------------  -------------  ----  -------- --------------- ----------%s", VTY_NEWLINE);
+	vty_out(vty, "ASP Name      AS Name       State          Type Remote IP Addr  Rmt Port SCTP%s", VTY_NEWLINE);
+	vty_out(vty, "------------  ------------  -------------  ---- --------------  -------- ----------%s", VTY_NEWLINE);
 
 	llist_for_each_entry(asp, &inst->asp_list, list) {
-		vty_out(vty, "%-12s  %-12s  %-13s  %-4s  %-8u %-15s %-10s%s",
+		osmo_ss7_asp_peer_snprintf(buf, sizeof(buf), &asp->cfg.remote);
+		vty_out(vty, "%-12s  %-12s  %-13s  %-4s  %-23s  %-10s%s",
 			asp->cfg.name, "?",
 			asp->fi? osmo_fsm_inst_state_name(asp->fi) : "uninitialized",
 			get_value_string(osmo_ss7_asp_protocol_vals, asp->cfg.proto),
-			asp->cfg.remote.port, asp->cfg.remote.host, "", VTY_NEWLINE);
+			buf, "", VTY_NEWLINE);
 	}
 	return CMD_SUCCESS;
 }
 
 static void write_one_asp(struct vty *vty, struct osmo_ss7_asp *asp)
 {
+	int i;
 	/* skip any dynamically created ASPs (e.g. auto-created at connect time) */
 	if (asp->dyn_allocated || asp->simple_client_allocated)
 		return;
@@ -685,10 +697,14 @@
 		osmo_ss7_asp_protocol_name(asp->cfg.proto), VTY_NEWLINE);
 	if (asp->cfg.description)
 		vty_out(vty, "  description %s%s", asp->cfg.description, VTY_NEWLINE);
-	if (asp->cfg.local.host)
-		vty_out(vty, "  local-ip %s%s", asp->cfg.local.host, VTY_NEWLINE);
-	if (asp->cfg.remote.host)
-		vty_out(vty, "  remote-ip %s%s", asp->cfg.remote.host, VTY_NEWLINE);
+	for (i = 0; i < asp->cfg.local.host_cnt; i++) {
+		if (asp->cfg.local.host)
+			vty_out(vty, "  local-ip %s%s", asp->cfg.local.host[i], VTY_NEWLINE);
+	}
+	for (i = 0; i < asp->cfg.remote.host_cnt; i++) {
+		if (asp->cfg.remote.host)
+			vty_out(vty, "  remote-ip %s%s", asp->cfg.remote.host[i], VTY_NEWLINE);
+	}
 	if (asp->cfg.qos_class)
 		vty_out(vty, "  qos-class %u%s", asp->cfg.qos_class, VTY_NEWLINE);
 }
@@ -1689,6 +1705,9 @@
 		break;
 	case L_CS7_XUA_NODE:
 		oxs = vty->index;
+		/* If no local addr was set, or erased after _create(): */
+		if (!oxs->cfg.local.host_cnt)
+			osmo_ss7_xua_server_set_local_host(oxs, NULL);
 		if (osmo_ss7_xua_server_bind(oxs) < 0)
 			vty_out(vty, "%% Unable to bind xUA server to IP(s)%s", VTY_NEWLINE);
 		vty->node = L_CS7_NODE;
diff --git a/src/sccp_user.c b/src/sccp_user.c
index a1302d9..4e4144e 100644
--- a/src/sccp_user.c
+++ b/src/sccp_user.c
@@ -566,16 +566,18 @@
 				goto out_rt;
 			asp_created = true;
 
-			asp->cfg.local.host = NULL;
-			asp->cfg.remote.host = NULL;
+			asp->cfg.local.host[0] = NULL;
+			asp->cfg.remote.host[0] = NULL;
 			if (default_local_ip) {
-				asp->cfg.local.host =
+				asp->cfg.local.host[0] =
 				    talloc_strdup(asp, default_local_ip);
 			}
 			if (default_remote_ip) {
-				asp->cfg.remote.host =
+				asp->cfg.remote.host[0] =
 				    talloc_strdup(asp, default_remote_ip);
 			}
+			asp->cfg.local.host_cnt = 1;
+			asp->cfg.remote.host_cnt = 1;
 			asp->simple_client_allocated = true;
 		} else
 			talloc_free(asp_name);

-- 
To view, visit https://gerrit.osmocom.org/c/libosmo-sccp/+/15785
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Change-Id: Ibd15de7a4e00dbec78ff2e2dd6a686b0f3af22de
Gerrit-Change-Number: 15785
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20191011/cd5424f4/attachment.htm>


More information about the gerrit-log mailing list