aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2023-09-08 13:02:14 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2023-09-08 13:49:08 +0200
commit658c509061163799e3ec67a5fac9dd4ea8234c76 (patch)
tree3525fafd9f4b4c6a704e09f2750cd77b07f3af6e
parentgsm_12_21.h: add flags for NM_ATT_IPACC_SUPP_FEATURES (diff)
downloadlibosmocore-658c509061163799e3ec67a5fac9dd4ea8234c76.tar.xz
libosmocore-658c509061163799e3ec67a5fac9dd4ea8234c76.zip
socket: Remove OSMO_SOCK_F_SCTP_ASCONF_SUPPORTED, add osmo_sock_init2_multiaddr2()
The OSMO_SOCK_F_SCTP_ASCONF_SUPPORTED flag was added recently to enable use of ASCONF in osmo_sock_inti2_multiaddr. Since we didn't release yet, we are still in time to get rid of this flag. It turns out that we'll want to add more features which must be set before SCTP INIT (connect()) time, like setsockopt SCTP_INITMSG, which in turn contains a struct with several parameters. Hence, adding flags for all those makes no sense. Instead, add a new API which allows passing an extensible struct which allows much more fine-grained setup from the caller. The new struct "pars" parameter is non-const on purpose, in order to be able to extend the struct in the future if we wish to get/obtain some data from the socket. Related: SYS#6501 Related: SYS#6558 Change-Id: I1f6fd09a79b0a2bd794e5669d933be25bbf1eeaa
-rw-r--r--TODO-RELEASE3
-rw-r--r--include/osmocom/core/socket.h29
-rw-r--r--src/core/libosmocore.map1
-rw-r--r--src/core/socket.c59
4 files changed, 79 insertions, 13 deletions
diff --git a/TODO-RELEASE b/TODO-RELEASE
index f78104e8..2d9e32ee 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -17,4 +17,5 @@ libosmogsm ADD new osmo_sub_auth_data2 / osmo_auth_gen_vec2 / osmo_auth_gen_vec_
libosmogsm MODIFY osmo_auth_impl callback function signature change. No known external users
libosmogsm ADD osmo_auth_c2
libosmogsm ADD OSMO_AUTH_ALG_TUAK
-libosmogsm ADD new API msgb_tv32_push() \ No newline at end of file
+libosmogsm ADD new API msgb_tv32_push()
+libosmocore ADD osmo_sock_init2_multiaddr2() \ No newline at end of file
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index c68bb6f0..ba986f84 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -14,6 +14,8 @@
#include <arpa/inet.h>
+#include <osmocom/core/defs.h>
+
/*! maximum length of a socket name ("r=1.2.3.4:123<->l=5.6.7.8:987") */
#define OSMO_SOCK_NAME_MAXLEN (2 + INET6_ADDRSTRLEN + 1 + 5 + 3 + 2 + INET6_ADDRSTRLEN + 1 + 5 + 1)
@@ -94,8 +96,6 @@ char *osmo_sockaddr_to_str_c(void *ctx, const struct osmo_sockaddr *sockaddr);
#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)
@@ -116,9 +116,32 @@ int osmo_sock_init2(uint16_t family, uint16_t type, uint8_t proto,
const char *local_host, uint16_t local_port,
const char *remote_host, uint16_t remote_port, unsigned int flags);
+struct osmo_sock_init2_multiaddr_pars {
+ union {
+ struct {
+ uint8_t version; /* set to 0 */
+ struct {
+ bool set;
+ bool abort_on_failure;
+ uint32_t value;
+ } sockopt_auth_supported;
+ struct {
+ bool set;
+ bool abort_on_failure;
+ uint32_t value;
+ } sockopt_asconf_supported;
+ } sctp;
+ };
+};
int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
const char **local_hosts, size_t local_hosts_cnt, uint16_t local_port,
- const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port, unsigned int flags);
+ const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port, unsigned int flags)
+ OSMO_DEPRECATED_OUTSIDE("Use osmo_sock_init2_multiaddr2() instead");
+int osmo_sock_init2_multiaddr2(uint16_t family, uint16_t type, uint8_t proto,
+ const char **local_hosts, size_t local_hosts_cnt, uint16_t local_port,
+ const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port,
+ unsigned int flags, struct osmo_sock_init2_multiaddr_pars *pars);
+
int osmo_sock_init_osa(uint16_t type, uint8_t proto,
const struct osmo_sockaddr *local,
diff --git a/src/core/libosmocore.map b/src/core/libosmocore.map
index 99be86cb..c0e164b7 100644
--- a/src/core/libosmocore.map
+++ b/src/core/libosmocore.map
@@ -419,6 +419,7 @@ osmo_sock_get_remote_ip_port;
osmo_sock_init;
osmo_sock_init2;
osmo_sock_init2_multiaddr;
+osmo_sock_init2_multiaddr2;
osmo_sock_init2_ofd;
osmo_sock_init_ofd;
osmo_sock_init_osa;
diff --git a/src/core/socket.c b/src/core/socket.c
index 3c2ba501..65da2032 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -696,33 +696,33 @@ static int addrinfo_to_sockaddr(uint16_t family, const struct addrinfo **result,
return 0;
}
-static int setsockopt_sctp_auth_supported(int fd)
+static int setsockopt_sctp_auth_supported(int fd, uint32_t val)
{
#ifdef SCTP_AUTH_SUPPORTED
struct sctp_assoc_value assoc_val = {
.assoc_id = SCTP_FUTURE_ASSOC,
- .assoc_value = 1,
+ .assoc_value = val,
};
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;
+ return -ENOTSUP;
#endif
}
-static int setsockopt_sctp_asconf_supported(int fd)
+static int setsockopt_sctp_asconf_supported(int fd, uint32_t val)
{
#ifdef SCTP_ASCONF_SUPPORTED
struct sctp_assoc_value assoc_val = {
.assoc_id = SCTP_FUTURE_ASSOC,
- .assoc_value = 1,
+ .assoc_value = val,
};
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;
+ return -ENOTSUP;
#endif
}
@@ -750,6 +750,38 @@ int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
const char **local_hosts, size_t local_hosts_cnt, uint16_t local_port,
const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port,
unsigned int flags)
+{
+ return osmo_sock_init2_multiaddr2(family, type, proto, local_hosts, local_hosts_cnt, local_port,
+ remote_hosts, remote_hosts_cnt, remote_port, flags, NULL);
+}
+
+/*! 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
+ * \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
+ * \param[in] local_hosts array of char pointers (strings), each containing local host name or IP address in string form
+ * \param[in] local_hosts_cnt length of local_hosts (in items)
+ * \param[in] local_port local port number in host byte order
+ * \param[in] remote_host array of char pointers (strings), each containing remote host name or IP address in string form
+ * \param[in] remote_hosts_cnt length of remote_hosts (in items)
+ * \param[in] remote_port remote port number in host byte order
+ * \param[in] flags flags like \ref OSMO_SOCK_F_CONNECT
+ * \param[in] pars Extra parameters for multi-address specific protocols, such as SCTP. Can be NULL.
+ * \returns socket file descriptor on success; negative on error
+ *
+ * This function is similar to \ref osmo_sock_init2(), but can be passed an
+ * array of local or remote addresses for protocols supporting multiple
+ * addresses per socket, like SCTP (currently only one supported). This function
+ * should not be used by protocols not supporting this kind of features, but
+ * rather \ref osmo_sock_init2() should be used instead.
+ * See \ref osmo_sock_init2() for more information on flags and general behavior.
+ *
+ * pars: If "pars" parameter is passed to the function, sctp.version shall be set to 0.
+ */
+int osmo_sock_init2_multiaddr2(uint16_t family, uint16_t type, uint8_t proto,
+ const char **local_hosts, size_t local_hosts_cnt, uint16_t local_port,
+ const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port,
+ unsigned int flags, struct osmo_sock_init2_multiaddr_pars *pars)
{
struct addrinfo *res_loc[OSMO_SOCK_MAX_ADDRS], *res_rem[OSMO_SOCK_MAX_ADDRS];
@@ -769,6 +801,9 @@ int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
if (proto != IPPROTO_SCTP)
return -ENOTSUP;
+ if (pars && pars->sctp.version != 0)
+ return -EINVAL;
+
if ((flags & (OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT)) == 0) {
LOGP(DLGLOBAL, LOGL_ERROR, "invalid: you have to specify either "
"BIND or CONNECT flags\n");
@@ -841,26 +876,32 @@ int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
goto ret_close;
}
- if (flags & OSMO_SOCK_F_SCTP_ASCONF_SUPPORTED) {
+ if (pars && pars->sctp.sockopt_auth_supported.set) {
/* RFC 5061 4.2.7: ASCONF also requires AUTH feature. */
- rc = setsockopt_sctp_auth_supported(sfd);
+ rc = setsockopt_sctp_auth_supported(sfd, pars->sctp.sockopt_auth_supported.value);
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));
+ if (pars->sctp.sockopt_auth_supported.abort_on_failure)
+ goto ret_close;
/* do not fail, some features such as Peer Primary Address won't be available
* unless configured system-wide through sysctl */
}
+ }
- rc = setsockopt_sctp_asconf_supported(sfd);
+ if (pars && pars->sctp.sockopt_asconf_supported.set) {
+ rc = setsockopt_sctp_asconf_supported(sfd, pars->sctp.sockopt_asconf_supported.value);
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));
+ if (pars->sctp.sockopt_asconf_supported.abort_on_failure)
+ goto ret_close;
/* do not fail, some features such as Peer Primary Address won't be available
* unless configured system-wide through sysctl */
}