From f594b7dfd209555bfd732d6d1254e768a9ec4fe5 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 5 Oct 2021 16:24:26 +0200 Subject: osmo_sccp_simple_client_on_ss7_id(): Allow set internally proper IPv4/v6 default hosts Allow user apps to relay the decision of proper default local/remote hosts values to the library. Proper configuration of these addresses can be quite cumbersome to get correctly, or confusing at least. That's due to the multi-homing feature of SCTP where both IPv4 and IPv6 are involved. We were already doing this kind of automatic setup in osmo_ss7_vty_go_parent(), where we do validations and assign addresses based on IPv6 availability. On the other hand, apps using osmo_sccp_simple_client_on_ss7_id() API usually pass "localhost" as default address. In Linux, when IPv6 is enabled localhost is resolved as "::1", and "127.0.0.1" when IPv6 is disabled. Let's instead allow apps to relay the setup to the lib, so same addresses can be applied both during VTY command as well as if there was no VTY setup at all. Related: OS#5186 Change-Id: I82e203612571b7651d758d8148661f706a1642ba --- src/Makefile.am | 2 +- src/osmo_ss7.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/osmo_ss7_vty.c | 64 +++--------------------------------------- src/sccp_user.c | 13 ++++++--- src/ss7_internal.h | 9 ++++++ 5 files changed, 104 insertions(+), 65 deletions(-) create mode 100644 src/ss7_internal.h diff --git a/src/Makefile.am b/src/Makefile.am index aee7fd5..9d5e9a3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) \ $(LIBOSMONETIF_CFLAGS) -noinst_HEADERS = sccp_internal.h xua_asp_fsm.h xua_as_fsm.h xua_internal.h +noinst_HEADERS = sccp_internal.h ss7_internal.h xua_asp_fsm.h xua_as_fsm.h xua_internal.h # Legacy static libs diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c index ebed9cf..e1e7ace 100644 --- a/src/osmo_ss7.c +++ b/src/osmo_ss7.c @@ -1225,6 +1225,73 @@ int osmo_ss7_asp_peer_add_host(struct osmo_ss7_asp_peer *peer, void *talloc_ctx, return 0; } +static bool ipv6_sctp_supported(const char *host, bool bind) +{ + int rc; + struct addrinfo hints; + struct addrinfo *result; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_NUMERICHOST; + hints.ai_protocol = 0; /* Any protocol */ + + if (bind) /* For wildcard IP address */ + hints.ai_flags |= AI_PASSIVE; + + /* man getaddrinfo: Either node or service, but not both, may be NULL. */ + OSMO_ASSERT(host); + rc = getaddrinfo(host, NULL, &hints, &result); + if (rc != 0) { + LOGP(DLSS7, LOGL_NOTICE, "Default IPv6 address %s not supported: %s\n", + host, gai_strerror(rc)); + return false; + } else { + freeaddrinfo(result); + return true; + } +} + +/* Set default values for local and remote peer hosts if they are not yet set. + * \param[in] asp ASP for which to set default hosts. + * \returns true if values where changed, false otherwise. + * + * If the ASP is already started, osmo_ss7_asp_restart() must be called + * afterwards in order to apply the new settings. + * This API is internal, hence doesn't appear in osmo_ss7.h + */ +bool osmo_ss7_asp_set_default_peer_hosts(struct osmo_ss7_asp *asp) +{ + bool changed = false; + /* If no local addr was set */ + if (!asp->cfg.local.host_cnt) { + bool rem_has_v4 = false, rem_has_v6 = false; + int i; + for (i = 0; i < asp->cfg.remote.host_cnt; i++) { + if (osmo_ip_str_type(asp->cfg.remote.host[i]) == AF_INET6) + rem_has_v6 = true; + else + rem_has_v4 = true; + } + /* "::" Covers both IPv4 and IPv6, but if only IPv4 + * address are set on the remote side, IPv4 on the local + * side must be set too */ + if (ipv6_sctp_supported("::", true) && !(rem_has_v4 && !rem_has_v6)) + osmo_ss7_asp_peer_add_host(&asp->cfg.local, asp, "::"); + else + osmo_ss7_asp_peer_add_host(&asp->cfg.local, asp, "0.0.0.0"); + changed = true; + } + /* If no remote addr was set */ + if (!asp->cfg.remote.host_cnt) { + osmo_ss7_asp_peer_add_host(&asp->cfg.remote, asp, "127.0.0.1"); + if (ipv6_sctp_supported("::1", false)) + osmo_ss7_asp_peer_add_host(&asp->cfg.remote, asp, "::1"); + changed = true; + } + return changed; +} + struct osmo_ss7_asp * osmo_ss7_asp_find_by_name(struct osmo_ss7_instance *inst, const char *name) { @@ -2171,6 +2238,20 @@ osmo_ss7_xua_server_add_local_host(struct osmo_xua_server *xs, const char *local return osmo_stream_srv_link_set_addrs(xs->server, (const char **)xs->cfg.local.host, xs->cfg.local.host_cnt); } +bool osmo_ss7_xua_server_set_default_local_hosts(struct osmo_xua_server *oxs) +{ + /* If no local addr was set, or erased after _create(): */ + if (!oxs->cfg.local.host_cnt) { + /* "::" Covers both IPv4 and IPv6 */ + if (ipv6_sctp_supported("::", true)) + osmo_ss7_xua_server_set_local_host(oxs, "::"); + else + osmo_ss7_xua_server_set_local_host(oxs, "0.0.0.0"); + return true; + } + return false; +} + void osmo_ss7_xua_server_destroy(struct osmo_xua_server *xs) { struct osmo_ss7_asp *asp, *asp2; diff --git a/src/osmo_ss7_vty.c b/src/osmo_ss7_vty.c index 3b39a61..8ee3087 100644 --- a/src/osmo_ss7_vty.c +++ b/src/osmo_ss7_vty.c @@ -45,8 +45,7 @@ #include "xua_internal.h" #include #include "sccp_internal.h" - -#include "sccp_internal.h" +#include "ss7_internal.h" #define XUA_VAR_STR "(sua|m3ua|ipa)" @@ -1937,33 +1936,6 @@ static void write_one_cs7(struct vty *vty, struct osmo_ss7_instance *inst, bool osmo_sccp_vty_write_cs7_node(vty, " ", inst->sccp); } -static bool ipv6_sctp_supported(const char *host, bool bind) -{ - int rc; - struct addrinfo hints; - struct addrinfo *result; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICHOST; - hints.ai_protocol = 0; /* Any protocol */ - - if (bind) /* For wildcard IP address */ - hints.ai_flags |= AI_PASSIVE; - - /* man getaddrinfo: Either node or service, but not both, may be NULL. */ - OSMO_ASSERT(host); - rc = getaddrinfo(host, NULL, &hints, &result); - if (rc != 0) { - LOGP(DLSS7, LOGL_NOTICE, "Default IPv6 address %s not supported: %s\n", - host, gai_strerror(rc)); - return false; - } else { - freeaddrinfo(result); - return true; - } -} - int osmo_ss7_vty_go_parent(struct vty *vty) { struct osmo_ss7_as *as; @@ -1975,30 +1947,8 @@ int osmo_ss7_vty_go_parent(struct vty *vty) switch (vty->node) { case L_CS7_ASP_NODE: asp = vty->index; - /* If no local addr was set */ - if (!asp->cfg.local.host_cnt) { - bool rem_has_v4 = false, rem_has_v6 = false; - int i; - for (i = 0; i < asp->cfg.remote.host_cnt; i++) { - if (osmo_ip_str_type(asp->cfg.remote.host[i]) == AF_INET6) - rem_has_v6 = true; - else - rem_has_v4 = true; - } - /* "::" Covers both IPv4 and IPv6, but if only IPv4 - * address are set on the remote side, IPv4 on the local - * side must be set too */ - if (ipv6_sctp_supported("::", true) && !(rem_has_v4 && !rem_has_v6)) - osmo_ss7_asp_peer_add_host(&asp->cfg.local, asp, "::"); - else - osmo_ss7_asp_peer_add_host(&asp->cfg.local, asp, "0.0.0.0"); - } - /* If no remote addr was set */ - if (!asp->cfg.remote.host_cnt) { - osmo_ss7_asp_peer_add_host(&asp->cfg.remote, asp, "127.0.0.1"); - if (ipv6_sctp_supported("::1", false)) - osmo_ss7_asp_peer_add_host(&asp->cfg.remote, asp, "::1"); - } + /* Make sure proper defaults values are set */ + osmo_ss7_asp_set_default_peer_hosts(asp); osmo_ss7_asp_restart(asp); vty->node = L_CS7_NODE; vty->index = asp->inst; @@ -2016,13 +1966,7 @@ int osmo_ss7_vty_go_parent(struct vty *vty) case L_CS7_XUA_NODE: oxs = vty->index; /* If no local addr was set, or erased after _create(): */ - if (!oxs->cfg.local.host_cnt) { - /* "::" Covers both IPv4 and IPv6 */ - if (ipv6_sctp_supported("::", true)) - osmo_ss7_xua_server_set_local_host(oxs, "::"); - else - osmo_ss7_xua_server_set_local_host(oxs, "0.0.0.0"); - } + osmo_ss7_xua_server_set_default_local_hosts(oxs); 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 a654cc6..ade9487 100644 --- a/src/sccp_user.c +++ b/src/sccp_user.c @@ -38,6 +38,7 @@ #include "sccp_internal.h" #include "xua_internal.h" +#include "ss7_internal.h" /*! \brief Find a SCCP User registered for given PC+SSN or SSN only * First search all users with a valid PC for a full PC+SSN match. @@ -476,9 +477,9 @@ const char *osmo_sccp_user_name(struct osmo_sccp_user *scu) * \param[in] default_pc pointcode to be used on missing VTY setting * \param[in] prot protocol to be used (e.g OSMO_SS7_ASP_PROT_M3UA) * \param[in] default_local_port local port to be used on missing VTY setting - * \param[in] default_local_ip local IP-address to be used on missing VTY setting + * \param[in] default_local_ip local IP-address to be used on missing VTY setting (NULL: use library own defaults) * \param[in] default_remote_port remote port to be used on missing VTY setting - * \param[in] default_remote_ip remote IP-address to be used on missing VTY setting + * \param[in] default_remote_ip remote IP-address to be used on missing VTY setting (NULL: use library own defaults) * \returns callee-allocated SCCP instance on success; NULL on error */ struct osmo_sccp_instance * @@ -618,8 +619,12 @@ osmo_sccp_simple_client_on_ss7_id(void *ctx, uint32_t ss7_id, const char *name, if (!asp) goto out_rt; asp_created = true; - osmo_ss7_asp_peer_set_hosts(&asp->cfg.local, asp, &default_local_ip, 1); - osmo_ss7_asp_peer_set_hosts(&asp->cfg.remote, asp, &default_remote_ip, 1); + if (default_local_ip) + osmo_ss7_asp_peer_set_hosts(&asp->cfg.local, asp, &default_local_ip, 1); + if (default_remote_ip) + osmo_ss7_asp_peer_set_hosts(&asp->cfg.remote, asp, &default_remote_ip, 1); + /* Make sure proper defaults are applied if app didn't provide specific default values */ + osmo_ss7_asp_set_default_peer_hosts(asp); asp->simple_client_allocated = true; } diff --git a/src/ss7_internal.h b/src/ss7_internal.h new file mode 100644 index 0000000..28e239c --- /dev/null +++ b/src/ss7_internal.h @@ -0,0 +1,9 @@ +#pragma once + +/* Internal header used by libosmo-sccp, not available publicly for lib users */ + +#include +#include + +bool osmo_ss7_asp_set_default_peer_hosts(struct osmo_ss7_asp *asp); +bool osmo_ss7_xua_server_set_default_local_hosts(struct osmo_xua_server *oxs); -- cgit v1.2.3