<p>Neels Hofmeyr has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13123">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add osmo_ip_port API<br><br>For handling RTP IP addresses and ports, osmo-mgw, osmo-bsc and osmo-msc so far<br>have their own separate shims and code duplication around inet_ntoa(), htons(),<br>sockaddr conversions etc. Unify and standardize with this common API.<br><br>In the MGW endpoint FSM that was introduced in osmo-bsc and which I would like<br>to re-use for osmo-msc (upcoming patch moving that to osmo-mgw), it has turned<br>out that using char* IP address and uint16_t port number types are a convenient<br>common denominator for logging, MGCP message composition and GSM48. Ongoing<br>osmo-msc work also uses this for MNCC.<br><br>This is of course potentially useful for any other IP+port combinations besides<br>RTP stream handling.<br><br>Needless to say that most current implementations will probably stay with their<br>current own conversion code for a long time; for current osmo-{bsc,msc,mgw}<br>work (MGW endpoint FSM) though, I would like to move to this API here.<br><br>Change-Id: Id617265337f09dfb6ddfe111ef5e578cd3dc9f63<br>---<br>M include/Makefile.am<br>A include/osmocom/core/ip_port.h<br>M src/Makefile.am<br>A src/ip_port.c<br>M tests/Makefile.am<br>A tests/ip_port/ip_port_test.c<br>A tests/ip_port/ip_port_test.ok<br>M tests/testsuite.at<br>8 files changed, 995 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/23/13123/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/Makefile.am b/include/Makefile.am</span><br><span>index 6f64fa6..1f0f94b 100644</span><br><span>--- a/include/Makefile.am</span><br><span>+++ b/include/Makefile.am</span><br><span>@@ -53,6 +53,7 @@</span><br><span>                        osmocom/core/utils.h \</span><br><span>                        osmocom/core/write_queue.h \</span><br><span>                        osmocom/core/use_count.h \</span><br><span style="color: hsl(120, 100%, 40%);">+                       osmocom/core/ip_port.h \</span><br><span>                        osmocom/crypt/auth.h \</span><br><span>                        osmocom/crypt/gprs_cipher.h \</span><br><span>                       osmocom/ctrl/control_cmd.h \</span><br><span>diff --git a/include/osmocom/core/ip_port.h b/include/osmocom/core/ip_port.h</span><br><span>new file mode 100644</span><br><span>index 0000000..2dad411</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/core/ip_port.h</span><br><span>@@ -0,0 +1,81 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file ip_port.h</span><br><span style="color: hsl(120, 100%, 40%);">+ * Common API to store an IP address and port.</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%);">+ * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: neels@hofmeyr.de</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</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%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <netinet/in.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \defgroup ip_port  IP address/port utilities.</span><br><span style="color: hsl(120, 100%, 40%);">+ * @{</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file ip_port.h</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%);">+int osmo_ip_str_type(const char *ip);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_ip_port {</span><br><span style="color: hsl(120, 100%, 40%);">+     /*! AF_INET for IPv4 address, or AF_INET6 for IPv6 address. */</span><br><span style="color: hsl(120, 100%, 40%);">+        int af;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! NUL terminated string of the IPv4 or IPv6 address. */</span><br><span style="color: hsl(120, 100%, 40%);">+     char ip[INET6_ADDRSTRLEN];</span><br><span style="color: hsl(120, 100%, 40%);">+    /*! Port number */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint16_t port;</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%);">+/*! Format string to print an osmo_ip_port.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * For example:</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *     struct osmo_ip_port *my_ip_port = ...;</span><br><span style="color: hsl(120, 100%, 40%);">+ *     printf("got " OSMO_IP_PORT_FMT, OSMO_IP_PORT_ARGS(my_ip_port));</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define OSMO_IP_PORT_FMT "%s:%u"</span><br><span style="color: hsl(120, 100%, 40%);">+#define OSMO_IP_PORT_ARGS(R) ((R)->ip ? : ""), (R)->port</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool osmo_ip_port_is_set(const struct osmo_ip_port *ip_port);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_str(struct osmo_ip_port *ip_port, const char *ip, uint16_t port);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_in_addr(struct osmo_ip_port *ip_port, const struct in_addr *addr, uint16_t port);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_in6_addr(struct osmo_ip_port *ip_port, const struct in6_addr *addr, uint16_t port);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_32(struct osmo_ip_port *ip_port, uint32_t ip, uint16_t port);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_32n(struct osmo_ip_port *ip_port, uint32_t ip, uint16_t port);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_sockaddr_in(struct osmo_ip_port *ip_port, const struct sockaddr_in *src);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_sockaddr_in6(struct osmo_ip_port *ip_port, const struct sockaddr_in6 *src);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_sockaddr(struct osmo_ip_port *ip_port, const struct sockaddr_storage *dst);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_in_addr(const struct osmo_ip_port *ip_port, struct in_addr *dst);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_in6_addr(const struct osmo_ip_port *ip_port, struct in6_addr *dst);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_32(const struct osmo_ip_port *ip_port, uint32_t *ip);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_32n(const struct osmo_ip_port *ip_port, uint32_t *ip);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_sockaddr_in(const struct osmo_ip_port *ip_port, struct sockaddr_in *dst);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_sockaddr_in6(const struct osmo_ip_port *ip_port, struct sockaddr_in6 *dst);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_sockaddr(const struct osmo_ip_port *ip_port, struct sockaddr_storage *dst);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index 726ad15..cb1d76c 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -26,6 +26,7 @@</span><br><span>                        isdnhdlc.c \</span><br><span>                         tdef.c \</span><br><span>                     use_count.c \</span><br><span style="color: hsl(120, 100%, 40%);">+                         ip_port.c \</span><br><span>                          $(NULL)</span><br><span> </span><br><span> if HAVE_SSSE3</span><br><span>diff --git a/src/ip_port.c b/src/ip_port.c</span><br><span>new file mode 100644</span><br><span>index 0000000..4ab6f79</span><br><span>--- /dev/null</span><br><span>+++ b/src/ip_port.c</span><br><span>@@ -0,0 +1,375 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file ip_port.c</span><br><span style="color: hsl(120, 100%, 40%);">+ * Common implementation to store an IP address and port.</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%);">+ * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: neels@hofmeyr.de</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</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%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <netinet/in.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <arpa/inet.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/ip_port.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/byteswap.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \addtogroup ip_port</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Common operations to store IP address as a char string along with a uint16_t port number.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Convert IP address string to/from in_addr and in6_addr, with bounds checking and basic housekeeping.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The initial purpose is to store and translate IP address info between GSM CC and MGCP protocols -- GSM mostly using</span><br><span style="color: hsl(120, 100%, 40%);">+ * 32-bit IPv4 addresses, and MGCP forwarding addresses as ASCII character strings.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (At the time of writing, there are no immediate IPv6 users that come to mind, but it seemed appropriate to</span><br><span style="color: hsl(120, 100%, 40%);">+ * accommodate both address families from the start.)</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%);">+ * \file ip_port.c</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%);">+/*! Return true if all elements of the osmo_ip_port instance are set.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip_port  The instance to examine.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return True iff ip is nonempty, port is not 0 and af is set to either AF_INET or AF_INET6.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+bool osmo_ip_port_is_set(const struct osmo_ip_port *ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return *ip_port->ip</span><br><span style="color: hsl(120, 100%, 40%);">+                && ip_port->port</span><br><span style="color: hsl(120, 100%, 40%);">+           && (ip_port->af == AF_INET || ip_port->af == AF_INET6);</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%);">+/*! Distinguish between valid IPv4 and IPv6 strings.</span><br><span style="color: hsl(120, 100%, 40%);">+ * This does not verify whether the string is a valid IP address; it assumes that the input is a valid IP address, and</span><br><span style="color: hsl(120, 100%, 40%);">+ * on that premise returns whether it is an IPv4 or IPv6 string, by looking for '.' and ':' characters.  It is safe to</span><br><span style="color: hsl(120, 100%, 40%);">+ * feed invalid address strings, but the return value is only guaranteed to be meaningful if the input was valid.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip  Valid IP address string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return AF_INET or AF_INET6, or AF_UNSPEC if neither '.' nor ':' are found in the string.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_str_type(const char *ip)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!ip)</span><br><span style="color: hsl(120, 100%, 40%);">+              return AF_UNSPEC;</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Could also be IPv4-mapped IPv6 format with both colons and dots: x:x:x:x:x:x:d.d.d.d */</span><br><span style="color: hsl(120, 100%, 40%);">+    if (strchr(ip, ':'))</span><br><span style="color: hsl(120, 100%, 40%);">+          return AF_INET6;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (strchr(ip, '.'))</span><br><span style="color: hsl(120, 100%, 40%);">+          return AF_INET;</span><br><span style="color: hsl(120, 100%, 40%);">+       return AF_UNSPEC;</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%);">+/*! Safely copy the given ip string to ip_port, classify to AF_INET or AF_INET6, and set the port.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Data will be written to ip_port even if an error is returned.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ip_port  The instance to copy to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip  Valid IP address string.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] port  Port number.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative if copying the address string failed (e.g. too long), if the address family could</span><br><span style="color: hsl(120, 100%, 40%);">+ *         not be detected (i.e. if osmo_ip_str_type() returned AF_UNSPEC), or if ip_port is NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_str(struct osmo_ip_port *ip_port, const char *ip, uint16_t port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ip)</span><br><span style="color: hsl(120, 100%, 40%);">+              ip = "";</span><br><span style="color: hsl(120, 100%, 40%);">+    *ip_port = (struct osmo_ip_port){</span><br><span style="color: hsl(120, 100%, 40%);">+             .af = osmo_ip_str_type(ip),</span><br><span style="color: hsl(120, 100%, 40%);">+           .port = port,</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+    rc = osmo_strlcpy(ip_port->ip, ip, sizeof(ip_port->ip));</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc >= sizeof(ip_port->ip))</span><br><span style="color: hsl(120, 100%, 40%);">+          return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ip_port->af == AF_UNSPEC)</span><br><span style="color: hsl(120, 100%, 40%);">+              return -EINVAL;</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 style="color: hsl(120, 100%, 40%);">+/*! Convert IPv4 address to osmo_ip_port, and set port.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ip_port  The instance to copy to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] addr  IPv4 address data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] port  Port number.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_in_addr(struct osmo_ip_port *ip_port, const struct in_addr *addr, uint16_t port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       *ip_port = (struct osmo_ip_port){</span><br><span style="color: hsl(120, 100%, 40%);">+             .af = AF_INET,</span><br><span style="color: hsl(120, 100%, 40%);">+                .port = port,</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!inet_ntop(AF_INET, addr, ip_port->ip, sizeof(ip_port->ip)))</span><br><span style="color: hsl(120, 100%, 40%);">+                return -ENOSPC;</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 style="color: hsl(120, 100%, 40%);">+/*! Convert IPv6 address to osmo_ip_port, and set port.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ip_port  The instance to copy to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] addr  IPv6 address data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] port  Port number.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_in6_addr(struct osmo_ip_port *ip_port, const struct in6_addr *addr, uint16_t port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       *ip_port = (struct osmo_ip_port){</span><br><span style="color: hsl(120, 100%, 40%);">+             .af = AF_INET6,</span><br><span style="color: hsl(120, 100%, 40%);">+               .port = port,</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!inet_ntop(AF_INET6, addr, ip_port->ip, sizeof(ip_port->ip)))</span><br><span style="color: hsl(120, 100%, 40%);">+               return -ENOSPC;</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 style="color: hsl(120, 100%, 40%);">+/*! Convert IPv4 address from 32bit host-byte-order to osmo_ip_port, and set port.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ip_port  The instance to copy to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] addr  32bit IPv4 address data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] port  Port number.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_32(struct osmo_ip_port *ip_port, uint32_t ip, uint16_t port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct in_addr addr;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       addr.s_addr = ip;</span><br><span style="color: hsl(120, 100%, 40%);">+     return osmo_ip_port_from_in_addr(ip_port, &addr, port);</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%);">+/*! Convert IPv4 address from 32bit network-byte-order to osmo_ip_port, and set port.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ip_port  The instance to copy to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] addr  32bit IPv4 address data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] port  Port number.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_32n(struct osmo_ip_port *ip_port, uint32_t ip, uint16_t port)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       return osmo_ip_port_from_32(ip_port, osmo_ntohl(ip), port);</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%);">+/*! Convert IPv4 address and port to osmo_ip_port.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ip_port  The instance to copy to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] src  IPv4 address and port data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_sockaddr_in(struct osmo_ip_port *ip_port, const struct sockaddr_in *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!src)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (src->sin_family != AF_INET)</span><br><span style="color: hsl(120, 100%, 40%);">+            return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       return osmo_ip_port_from_in_addr(ip_port, &src->sin_addr, osmo_ntohs(src->sin_port));</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%);">+/*! Convert IPv6 address and port to osmo_ip_port.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ip_port  The instance to copy to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] src  IPv6 address and port data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_sockaddr_in6(struct osmo_ip_port *ip_port, const struct sockaddr_in6 *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!src)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (src->sin6_family != AF_INET6)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       return osmo_ip_port_from_in6_addr(ip_port, &src->sin6_addr, osmo_ntohs(src->sin6_port));</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%);">+/*! Convert IPv4 or IPv6 address and port to osmo_ip_port.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] ip_port  The instance to copy to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] src  IPv4 or IPv6 address and port data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative if src does not indicate AF_INET nor AF_INET6 (or if the conversion fails, which</span><br><span style="color: hsl(120, 100%, 40%);">+ *         should not be possible in practice).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_from_sockaddr(struct osmo_ip_port *ip_port, const struct sockaddr_storage *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  const struct sockaddr_in *sin = (void*)src;</span><br><span style="color: hsl(120, 100%, 40%);">+   const struct sockaddr_in6 *sin6 = (void*)src;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!src)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (sin->sin_family == AF_INET)</span><br><span style="color: hsl(120, 100%, 40%);">+            return osmo_ip_port_from_sockaddr_in(ip_port, sin);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (sin6->sin6_family == AF_INET6)</span><br><span style="color: hsl(120, 100%, 40%);">+         return osmo_ip_port_from_sockaddr_in6(ip_port, sin6);</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%);">+/*! Convert osmo_ip_port address string to IPv4 address data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip_port  The instance to convert the IP of.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] dst  IPv4 address data to write to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error (e.g. invalid IPv4 address string).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_in_addr(const struct osmo_ip_port *ip_port, struct in_addr *dst)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!dst)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ip_port->af != AF_INET)</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EAFNOSUPPORT;</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = inet_pton(AF_INET, ip_port->ip, dst);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</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 style="color: hsl(120, 100%, 40%);">+/*! Convert osmo_ip_port address string to IPv6 address data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip_port  The instance to convert the IP of.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] dst  IPv6 address data to write to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error (e.g. invalid IPv6 address string).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_in6_addr(const struct osmo_ip_port *ip_port, struct in6_addr *dst)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!dst)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ip_port->af != AF_INET6)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = inet_pton(AF_INET6, ip_port->ip, dst);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (rc != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINVAL;</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 style="color: hsl(120, 100%, 40%);">+/*! Convert osmo_ip_port address string to IPv4 address data in host-byte-order.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip_port  The instance to convert the IP of.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] dst  IPv4 address data in 32bit host-byte-order format to write to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error (e.g. invalid IPv4 address string).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_32(const struct osmo_ip_port *ip_port, uint32_t *ip)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct in_addr addr;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ip)</span><br><span style="color: hsl(120, 100%, 40%);">+              return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = osmo_ip_port_to_in_addr(ip_port, &addr);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    *ip = addr.s_addr;</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 style="color: hsl(120, 100%, 40%);">+/*! Convert osmo_ip_port address string to IPv4 address data in network-byte-order.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip_port  The instance to convert the IP of.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] dst  IPv4 address data in 32bit network-byte-order format to write to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error (e.g. invalid IPv4 address string).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_32n(const struct osmo_ip_port *ip_port, uint32_t *ip)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t ip_h;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!ip)</span><br><span style="color: hsl(120, 100%, 40%);">+              return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = osmo_ip_port_to_32(ip_port, &ip_h);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc)</span><br><span style="color: hsl(120, 100%, 40%);">+               return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+    *ip = osmo_htonl(ip_h);</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 style="color: hsl(120, 100%, 40%);">+/*! Convert osmo_ip_port address string and port to IPv4 address and port data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip_port  The instance to convert the IP and port of.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] dst  IPv4 address and port data to write to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error (e.g. invalid IPv4 address string).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_sockaddr_in(const struct osmo_ip_port *ip_port, struct sockaddr_in *dst)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!dst)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ip_port->af != AF_INET)</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       *dst = (struct sockaddr_in){</span><br><span style="color: hsl(120, 100%, 40%);">+          .sin_family = ip_port->af,</span><br><span style="color: hsl(120, 100%, 40%);">+         .sin_port = osmo_htons(ip_port->port),</span><br><span style="color: hsl(120, 100%, 40%);">+     };</span><br><span style="color: hsl(120, 100%, 40%);">+    return osmo_ip_port_to_in_addr(ip_port, &dst->sin_addr);</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%);">+/*! Convert osmo_ip_port address string and port to IPv6 address and port data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip_port  The instance to convert the IP and port of.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] dst  IPv6 address and port data to write to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error (e.g. invalid IPv6 address string).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_sockaddr_in6(const struct osmo_ip_port *ip_port, struct sockaddr_in6 *dst)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!dst)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ip_port->af != AF_INET6)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       *dst = (struct sockaddr_in6){</span><br><span style="color: hsl(120, 100%, 40%);">+         .sin6_family = ip_port->af,</span><br><span style="color: hsl(120, 100%, 40%);">+                .sin6_port = osmo_htons(ip_port->port),</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+    return osmo_ip_port_to_in6_addr(ip_port, &dst->sin6_addr);</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%);">+/*! Convert osmo_ip_port address string and port to IPv4 or IPv6 address and port data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Depending on ip_port->af, dst will be handled as struct sockaddr_in or struct sockaddr_in6.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ip_port  The instance to convert the IP and port of.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] dst  IPv4/IPv6 address and port data to write to.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0 on success, negative on error (e.g. invalid IP address string for the family indicated by ip_port->af).</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ip_port_to_sockaddr(const struct osmo_ip_port *ip_port, struct sockaddr_storage *dst)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ip_port)</span><br><span style="color: hsl(120, 100%, 40%);">+         return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!dst)</span><br><span style="color: hsl(120, 100%, 40%);">+             return -ENOSPC;</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (ip_port->af) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case AF_INET:</span><br><span style="color: hsl(120, 100%, 40%);">+         return osmo_ip_port_to_sockaddr_in(ip_port, (void*)dst);</span><br><span style="color: hsl(120, 100%, 40%);">+      case AF_INET6:</span><br><span style="color: hsl(120, 100%, 40%);">+                return osmo_ip_port_to_sockaddr_in6(ip_port, (void*)dst);</span><br><span style="color: hsl(120, 100%, 40%);">+     default:</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/tests/Makefile.am b/tests/Makefile.am</span><br><span>index 0584834..afed74d 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -31,6 +31,7 @@</span><br><span>                tdef/tdef_vty_test_config_subnode                      \</span><br><span>             tdef/tdef_vty_test_dynamic                             \</span><br><span>             use_count/use_count_test                               \</span><br><span style="color: hsl(120, 100%, 40%);">+              ip_port/ip_port_test                                   \</span><br><span>             $(NULL)</span><br><span> </span><br><span> if ENABLE_MSGFILE</span><br><span>@@ -240,6 +241,9 @@</span><br><span> use_count_use_count_test_SOURCES = use_count/use_count_test.c</span><br><span> use_count_use_count_test_LDADD = $(LDADD)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ip_port_ip_port_test_SOURCES = ip_port/ip_port_test.c</span><br><span style="color: hsl(120, 100%, 40%);">+ip_port_ip_port_test_LDADD = $(LDADD)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # The `:;' works around a Bash 3.2 bug when the output is not writeable.</span><br><span> $(srcdir)/package.m4: $(top_srcdir)/configure.ac</span><br><span>        :;{ \</span><br><span>@@ -309,6 +313,7 @@</span><br><span>       tdef/tdef_vty_test_config_subnode.vty \</span><br><span>              tdef/tdef_vty_test_dynamic.vty \</span><br><span>             use_count/use_count_test.ok use_count/use_count_test.err \</span><br><span style="color: hsl(120, 100%, 40%);">+            ip_port/ip_port_test.ok \</span><br><span>            $(NULL)</span><br><span> </span><br><span> DISTCLEANFILES = atconfig atlocal conv/gsm0503_test_vectors.c</span><br><span>diff --git a/tests/ip_port/ip_port_test.c b/tests/ip_port/ip_port_test.c</span><br><span>new file mode 100644</span><br><span>index 0000000..da1150b</span><br><span>--- /dev/null</span><br><span>+++ b/tests/ip_port/ip_port_test.c</span><br><span>@@ -0,0 +1,238 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* tests for osmo_ip_port API of libmsomcore */</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Author: neels@hofmeyr.de</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</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%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/ip_port.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_ip_port oip_data[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     { .af = AF_INET, .ip = "1.2.3.4", .port = 5 },</span><br><span style="color: hsl(120, 100%, 40%);">+      { .af = AF_INET, .ip = "0.0.0.0", .port = 0 },</span><br><span style="color: hsl(120, 100%, 40%);">+      { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 },</span><br><span style="color: hsl(120, 100%, 40%);">+  { .af = AF_INET, .ip = "0.0.0.256", .port = 1 },</span><br><span style="color: hsl(120, 100%, 40%);">+    { .af = AF_INET, .ip = "not an ip address", .port = 1 },</span><br><span style="color: hsl(120, 100%, 40%);">+    { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 },</span><br><span style="color: hsl(120, 100%, 40%);">+    { .af = AF_INET6, .ip = "::", .port = 0 },</span><br><span style="color: hsl(120, 100%, 40%);">+  { .af = AF_INET6, .ip = "::1", .port = 0 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { .af = AF_INET6, .ip = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", .port = 65535 },</span><br><span style="color: hsl(120, 100%, 40%);">+ { .af = AF_INET6, .ip = "::fffff", .port = 1 },</span><br><span style="color: hsl(120, 100%, 40%);">+     { .af = AF_INET6, .ip = "not an ip address", .port = 1 },</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ { .af = AF_INET6, .ip = "1.2.3.4", .port = 5 },</span><br><span style="color: hsl(120, 100%, 40%);">+     { .af = AF_INET, .ip = "1:2:3::4", .port = 5 },</span><br><span style="color: hsl(120, 100%, 40%);">+     { .af = AF_UNSPEC, .ip = "1.2.3.4", .port = 5 },</span><br><span style="color: hsl(120, 100%, 40%);">+    { .af = AF_INET, .ip = "", .port = 5 },</span><br><span style="color: hsl(120, 100%, 40%);">+     { .af = AF_INET6, .ip = "", .port = 5 },</span><br><span style="color: hsl(120, 100%, 40%);">+    { .af = AF_INET, .ip = "1.2.3.4", .port = 0 },</span><br><span style="color: hsl(120, 100%, 40%);">+      { .af = AF_INET, .ip = "1.2.3:4:5", .port = 0 },</span><br><span style="color: hsl(120, 100%, 40%);">+    { .af = AF_INET6, .ip = "::1:10.9.8.7", .port = 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%);">+const char *af_name(int af)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (af) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case AF_INET:</span><br><span style="color: hsl(120, 100%, 40%);">+         return "AF_INET";</span><br><span style="color: hsl(120, 100%, 40%);">+   case AF_INET6:</span><br><span style="color: hsl(120, 100%, 40%);">+                return "AF_INET6";</span><br><span style="color: hsl(120, 100%, 40%);">+  case AF_UNSPEC:</span><br><span style="color: hsl(120, 100%, 40%);">+               return "AF_UNSPEC";</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return "?";</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%);">+static const struct value_string err_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      { -EINVAL, "-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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline const char *err_name(int err)</span><br><span style="color: hsl(120, 100%, 40%);">+{ return get_value_string(err_names, err); }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static inline const char *rc_name(int rc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!rc)</span><br><span style="color: hsl(120, 100%, 40%);">+              return "rc == 0";</span><br><span style="color: hsl(120, 100%, 40%);">+   if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return "rc < 0";</span><br><span style="color: hsl(120, 100%, 40%);">+ return "rc > 0";</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%);">+void dump_oip(const struct osmo_ip_port *oip)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("{ .af = %s, .ip = %s, .port = %u }\n", af_name(oip->af), osmo_quote_str(oip->ip, -1), oip->port);</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%);">+void ip_port_test_conversions()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        char buf[1024];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define hexdump(what) \</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_hexdump_buf(buf, sizeof(buf), (void*)(&what), sizeof(what), "", false)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < ARRAY_SIZE(oip_data); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct osmo_ip_port *x = &oip_data[i];</span><br><span style="color: hsl(120, 100%, 40%);">+            int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("\n\n");</span><br><span style="color: hsl(120, 100%, 40%);">+             dump_oip(x);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                printf("  osmo_ip_port_is_set() = %s\n", osmo_ip_port_is_set(x) ? "true" : "false");</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%);">+                     struct in_addr a = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      rc = osmo_ip_port_to_in_addr(x, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("  osmo_ip_port_to_in_addr() %s in_addr=%s\n", rc_name(rc), hexdump(a));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct osmo_ip_port back;</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = osmo_ip_port_from_in_addr(&back, &a, x->port);</span><br><span style="color: hsl(120, 100%, 40%);">+                                printf("   -> osmo_ip_port_from_in_addr() %s ", rc_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                            dump_oip(&back);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (memcmp(x, &back, sizeof(back)))</span><br><span style="color: hsl(120, 100%, 40%);">+                                       printf("      DIFFERS!\n");</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%);">+           {</span><br><span style="color: hsl(120, 100%, 40%);">+                     struct in6_addr a = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = osmo_ip_port_to_in6_addr(x, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("  osmo_ip_port_to_in6_addr() %s in6_addr=%s\n", rc_name(rc), hexdump(a));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct osmo_ip_port back;</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = osmo_ip_port_from_in6_addr(&back, &a, x->port);</span><br><span style="color: hsl(120, 100%, 40%);">+                               printf("   -> osmo_ip_port_from_in6_addr() %s ", rc_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                           dump_oip(&back);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (memcmp(x, &back, sizeof(back)))</span><br><span style="color: hsl(120, 100%, 40%);">+                                       printf("      DIFFERS!\n");</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%);">+           {</span><br><span style="color: hsl(120, 100%, 40%);">+                     uint32_t a = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = osmo_ip_port_to_32(x, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                   printf("  osmo_ip_port_to_32() %s uint32_t=0x%x\n", rc_name(rc), a);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct osmo_ip_port back;</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = osmo_ip_port_from_32(&back, a, x->port);</span><br><span style="color: hsl(120, 100%, 40%);">+                          printf("   -> osmo_ip_port_from_32() %s ", rc_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                         dump_oip(&back);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (memcmp(x, &back, sizeof(back)))</span><br><span style="color: hsl(120, 100%, 40%);">+                                       printf("      DIFFERS!\n");</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%);">+           {</span><br><span style="color: hsl(120, 100%, 40%);">+                     uint32_t a = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = osmo_ip_port_to_32n(x, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                  printf("  osmo_ip_port_to_32n() %s uint32_t=0x%x\n", rc_name(rc), a);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct osmo_ip_port back;</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = osmo_ip_port_from_32n(&back, a, x->port);</span><br><span style="color: hsl(120, 100%, 40%);">+                         printf("   -> osmo_ip_port_from_32n() %s ", rc_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                                dump_oip(&back);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (memcmp(x, &back, sizeof(back)))</span><br><span style="color: hsl(120, 100%, 40%);">+                                       printf("      DIFFERS!\n");</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%);">+           {</span><br><span style="color: hsl(120, 100%, 40%);">+                     struct sockaddr_in a = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                  rc = osmo_ip_port_to_sockaddr_in(x, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                  printf("  osmo_ip_port_to_sockaddr_in() %s sockaddr_in=%s\n", rc_name(rc), hexdump(a));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct osmo_ip_port back;</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = osmo_ip_port_from_sockaddr_in(&back, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                                printf("   -> osmo_ip_port_from_sockaddr_in() %s ", rc_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                                dump_oip(&back);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (memcmp(x, &back, sizeof(back)))</span><br><span style="color: hsl(120, 100%, 40%);">+                                       printf("      DIFFERS!\n");</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%);">+           {</span><br><span style="color: hsl(120, 100%, 40%);">+                     struct sockaddr_in6 a = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 rc = osmo_ip_port_to_sockaddr_in6(x, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                 printf("  osmo_ip_port_to_sockaddr_in6() %s sockaddr_in6=%s\n", rc_name(rc), hexdump(a));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct osmo_ip_port back;</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = osmo_ip_port_from_sockaddr_in6(&back, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                               printf("   -> osmo_ip_port_from_sockaddr_in6() %s ", rc_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                               dump_oip(&back);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (memcmp(x, &back, sizeof(back)))</span><br><span style="color: hsl(120, 100%, 40%);">+                                       printf("      DIFFERS!\n");</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%);">+           {</span><br><span style="color: hsl(120, 100%, 40%);">+                     struct sockaddr_storage a = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     rc = osmo_ip_port_to_sockaddr(x, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                     printf("  osmo_ip_port_to_sockaddr() %s sockaddr_storage=%s\n", rc_name(rc), hexdump(a));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (rc == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                struct osmo_ip_port back;</span><br><span style="color: hsl(120, 100%, 40%);">+                             rc = osmo_ip_port_from_sockaddr(&back, &a);</span><br><span style="color: hsl(120, 100%, 40%);">+                           printf("   -> osmo_ip_port_from_sockaddr() %s ", rc_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                           dump_oip(&back);</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (memcmp(x, &back, sizeof(back)))</span><br><span style="color: hsl(120, 100%, 40%);">+                                       printf("      DIFFERS!\n");</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%);">+           {</span><br><span style="color: hsl(120, 100%, 40%);">+                     struct osmo_ip_port from_str;</span><br><span style="color: hsl(120, 100%, 40%);">+                 rc = osmo_ip_port_from_str(&from_str, x->ip, x->port);</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf("  osmo_ip_port_from_str() %s ", rc_name(rc));</span><br><span style="color: hsl(120, 100%, 40%);">+                       dump_oip(&from_str);</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (rc == 0 && memcmp(x, &from_str, sizeof(from_str)))</span><br><span style="color: hsl(120, 100%, 40%);">+                            printf("      DIFFERS!\n");</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%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int main(int argc, char **argv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  ip_port_test_conversions();</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>diff --git a/tests/ip_port/ip_port_test.ok b/tests/ip_port/ip_port_test.ok</span><br><span>new file mode 100644</span><br><span>index 0000000..7ab7b01</span><br><span>--- /dev/null</span><br><span>+++ b/tests/ip_port/ip_port_test.ok</span><br><span>@@ -0,0 +1,288 @@</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%);">+{ .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc == 0 in_addr=01020304</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in_addr() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc == 0 uint32_t=0x4030201</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_32() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc == 0 uint32_t=0x1020304</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_32n() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc == 0 sockaddr_in=02000005010203040000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0200000501020304000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</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%);">+{ .af = AF_INET, .ip = "0.0.0.0", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = false</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc == 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in_addr() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc == 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_32() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc == 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_32n() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc == 0 sockaddr_in=02000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 }</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%);">+{ .af = AF_INET, .ip = "255.255.255.255", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc == 0 in_addr=ffffffff</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in_addr() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc == 0 uint32_t=0xffffffff</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_32() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc == 0 uint32_t=0xffffffff</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_32n() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc == 0 sockaddr_in=0200ffffffffffff0000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0200ffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 }</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%);">+{ .af = AF_INET, .ip = "0.0.0.256", .port = 1 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=02000001000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0200000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET, .ip = "0.0.0.256", .port = 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%);">+{ .af = AF_INET, .ip = "not an ip address", .port = 1 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=02000001000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0200000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc < 0 { .af = AF_UNSPEC, .ip = "not an ip address", .port = 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%);">+{ .af = AF_INET6, .ip = "1:2:3::4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc == 0 in6_addr=00010002000300000000000000000004</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000005000000000001000200030000000000000000000400000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0a00000500000000000100020003000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 }</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%);">+{ .af = AF_INET6, .ip = "::", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = false</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc == 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "::", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "::", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET6, .ip = "::", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "::", .port = 0 }</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%);">+{ .af = AF_INET6, .ip = "::1", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = false</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc == 0 in6_addr=00000000000000000000000000000001</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "::1", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000000000000000000000000000000000000000000000100000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "::1", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0a00000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET6, .ip = "::1", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "::1", .port = 0 }</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%);">+{ .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc == 0 in6_addr=ffffffffffffffffffffffffffffffff</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc == 0 sockaddr_in6=0a00ffff00000000ffffffffffffffffffffffffffffffff00000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0a00ffff00000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 }</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%);">+{ .af = AF_INET6, .ip = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc == 0 in6_addr=ffffffffffffffffffffffffffffffff</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc == 0 sockaddr_in6=0a00ffff00000000ffffffffffffffffffffffffffffffff00000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0a00ffff00000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", .port = 65535 }</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%);">+{ .af = AF_INET6, .ip = "::fffff", .port = 1 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=0a000001000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0a00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "::fffff", .port = 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%);">+{ .af = AF_INET6, .ip = "not an ip address", .port = 1 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=0a000001000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0a00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc < 0 { .af = AF_UNSPEC, .ip = "not an ip address", .port = 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%);">+{ .af = AF_INET6, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=0a000005000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0a00000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</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%);">+{ .af = AF_INET, .ip = "1:2:3::4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=02000005000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0200000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</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%);">+{ .af = AF_UNSPEC, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = false</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</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%);">+{ .af = AF_INET, .ip = "", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = false</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=02000005000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0200000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc < 0 { .af = AF_UNSPEC, .ip = "", .port = 5 }</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%);">+{ .af = AF_INET6, .ip = "", .port = 5 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = false</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=0a000005000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0a00000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc < 0 { .af = AF_UNSPEC, .ip = "", .port = 5 }</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%);">+{ .af = AF_INET, .ip = "1.2.3.4", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = false</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc == 0 in_addr=01020304</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in_addr() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc == 0 uint32_t=0x4030201</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_32() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc == 0 uint32_t=0x1020304</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_32n() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc == 0 sockaddr_in=02000000010203040000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0200000001020304000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 }</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%);">+{ .af = AF_INET, .ip = "1.2.3:4:5", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = false</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=02000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc < 0 sockaddr_storage=0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "1.2.3:4:5", .port = 0 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</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%);">+{ .af = AF_INET6, .ip = "::1:10.9.8.7", .port = 1 }</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_is_set() = true</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in_addr() rc < 0 in_addr=00000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_in6_addr() rc == 0 in6_addr=0000000000000000000000010a090807</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "::1:a09:807", .port = 1 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_32n() rc < 0 uint32_t=0x0</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000001000000000000000000000000000000010a09080700000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "::1:a09:807", .port = 1 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_to_sockaddr() rc == 0 sockaddr_storage=0a000001000000000000000000000000000000010a0908070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</span><br><span style="color: hsl(120, 100%, 40%);">+   -> osmo_ip_port_from_sockaddr() rc == 0 { .af = AF_INET6, .ip = "::1:a09:807", .port = 1 }</span><br><span style="color: hsl(120, 100%, 40%);">+      DIFFERS!</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_ip_port_from_str() rc == 0 { .af = AF_INET6, .ip = "::1:10.9.8.7", .port = 1 }</span><br><span>diff --git a/tests/testsuite.at b/tests/testsuite.at</span><br><span>index edf127d..5d74af1 100644</span><br><span>--- a/tests/testsuite.at</span><br><span>+++ b/tests/testsuite.at</span><br><span>@@ -338,3 +338,9 @@</span><br><span> cat $abs_srcdir/use_count/use_count_test.err > experr</span><br><span> AT_CHECK([$abs_top_builddir/tests/use_count/use_count_test], [0], [expout], [experr])</span><br><span> AT_CLEANUP</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AT_SETUP([ip_port])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_KEYWORDS([ip_port])</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/ip_port/ip_port_test.ok > expout</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CHECK([$abs_top_builddir/tests/ip_port/ip_port_test], [0], [expout], [ignore])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CLEANUP</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13123">change 13123</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/13123"/><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-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Id617265337f09dfb6ddfe111ef5e578cd3dc9f63 </div>
<div style="display:none"> Gerrit-Change-Number: 13123 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>