pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/34113 )
Change subject: socket: Add osmo_sock_init flag to enable SCTP ASCONF features ......................................................................
socket: Add osmo_sock_init flag to enable SCTP ASCONF features
The SCTP_ASCONF_SUPPORTED sockopt, which enables ASCONF features for the SCTP associations managed by the SCTP socket, gets its default value from to sysctl "net.sctp.addip_enable", which, at least up to current kernel 6.4.8 is set to "0" (disabled) by default. As a result, ASCONF related features such as setsockopt(SCTP_SET_PEER_PRIMARY_ADDR) fail with -EPERM since ASNCONF extensions where not negotiated during the SCTP init handshake. This commit adds support for setting SCTP_ASCONF_SUPPORTED=1 during socket creation, since that needs to be applied before the first bind()/connect() (before first assoc is created).
Furthermore, for ASCONF features to work properly, the assoc also needs to announce/use the AUTH extension, as per RFC5061 section 4.2.7. Otherwise, the peer receiving an SCTP INIT with ExtensionFeatures=ASCONF,ASCONF_ACK but without AUTH, will reject the assoc with an ABORT since it's not complying with spec (this behavior can be tweaked through sysctl "net.sctp.addip_noauth_enable").
The AUTH extension is enabled through sockopt SCTP_AUTH_SUPPORTED, and its default value is that of sysctl "net.sctp.auth_enable", which is also disabled (0) by default.
Related: OS#6076 Change-Id: Iac07031927b66a9d32d2bb2faab817e4c922a359 --- M include/osmocom/core/socket.h M src/core/socket.c 2 files changed, 63 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/13/34113/1
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h index 6bac87d..c68bb6f 100644 --- a/include/osmocom/core/socket.h +++ b/include/osmocom/core/socket.h @@ -94,6 +94,8 @@ #define OSMO_SOCK_F_NO_MCAST_ALL (1 << 4) /*! use SO_REUSEADDR on UDP ports (required for multicast) */ #define OSMO_SOCK_F_UDP_REUSEADDR (1 << 5) +/*! use SCTP_AUTH_SUPPORTED + SCTP_ASCONF_SUPPORTED on SCTP socket (required for ASCONF / Peer Primary Address feature) */ +#define OSMO_SOCK_F_SCTP_ASCONF_SUPPORTED (1 << 6)
/*! use OSMO_SOCK_F_DSCP(x) to set IP DSCP 'x' for packets transmitted on the socket */ #define OSMO_SOCK_F_DSCP(x) (((x)&0x3f) << 24) diff --git a/src/core/socket.c b/src/core/socket.c index 5a31c8f..66f903e 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -811,6 +811,34 @@ goto ret_close; }
+ if (flags & OSMO_SOCK_F_SCTP_ASCONF_SUPPORTED) { + struct sctp_assoc_value assoc_val = { + .assoc_id = SCTP_FUTURE_ASSOC, + .assoc_value = 1, + }; + /* RFC 5061 4.2.7: ASCONF also requires AUTH feature. */ + rc = setsockopt(sfd, IPPROTO_SCTP, SCTP_AUTH_SUPPORTED, + &assoc_val, sizeof(assoc_val)); + if (rc < 0) { + int err = errno; + multiaddr_snprintf(strbuf, sizeof(strbuf), local_hosts, local_hosts_cnt); + LOGP(DLGLOBAL, LOGL_ERROR, + "cannot setsockopt(SCTP_AUTH_SUPPORTED) socket: %s:%u: %s\n", + strbuf, local_port, strerror(err)); + goto ret_close; + } + rc = setsockopt(sfd, IPPROTO_SCTP, SCTP_ASCONF_SUPPORTED, + &assoc_val, sizeof(assoc_val)); + if (rc < 0) { + int err = errno; + multiaddr_snprintf(strbuf, sizeof(strbuf), local_hosts, local_hosts_cnt); + LOGP(DLGLOBAL, LOGL_ERROR, + "cannot setsockopt(SCTP_ASCONF_SUPPORTED) socket: %s:%u: %s\n", + strbuf, local_port, strerror(err)); + goto ret_close; + } + } + /* Build array of addresses taking first entry for each host. TODO: Ideally we should use backtracking storing last used indexes and trying next combination if connect() fails .*/