pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/34346?usp=email )
Change subject: socket: Support setsokopt SCTP_INITMSG in osmo_sock_init2_multiaddr2() ......................................................................
socket: Support setsokopt SCTP_INITMSG in osmo_sock_init2_multiaddr2()
This allows setting several socket paramets which can only be set before SCTP INIT phase (connect()).
Since no release with osmo_sock_init2_multiaddr2() happened yet, we are allowed to extend struct osmo_sock_init2_multiaddr_pars without bumping the version field.
Related: SYS#6558 Change-Id: Ibc55932d954279927d1e70ccce1e8bf32b180d44 --- M include/osmocom/core/socket.h M src/core/socket.c 2 files changed, 83 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/46/34346/1
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h index ba986f8..bbf828f 100644 --- a/include/osmocom/core/socket.h +++ b/include/osmocom/core/socket.h @@ -130,6 +130,18 @@ bool abort_on_failure; uint32_t value; } sockopt_asconf_supported; + struct { + bool set; + bool abort_on_failure; + bool num_ostreams_present; + bool max_instreams_present; + bool max_attempts_present; + bool max_init_timeo_present; + uint16_t num_ostreams_value; + uint16_t max_instreams_value; + uint16_t max_attempts_value; + uint16_t max_init_timeo_value; + } sockopt_initmsg; } sctp; }; }; diff --git a/src/core/socket.c b/src/core/socket.c index a4c3a35..993a4fc 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -726,6 +726,46 @@ #endif }
+static int setsockopt_sctp_initmsg(int fd, const struct osmo_sock_init2_multiaddr_pars *pars) +{ + if (!pars->sctp.sockopt_initmsg.num_ostreams_present && + !pars->sctp.sockopt_initmsg.max_instreams_present && + !pars->sctp.sockopt_initmsg.max_attempts_present && + !pars->sctp.sockopt_initmsg.max_init_timeo_present) + return 0; /* nothing to set/do */ + +#ifdef SCTP_INITMSG + struct sctp_initmsg si = {0}; + socklen_t si_len = sizeof(si); + int rc; + + /* If at least one field not present, obtain current value from kernel: */ + if (!pars->sctp.sockopt_initmsg.num_ostreams_present || + !pars->sctp.sockopt_initmsg.max_instreams_present || + !pars->sctp.sockopt_initmsg.max_attempts_present || + !pars->sctp.sockopt_initmsg.max_init_timeo_present) { + rc = getsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &si, &si_len); + if (rc < 0) + return rc; + } + + if (pars->sctp.sockopt_initmsg.num_ostreams_present) + si.sinit_num_ostreams = pars->sctp.sockopt_initmsg.num_ostreams_value; + if (pars->sctp.sockopt_initmsg.max_instreams_present) + si.sinit_max_instreams = pars->sctp.sockopt_initmsg.max_instreams_value; + if (pars->sctp.sockopt_initmsg.max_attempts_present) + si.sinit_max_attempts = pars->sctp.sockopt_initmsg.max_attempts_value; + if (pars->sctp.sockopt_initmsg.max_init_timeo_present) + si.sinit_max_init_timeo = pars->sctp.sockopt_initmsg.max_init_timeo_value; + + return setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &si, sizeof(si)); +#else +#pragma message "setsockopt(SCTP_INITMSG) not supported! some SCTP features may not be available!" + LOGP(DLGLOBAL, LOGL_NOTICE, "Built without support for setsockopt(SCTP_INITMSG), skipping\n"); + return -ENOTSUP +#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 @@ -905,6 +945,20 @@ } }
+ if (pars && pars->sctp.sockopt_initmsg.set) { + rc = setsockopt_sctp_initmsg(sfd, pars); + if (rc < 0) { + int err = errno; + multiaddr_snprintf(strbuf, sizeof(strbuf), local_hosts, local_hosts_cnt); + LOGP(DLGLOBAL, LOGL_ERROR, + "cannot setsockopt(SCTP_INITMSG) socket: %s:%u: %s\n", + strbuf, local_port, strerror(err)); + if (pars->sctp.sockopt_initmsg.abort_on_failure) + goto ret_close; + /* do not fail, some parameters will be left as the global default */ + } + } + /* 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 .*/