pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-sccp/+/34112 )
Change subject: asp: Monitor SCTP_PEER_ADDR_CHANGE events to re-apply configured Primary
Address
......................................................................
asp: Monitor SCTP_PEER_ADDR_CHANGE events to re-apply configured Primary Address
The kernel doesn't store state about a "always-preferred" Primary
address, it simply applies the requested one at the time the request is
done. If afterwards the remote address becomes unavailable, the kernel
will end up giving up on it and selecting anoter one as primary address.
If the VTY-configured Primary Address become available after a while
(signaled by the kernel in the SCTP_PEER_ADDR_CHANGE), make sure to
apply it again.
Similary, if the peer sends us an ASCONF changing our Primary Address,
we should discard that and apply/overwrite *iff* the user explicitly
VTY-configured one (kernel announces the change through
SCTP_ADDR_MADE_PRIM in this scenario).
Related: OS#6076
Change-Id: I2e54e6f9e424350474db6dec6ab604b33a03f88b
---
M src/osmo_ss7.c
1 file changed, 106 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/12/34112/1
diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c
index 68b4559..fadab9e 100644
--- a/src/osmo_ss7.c
+++ b/src/osmo_ss7.c
@@ -1478,6 +1478,86 @@
return rc;
}
+static void asp_handle_sctp_notif_monitor_primary_address(const struct osmo_ss7_asp
*asp,
+ const union sctp_notification *notif)
+{
+ const char *primary_str;
+ int primary_str_type;
+ struct osmo_sockaddr ev_addr, primary;
+
+ if (asp->cfg.remote.idx_primary == -1)
+ return;
+ if (notif->sn_header.sn_type != SCTP_PEER_ADDR_CHANGE)
+ return;
+
+ primary_str = asp->cfg.remote.host[asp->cfg.remote.idx_primary];
+ primary_str_type = osmo_ip_str_type(primary_str);
+ memcpy(&ev_addr.u.sas, ¬if->sn_paddr_change.spc_aaddr,
sizeof(ev_addr.u.sas));
+
+ switch (notif->sn_paddr_change.spc_state) {
+ case SCTP_ADDR_AVAILABLE:
+ case SCTP_ADDR_ADDED:
+ case SCTP_ADDR_CONFIRMED:
+ /* If our primary addr is made available/added/confirmed, set it */
+ /* This whole switch is to properly compare addresses (take into account v6mapped IPv4
addresses): */
+ switch (ev_addr.u.sa.sa_family) {
+ case AF_INET:
+ switch (primary_str_type) {
+ case AF_INET:
+ primary = ev_addr; /* Copy AF + port */
+ inet_pton(AF_INET, primary_str, &primary.u.sin.sin_addr);
+ if (osmo_sockaddr_cmp(&primary, &ev_addr) == 0)
+ asp_apply_primary_address(asp);
+ case AF_INET6:
+ /* for sure not the same, nothing to do. */
+ return;
+ }
+ return;
+ case AF_INET6:
+ /* "ev_addr" can either be a IPv6 addr or a v6-mapped IPv4
+ * address. Compare both as IPv6 (or v6-mapped IPv4) addresses. */
+ primary = ev_addr; /* Copy AF + port */
+ inet_pton(AF_INET6, primary_str, &primary.u.sin6.sin6_addr);
+ if (osmo_sockaddr_cmp(&primary, &ev_addr) == 0)
+ asp_apply_primary_address(asp);
+ return;
+ default:
+ return;
+ }
+ break;
+ case SCTP_ADDR_MADE_PRIM:
+ /* If anoter primary addr is made primary, overwrite it by setting it again */
+ /* This whole switch is to properly compare addresses (take into account v6mapped IPv4
addresses): */
+ switch (ev_addr.u.sa.sa_family) {
+ case AF_INET:
+ switch (primary_str_type) {
+ case AF_INET:
+ primary = ev_addr; /* Copy AF + port */
+ inet_pton(AF_INET, primary_str, &primary.u.sin.sin_addr);
+ if (osmo_sockaddr_cmp(&primary, &ev_addr) != 0)
+ asp_apply_primary_address(asp);
+ case AF_INET6:
+ /* for sure not the same, apply primary address: */
+ asp_apply_primary_address(asp);
+ return;
+ }
+ return;
+ case AF_INET6:
+ /* "ev_addr" can either be a IPv6 addr or a v6-mapped IPv4
+ * address. Compare both as IPv6 (or v6-mapped IPv4) addresses. */
+ primary = ev_addr; /* Copy AF + port */
+ inet_pton(AF_INET6, primary_str, &primary.u.sin6.sin6_addr);
+ if (osmo_sockaddr_cmp(&primary, &ev_addr) != 0)
+ asp_apply_primary_address(asp);
+ return;
+ default:
+ return;
+ }
+ default:
+ break;
+ }
+}
+
static bool ipv6_sctp_supported(const char *host, bool bind)
{
int rc;
@@ -2001,6 +2081,7 @@
if (flags & OSMO_STREAM_SCTP_MSG_FLAGS_NOTIFICATION) {
union sctp_notification *notif = (union sctp_notification *) msgb_data(msg);
log_sctp_notification(asp, "xUA CLNT", notif);
+ asp_handle_sctp_notif_monitor_primary_address(asp, notif);
switch (notif->sn_header.sn_type) {
case SCTP_ASSOC_CHANGE:
@@ -2147,6 +2228,7 @@
if (flags & OSMO_STREAM_SCTP_MSG_FLAGS_NOTIFICATION) {
union sctp_notification *notif = (union sctp_notification *) msgb_data(msg);
log_sctp_notification(asp, "xUA CLNT", notif);
+ asp_handle_sctp_notif_monitor_primary_address(asp, notif);
switch (notif->sn_header.sn_type) {
case SCTP_ASSOC_CHANGE:
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-sccp/+/34112
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Change-Id: I2e54e6f9e424350474db6dec6ab604b33a03f88b
Gerrit-Change-Number: 34112
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: newchange