<p>lynxis lazus <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/19143">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, but someone else must approve
  pespin: Looks good to me, but someone else must approve
  lynxis lazus: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">socket: introduce osmo_sock_init_osa & osmo_sock_init_osa_ofd<br><br>osmo_sock_init_osa() takes osmo_sockaddr* as local and remote endpoints<br>to setup a socket.<br><br>Change-Id: I1eece543e3241ef0e095eb63bb831f7c15a16794<br>---<br>M include/osmocom/core/socket.h<br>M src/socket.c<br>M tests/socket/socket_test.c<br>M tests/socket/socket_test.err<br>M tests/socket/socket_test.ok<br>5 files changed, 310 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h</span><br><span>index e6a6bd5..4441449 100644</span><br><span>--- a/include/osmocom/core/socket.h</span><br><span>+++ b/include/osmocom/core/socket.h</span><br><span>@@ -58,6 +58,11 @@</span><br><span>                  const char **local_hosts, size_t local_hosts_cnt, uint16_t local_port,</span><br><span>               const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port, unsigned int flags);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sock_init_osa(uint16_t type, uint8_t proto,</span><br><span style="color: hsl(120, 100%, 40%);">+               const struct osmo_sockaddr *local,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const struct osmo_sockaddr *remote,</span><br><span style="color: hsl(120, 100%, 40%);">+                   unsigned int flags);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,</span><br><span>                   const char *host, uint16_t port, unsigned int flags);</span><br><span> </span><br><span>@@ -65,6 +70,11 @@</span><br><span>                       const char *local_host, uint16_t local_port,</span><br><span>                         const char *remote_host, uint16_t remote_port, unsigned int flags);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sock_init_osa_ofd(struct osmo_fd *ofd, int type, int proto,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const struct osmo_sockaddr *local,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const struct osmo_sockaddr *remote,</span><br><span style="color: hsl(120, 100%, 40%);">+                           unsigned int flags);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,</span><br><span>                     uint8_t proto, unsigned int flags);</span><br><span> </span><br><span>diff --git a/src/socket.c b/src/socket.c</span><br><span>index 56f01dc..6c06063 100644</span><br><span>--- a/src/socket.c</span><br><span>+++ b/src/socket.c</span><br><span>@@ -34,6 +34,7 @@</span><br><span> #include <osmocom/core/logging.h></span><br><span> #include <osmocom/core/select.h></span><br><span> #include <osmocom/core/socket.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/sockaddr_str.h></span><br><span> #include <osmocom/core/talloc.h></span><br><span> #include <osmocom/core/utils.h></span><br><span> </span><br><span>@@ -153,6 +154,28 @@</span><br><span>    return sfd;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int socket_helper_osa(const struct osmo_sockaddr *addr, uint16_t type, uint8_t proto, unsigned int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int sfd, on = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    sfd = socket(addr->u.sa.sa_family, type, proto);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (sfd == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGP(DLGLOBAL, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                    "unable to create socket: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+          return sfd;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (flags & OSMO_SOCK_F_NONBLOCK) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (ioctl(sfd, FIONBIO, (unsigned char *)&on) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   LOGP(DLGLOBAL, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                            "cannot set this socket unblocking: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                          strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                     close(sfd);</span><br><span style="color: hsl(120, 100%, 40%);">+                   sfd = -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     return sfd;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef HAVE_LIBSCTP</span><br><span> /* Fill buf with a string representation of the address set, in the form:</span><br><span>  * buf_len == 0: "()"</span><br><span>@@ -434,6 +457,135 @@</span><br><span>      return sfd;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define _SOCKADDR_TO_STR(dest, sockaddr) do { \</span><br><span style="color: hsl(120, 100%, 40%);">+         if (osmo_sockaddr_str_from_sockaddr(&dest, &sockaddr->u.sas)) \</span><br><span style="color: hsl(120, 100%, 40%);">+                    osmo_strlcpy(dest.ip, "Invalid IP", 11); \</span><br><span style="color: hsl(120, 100%, 40%);">+  } while (0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Initialize a socket (including bind and/or connect)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] local local address</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] remote remote address</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] flags flags like \ref OSMO_SOCK_F_CONNECT</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns socket file descriptor on success; negative on error</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function creates a new socket of the</span><br><span style="color: hsl(120, 100%, 40%);">+ * \a type and \a proto and optionally binds it to the \a local</span><br><span style="color: hsl(120, 100%, 40%);">+ * as well as optionally connects it to the \a remote</span><br><span style="color: hsl(120, 100%, 40%);">+ * depending on the value * of \a flags parameter.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * As opposed to \ref osmo_sock_init(), this function allows to combine</span><br><span style="color: hsl(120, 100%, 40%);">+ * the \ref OSMO_SOCK_F_BIND and \ref OSMO_SOCK_F_CONNECT flags.  This</span><br><span style="color: hsl(120, 100%, 40%);">+ * is useful if you want to connect to a remote host/port, but still</span><br><span style="color: hsl(120, 100%, 40%);">+ * want to bind that socket to either a specific local alias IP and/or a</span><br><span style="color: hsl(120, 100%, 40%);">+ * specific local source port.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You must specify either \ref OSMO_SOCK_F_BIND, or \ref</span><br><span style="color: hsl(120, 100%, 40%);">+ * OSMO_SOCK_F_CONNECT, or both.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * If \ref OSMO_SOCK_F_NONBLOCK is specified, the socket will be set to</span><br><span style="color: hsl(120, 100%, 40%);">+ * non-blocking mode.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sock_init_osa(uint16_t type, uint8_t proto,</span><br><span style="color: hsl(120, 100%, 40%);">+                   const struct osmo_sockaddr *local,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const struct osmo_sockaddr *remote,</span><br><span style="color: hsl(120, 100%, 40%);">+                   unsigned int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int sfd = -1, rc, on = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct osmo_sockaddr_str sastr = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if ((flags & (OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DLGLOBAL, LOGL_ERROR, "invalid: you have to specify either "</span><br><span style="color: hsl(120, 100%, 40%);">+                   "BIND or CONNECT flags\n");</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((flags & OSMO_SOCK_F_BIND) && !local) {</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGP(DLGLOBAL, LOGL_ERROR, "invalid argument. Cannot BIND when local is NULL\n");</span><br><span style="color: hsl(120, 100%, 40%);">+           return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((flags & OSMO_SOCK_F_CONNECT) && !remote) {</span><br><span style="color: hsl(120, 100%, 40%);">+           LOGP(DLGLOBAL, LOGL_ERROR, "invalid argument. Cannot CONNECT when remote is NULL\n");</span><br><span style="color: hsl(120, 100%, 40%);">+               return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((flags & OSMO_SOCK_F_BIND) &&</span><br><span style="color: hsl(120, 100%, 40%);">+     (flags & OSMO_SOCK_F_CONNECT) &&</span><br><span style="color: hsl(120, 100%, 40%);">+          local->u.sa.sa_family != remote->u.sa.sa_family) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGP(DLGLOBAL, LOGL_ERROR, "invalid: the family for "</span><br><span style="color: hsl(120, 100%, 40%);">+                    "local and remote endpoint must be same.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* figure out local side of socket */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (flags & OSMO_SOCK_F_BIND) {</span><br><span style="color: hsl(120, 100%, 40%);">+           sfd = socket_helper_osa(local, type, proto, flags);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (sfd < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     _SOCKADDR_TO_STR(sastr, local);</span><br><span style="color: hsl(120, 100%, 40%);">+                       LOGP(DLGLOBAL, LOGL_ERROR, "no suitable local addr found for: %s:%u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                             sastr.ip, sastr.port);</span><br><span style="color: hsl(120, 100%, 40%);">+                        return -ENODEV;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (proto != IPPROTO_UDP || (flags & OSMO_SOCK_F_UDP_REUSEADDR)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR,</span><br><span style="color: hsl(120, 100%, 40%);">+                                        &on, sizeof(on));</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              _SOCKADDR_TO_STR(sastr, local);</span><br><span style="color: hsl(120, 100%, 40%);">+                               LOGP(DLGLOBAL, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 "cannot setsockopt socket:"</span><br><span style="color: hsl(120, 100%, 40%);">+                                 " %s:%u: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                     sastr.ip, sastr.port,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                                close(sfd);</span><br><span style="color: hsl(120, 100%, 40%);">+                           return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (bind(sfd, &local->u.sa, sizeof(struct osmo_sockaddr)) == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     _SOCKADDR_TO_STR(sastr, local);</span><br><span style="color: hsl(120, 100%, 40%);">+                       LOGP(DLGLOBAL, LOGL_ERROR, "unable to bind socket: %s:%u: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                         sastr.ip, sastr.port, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                  close(sfd);</span><br><span style="color: hsl(120, 100%, 40%);">+                   return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Reached this point, if OSMO_SOCK_F_BIND then sfd is valid (>=0) or it</span><br><span style="color: hsl(120, 100%, 40%);">+      was already closed and func returned. If OSMO_SOCK_F_BIND is not</span><br><span style="color: hsl(120, 100%, 40%);">+      set, then sfd = -1 */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* figure out remote side of socket */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (flags & OSMO_SOCK_F_CONNECT) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (sfd < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     sfd = socket_helper_osa(remote, type, proto, flags);</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (sfd < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             return sfd;</span><br><span style="color: hsl(120, 100%, 40%);">+                   }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           rc = connect(sfd, &remote->u.sa, sizeof(struct osmo_sockaddr));</span><br><span style="color: hsl(120, 100%, 40%);">+                if (rc != 0 && errno != EINPROGRESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        _SOCKADDR_TO_STR(sastr, remote);</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOGP(DLGLOBAL, LOGL_ERROR, "unable to connect socket: %s:%u: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                      sastr.ip, sastr.port, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+                  close(sfd);</span><br><span style="color: hsl(120, 100%, 40%);">+                   return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   rc = osmo_sock_init_tail(sfd, type, flags);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              close(sfd);</span><br><span style="color: hsl(120, 100%, 40%);">+           sfd = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return sfd;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef HAVE_LIBSCTP</span><br><span> </span><br><span> /* Check whether there's an IPv6 Addr as first option of any addrinfo item in the addrinfo set */</span><br><span>@@ -860,6 +1012,13 @@</span><br><span>                                         local_port, remote_host, remote_port, flags));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sock_init_osa_ofd(struct osmo_fd *ofd, int type, int proto,</span><br><span style="color: hsl(120, 100%, 40%);">+                 const struct osmo_sockaddr *local,</span><br><span style="color: hsl(120, 100%, 40%);">+                    const struct osmo_sockaddr *remote, unsigned int flags)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    return osmo_fd_init_ofd(ofd, osmo_sock_init_osa(type, proto, local, remote, flags));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Initialize a socket and fill \ref sockaddr</span><br><span>  *  \param[out] ss socket address (will be filled in)</span><br><span>  *  \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM</span><br><span>diff --git a/tests/socket/socket_test.c b/tests/socket/socket_test.c</span><br><span>index 64e48bc..671177f 100644</span><br><span>--- a/tests/socket/socket_test.c</span><br><span>+++ b/tests/socket/socket_test.c</span><br><span>@@ -186,6 +186,133 @@</span><br><span>    return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int test_sockinit_osa(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int fd, rc;</span><br><span style="color: hsl(120, 100%, 40%);">+   char *name;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_sockaddr localhost4 = {};</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_sockaddr localhost6 = {};</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_sockaddr localhost4_noport = {};</span><br><span style="color: hsl(120, 100%, 40%);">+  struct osmo_sockaddr localhost6_noport = {};</span><br><span style="color: hsl(120, 100%, 40%);">+  struct osmo_sockaddr any4 = {};</span><br><span style="color: hsl(120, 100%, 40%);">+       struct osmo_sockaddr any6 = {};</span><br><span style="color: hsl(120, 100%, 40%);">+       struct osmo_sockaddr invalid = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  localhost4.u.sin = (struct sockaddr_in){</span><br><span style="color: hsl(120, 100%, 40%);">+              .sin_family = AF_INET,</span><br><span style="color: hsl(120, 100%, 40%);">+                .sin_addr.s_addr = inet_addr("127.0.0.1"),</span><br><span style="color: hsl(120, 100%, 40%);">+          .sin_port = htons(42),</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  localhost6.u.sin6 = (struct sockaddr_in6){</span><br><span style="color: hsl(120, 100%, 40%);">+            .sin6_family = AF_INET6,</span><br><span style="color: hsl(120, 100%, 40%);">+              .sin6_port = htons(42),</span><br><span style="color: hsl(120, 100%, 40%);">+       };</span><br><span style="color: hsl(120, 100%, 40%);">+    inet_pton(AF_INET6, "::1", &localhost6.u.sin6.sin6_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     localhost4_noport = localhost4;</span><br><span style="color: hsl(120, 100%, 40%);">+       localhost4_noport.u.sin.sin_port = htons(0);</span><br><span style="color: hsl(120, 100%, 40%);">+  localhost6_noport = localhost6;</span><br><span style="color: hsl(120, 100%, 40%);">+       localhost6_noport.u.sin6.sin6_port = htons(0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      any4.u.sin = (struct sockaddr_in){</span><br><span style="color: hsl(120, 100%, 40%);">+            .sin_family = AF_INET,</span><br><span style="color: hsl(120, 100%, 40%);">+                .sin_addr.s_addr = inet_addr("0.0.0.0"),</span><br><span style="color: hsl(120, 100%, 40%);">+            .sin_port = htons(0),</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+    any6.u.sin6 = (struct sockaddr_in6){</span><br><span style="color: hsl(120, 100%, 40%);">+          .sin6_family = AF_INET6,</span><br><span style="color: hsl(120, 100%, 40%);">+              .sin6_port = htons(0),</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+    inet_pton(AF_INET6, "::", &any6.u.sin6.sin6_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    invalid.u.sa.sa_family = AF_UNSPEC;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("Checking osmo_sock_init_osa() with bind to a random local UDP port\n");</span><br><span style="color: hsl(120, 100%, 40%);">+     fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP,</span><br><span style="color: hsl(120, 100%, 40%);">+                          &any4, NULL, OSMO_SOCK_F_BIND);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(fd >= 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      name = osmo_sock_get_name(ctx, fd);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* expect it to be not connected. We cannot match on INADDR_ANY,</span><br><span style="color: hsl(120, 100%, 40%);">+       * as apparently that won't work on FreeBSD if there's only one</span><br><span style="color: hsl(120, 100%, 40%);">+        * address (e.g. 137.0.0.1) assigned to the entire system, like</span><br><span style="color: hsl(120, 100%, 40%);">+        * the Osmocom FreeBSD build slaves */</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(!strncmp(name, "(r=NULL<->", 9));</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(name);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* expect it to be blocking */</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = fcntl(fd, F_GETFL);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(!(rc & O_NONBLOCK));</span><br><span style="color: hsl(120, 100%, 40%);">+  close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("Checking osmo_sock_init_osa() IPv4 for OSMO_SOCK_F_NONBLOCK\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP,</span><br><span style="color: hsl(120, 100%, 40%);">+                          &any4, NULL, OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(fd >= 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* expect it to be blocking */</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = fcntl(fd, F_GETFL);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(rc & O_NONBLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+     close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("Checking osmo_sock_init_osa() IPv6 for OSMO_SOCK_F_NONBLOCK\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP,</span><br><span style="color: hsl(120, 100%, 40%);">+                          &any6, NULL, OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(fd >= 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* expect it to be blocking */</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = fcntl(fd, F_GETFL);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(rc & O_NONBLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+     close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("Checking osmo_sock_init_osa() for invalid flags\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP, &any4,  NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(fd < 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("Checking osmo_sock_init_osa() for combined BIND + CONNECT on IPv4\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP, &localhost4_noport, &localhost4,</span><br><span style="color: hsl(120, 100%, 40%);">+                          OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(fd >= 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      name = osmo_sock_get_name(ctx, fd);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __FreeBSD__</span><br><span style="color: hsl(120, 100%, 40%);">+      /* For some reason, on the jenkins.osmocom.org build slave with</span><br><span style="color: hsl(120, 100%, 40%);">+        * FreeBSD 10 inside a jail, it fails.  Works fine on laforge's</span><br><span style="color: hsl(120, 100%, 40%);">+    * FreeBSD 10 or 11 VM at home */</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(!strncmp(name, "(r=127.0.0.1:42<->l=127.0.0.1", 29));</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+     close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("Checking osmo_sock_init_osa() for combined BIND + CONNECT on IPv6\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP, &localhost6_noport, &localhost6,</span><br><span style="color: hsl(120, 100%, 40%);">+                          OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(fd >= 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      name = osmo_sock_get_name(ctx, fd);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef __FreeBSD__</span><br><span style="color: hsl(120, 100%, 40%);">+      /* For some reason, on the jenkins.osmocom.org build slave with</span><br><span style="color: hsl(120, 100%, 40%);">+        * FreeBSD 10 inside a jail, it fails.  Works fine on laforge's</span><br><span style="color: hsl(120, 100%, 40%);">+    * FreeBSD 10 or 11 VM at home */</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(!strncmp(name, "(r=::1:42<->l=::1", 17));</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+ close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("Checking osmo_sock_init_osa() must fail on mixed IPv4 & IPv6\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP, &localhost4_noport, &localhost6,</span><br><span style="color: hsl(120, 100%, 40%);">+                          OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(fd < 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("Checking osmo_sock_init_osa() must fail on mixed IPv6 & IPv4\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP, &localhost6_noport, &localhost4,</span><br><span style="color: hsl(120, 100%, 40%);">+                          OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(fd < 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("Checking osmo_sock_init_osa() must fail on invalid osmo_sockaddr\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       fd = osmo_sock_init_osa(SOCK_DGRAM, IPPROTO_UDP, &invalid, &localhost4,</span><br><span style="color: hsl(120, 100%, 40%);">+                            OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(fd < 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     talloc_free(name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> const struct log_info_cat default_categories[] = {</span><br><span> };</span><br><span> </span><br><span>@@ -204,6 +331,7 @@</span><br><span>         test_sockinit();</span><br><span>     test_sockinit2();</span><br><span>    test_get_ip_and_port();</span><br><span style="color: hsl(120, 100%, 40%);">+       test_sockinit_osa();</span><br><span> </span><br><span>     return EXIT_SUCCESS;</span><br><span> }</span><br><span>diff --git a/tests/socket/socket_test.err b/tests/socket/socket_test.err</span><br><span>index 0f0f8da..3c198ac 100644</span><br><span>--- a/tests/socket/socket_test.err</span><br><span>+++ b/tests/socket/socket_test.err</span><br><span>@@ -2,3 +2,7 @@</span><br><span> invalid: you have to specify either BIND or CONNECT flags</span><br><span> Unable to find a common protocol (IPv4 or IPv6) for local host: 127.0.0.1 and remote host: ::1.</span><br><span> Unable to find a common protocol (IPv4 or IPv6) for local host: ::1 and remote host: 127.0.0.1.</span><br><span style="color: hsl(120, 100%, 40%);">+invalid: you have to specify either BIND or CONNECT flags</span><br><span style="color: hsl(120, 100%, 40%);">+invalid: the family for local and remote endpoint must be same.</span><br><span style="color: hsl(120, 100%, 40%);">+invalid: the family for local and remote endpoint must be same.</span><br><span style="color: hsl(120, 100%, 40%);">+invalid: the family for local and remote endpoint must be same.</span><br><span>diff --git a/tests/socket/socket_test.ok b/tests/socket/socket_test.ok</span><br><span>index 589036f..9a52d44 100644</span><br><span>--- a/tests/socket/socket_test.ok</span><br><span>+++ b/tests/socket/socket_test.ok</span><br><span>@@ -12,3 +12,12 @@</span><br><span> Checking osmo_sock_init2(AF_UNSPEC) BIND on IPv4</span><br><span> Checking test_get_ip_and_port() for combined BIND + CONNECT on IPv4</span><br><span> Checking test_get_ip_and_port() for combined BIND + CONNECT on IPv6</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() with bind to a random local UDP port</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() IPv4 for OSMO_SOCK_F_NONBLOCK</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() IPv6 for OSMO_SOCK_F_NONBLOCK</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() for invalid flags</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() for combined BIND + CONNECT on IPv4</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() for combined BIND + CONNECT on IPv6</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() must fail on mixed IPv4 & IPv6</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() must fail on mixed IPv6 & IPv4</span><br><span style="color: hsl(120, 100%, 40%);">+Checking osmo_sock_init_osa() must fail on invalid osmo_sockaddr</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/19143">change 19143</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/19143"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I1eece543e3241ef0e095eb63bb831f7c15a16794 </div>
<div style="display:none"> Gerrit-Change-Number: 19143 </div>
<div style="display:none"> Gerrit-PatchSet: 20 </div>
<div style="display:none"> Gerrit-Owner: lynxis lazus <lynxis@fe80.eu> </div>
<div style="display:none"> Gerrit-Assignee: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: lynxis lazus <lynxis@fe80.eu> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-CC: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>