pespin has submitted this change. ( 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.
Kernel support for those is relatively new:
SCTP_FUTURE_ASSOC added in: 80df2704a375bb4b3c9c5cce9c00052361b16d61
Follows: v5.0-rc4
Precedes: v5.1-rc1
SCTP_ASCONF_SUPPORTED added in: df2c71ffdfae58961981d7cbcccea93688fc4e96
Follows: v5.3-rc5
Precedes: v5.4-rc1
SCTP_AUTH_SUPPORTED added in: 56dd525abd56f7acd7b44a52935726e3ada4916c
Follows: v5.3-rc5
Precedes: v5.4-rc1
Related: OS#6076
Change-Id: Iac07031927b66a9d32d2bb2faab817e4c922a359
---
M include/osmocom/core/socket.h
M src/core/socket.c
2 files changed, 101 insertions(+), 0 deletions(-)
Approvals:
pespin: Looks good to me, approved
Jenkins Builder: Verified
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..02d05e2 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -696,6 +696,36 @@
return 0;
}
+static int setsockopt_sctp_auth_supported(int fd)
+{
+#ifdef SCTP_AUTH_SUPPORTED
+ struct sctp_assoc_value assoc_val = {
+ .assoc_id = SCTP_FUTURE_ASSOC,
+ .assoc_value = 1,
+ };
+ return setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_SUPPORTED, &assoc_val, sizeof(assoc_val));
+#else
+#pragma message "setsockopt(SCTP_AUTH_SUPPORTED) not supported! some SCTP features may not be available!"
+ LOGP(DLGLOBAL, LOGL_NOTICE, "Built without support for setsockopt(SCTP_AUTH_SUPPORTED), skipping\n");
+ return 0;
+#endif
+}
+
+static int setsockopt_sctp_asconf_supported(int fd)
+{
+#ifdef SCTP_ASCONF_SUPPORTED
+ struct sctp_assoc_value assoc_val = {
+ .assoc_id = SCTP_FUTURE_ASSOC,
+ .assoc_value = 1,
+ };
+ return setsockopt(fd, IPPROTO_SCTP, SCTP_ASCONF_SUPPORTED, &assoc_val, sizeof(assoc_val));
+#else
+#pragma message "setsockopt(SCTP_ASCONF_SUPPORTED) not supported! some SCTP features may not be available!"
+ LOGP(DLGLOBAL, LOGL_NOTICE, "Built without support for setsockopt(SCTP_ASCONF_SUPPORTED), skipping\n");
+ return 0;
+#endif
+}
+
/*! Initialize a socket (including bind and/or connect) with multiple local or remote addresses.
* \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
@@ -811,6 +841,29 @@
goto ret_close;
}
+ if (flags & OSMO_SOCK_F_SCTP_ASCONF_SUPPORTED) {
+ /* RFC 5061 4.2.7: ASCONF also requires AUTH feature. */
+ rc = setsockopt_sctp_auth_supported(sfd);
+ 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_sctp_asconf_supported(sfd);
+ 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 .*/
--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/34113
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Iac07031927b66a9d32d2bb2faab817e4c922a359
Gerrit-Change-Number: 34113
Gerrit-PatchSet: 3
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged
pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-netif/+/34080 )
Change subject: stream_cli: Forward SCTP MSG_NOTIFICATION to upper layers
......................................................................
stream_cli: Forward SCTP MSG_NOTIFICATION to upper layers
Same mechanism as already used in stream_srv.
Change-Id: I4cb94d264109f1b763cccd44c6ba049cc7509319
---
M src/stream_cli.c
1 file changed, 52 insertions(+), 2 deletions(-)
Approvals:
Jenkins Builder: Verified
pespin: Looks good to me, approved
diff --git a/src/stream_cli.c b/src/stream_cli.c
index 778ac43..1ee0ba5 100644
--- a/src/stream_cli.c
+++ b/src/stream_cli.c
@@ -916,15 +916,54 @@
/*! \brief Receive data via an Osmocom stream client
* \param[in] cli Stream Client through which we want to send
* \param msg pre-allocate message buffer to which received data is appended
- * \returns number of bytes read; <=0 in case of error */
+ * \returns number of bytes read; <=0 in case of error
+ *
+ * If conn is an SCTP connection, additional specific considerations shall be taken:
+ * - msg->cb is always filled with SCTP ppid, and SCTP stream values, see msgb_sctp_*() APIs.
+ * - If an SCTP notification was received when reading from the SCTP socket,
+ * msgb_sctp_msg_flags(msg) will contain bit flag
+ * OSMO_STREAM_SCTP_MSG_FLAGS_NOTIFICATION set, and the msgb will
+ * contain a "union sctp_notification" instead of user data. In this case the
+ * return code will be either 0 (if conn is considered dead after the
+ * notification) or -EAGAIN (if conn is considered still alive after the
+ * notification) resembling the standard recv() API.
+ */
int osmo_stream_cli_recv(struct osmo_stream_cli *cli, struct msgb *msg)
{
int ret;
OSMO_ASSERT(cli);
OSMO_ASSERT(msg);
- ret = recv(cli->ofd.fd, msg->tail, msgb_tailroom(msg), 0);
+ switch (cli->sk_domain) {
+ case AF_UNIX:
+ ret = recv(cli->ofd.fd, msg->tail, msgb_tailroom(msg), 0);
+ break;
+ case AF_INET:
+ case AF_INET6:
+ case AF_UNSPEC:
+ switch (cli->proto) {
+#ifdef HAVE_LIBSCTP
+ case IPPROTO_SCTP:
+ {
+ char log_pfx[128];
+ snprintf(log_pfx, sizeof(log_pfx), "CLICONN(%s,%s)", cli->name ? : "", cli->sockname);
+ ret = stream_sctp_recvmsg_wrapper(cli->ofd.fd, msg, log_pfx);
+ break;
+ }
+#endif
+ case IPPROTO_TCP:
+ default:
+ ret = recv(cli->ofd.fd, msg->tail, msgb_tailroom(msg), 0);
+ break;
+ }
+ break;
+ default:
+ ret = -ENOTSUP;
+ }
+
if (ret < 0) {
+ if (ret == -EAGAIN)
+ return ret;
if (errno == EPIPE || errno == ECONNRESET)
LOGSCLI(cli, LOGL_ERROR, "lost connection with srv\n");
osmo_stream_cli_reconnect(cli);
--
To view, visit https://gerrit.osmocom.org/c/libosmo-netif/+/34080
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-netif
Gerrit-Branch: master
Gerrit-Change-Id: I4cb94d264109f1b763cccd44c6ba049cc7509319
Gerrit-Change-Number: 34080
Gerrit-PatchSet: 6
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged
Attention is currently required from: pespin.
Hello osmith, Jenkins Builder, laforge,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/libosmo-netif/+/34080
to look at the new patch set (#6).
Change subject: stream_cli: Forward SCTP MSG_NOTIFICATION to upper layers
......................................................................
stream_cli: Forward SCTP MSG_NOTIFICATION to upper layers
Same mechanism as already used in stream_srv.
Change-Id: I4cb94d264109f1b763cccd44c6ba049cc7509319
---
M src/stream_cli.c
1 file changed, 52 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-netif refs/changes/80/34080/6
--
To view, visit https://gerrit.osmocom.org/c/libosmo-netif/+/34080
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-netif
Gerrit-Branch: master
Gerrit-Change-Id: I4cb94d264109f1b763cccd44c6ba049cc7509319
Gerrit-Change-Number: 34080
Gerrit-PatchSet: 6
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: newpatchset