aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/core/socket.h4
-rw-r--r--src/socket.c62
-rw-r--r--tests/socket/socket_test.c75
-rw-r--r--tests/socket/socket_test.ok10
4 files changed, 151 insertions, 0 deletions
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index 98782406..0443c06e 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -118,5 +118,9 @@ int osmo_sockaddr_local_ip(struct osmo_sockaddr *local_ip,
int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
const struct osmo_sockaddr *b);
+const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *sockaddr);
+char *osmo_sockaddr_to_str_buf(char *buf, size_t buf_len,
+ const struct osmo_sockaddr *sockaddr);
+
#endif /* (!EMBEDDED) */
/*! @} */
diff --git a/src/socket.c b/src/socket.c
index 93b3d99d..229f72e3 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1715,6 +1715,68 @@ int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
}
}
+/*! string-format a given osmo_sockaddr address
+ * \param[in] sockaddr the osmo_sockaddr to print
+ * \return pointer to the string on success; NULL on error
+ */
+const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *sockaddr)
+{
+ /* INET6_ADDRSTRLEN contains already a null termination,
+ * adding '[' ']' ':' '16 bit port' */
+ static __thread char buf[INET6_ADDRSTRLEN + 8];
+ return osmo_sockaddr_to_str_buf(buf, sizeof(buf), sockaddr);
+}
+
+/*! string-format a given osmo_sockaddr address into a user-supplied buffer
+ * \param[in] buf user-supplied output buffer
+ * \param[in] buf_len size of the user-supplied output buffer in bytes
+ * \param[in] sockaddr the osmo_sockaddr to print
+ * \return pointer to the string on success; NULL on error
+ */
+char *osmo_sockaddr_to_str_buf(char *buf, size_t buf_len,
+ const struct osmo_sockaddr *sockaddr)
+{
+ uint16_t port = 0;
+ size_t written;
+ if (buf_len < 5)
+ return NULL;
+
+ if (!sockaddr)
+ return NULL;
+
+ switch (sockaddr->u.sa.sa_family) {
+ case AF_INET:
+ written = osmo_sockaddr_to_str_and_uint(buf, buf_len, &port, &sockaddr->u.sa);
+ if (written + 1 >= buf_len && port)
+ return NULL;
+ if (port)
+ snprintf(buf + written, buf_len - written, ":%u", port);
+ break;
+ case AF_INET6:
+ buf[0] = '[';
+ written = osmo_sockaddr_to_str_and_uint(buf + 1, buf_len - 1, &port, &sockaddr->u.sa);
+ if (written + 2 >= buf_len)
+ return NULL;
+
+ if (written + 3 >= buf_len && port)
+ return NULL;
+
+ if (port)
+ snprintf(buf + 1 + written, buf_len - written - 1, "]:%u", port);
+ else {
+ buf[written + 1] = ']';
+ buf[written + 2] = 0;
+ }
+ break;
+ default:
+ snprintf(buf, buf_len, "unsupported family %d", sockaddr->u.sa.sa_family);
+ return buf;
+ }
+
+ return buf;
+}
+
+
#endif /* HAVE_SYS_SOCKET_H */
/*! @} */
diff --git a/tests/socket/socket_test.c b/tests/socket/socket_test.c
index 671177fb..0bf2127b 100644
--- a/tests/socket/socket_test.c
+++ b/tests/socket/socket_test.c
@@ -313,6 +313,80 @@ static int test_sockinit_osa(void)
return 0;
}
+static void test_osa_str(void)
+{
+ char buf[256];
+ const char *result;
+ struct osmo_sockaddr localhost4 = {};
+ struct osmo_sockaddr localhost6 = {};
+
+ localhost4.u.sin = (struct sockaddr_in){
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = inet_addr("127.0.0.1"),
+ .sin_port = htons(42),
+ };
+
+ localhost6.u.sin6 = (struct sockaddr_in6){
+ .sin6_family = AF_INET6,
+ .sin6_port = htons(42),
+ };
+ inet_pton(AF_INET6, "::1", &localhost6.u.sin6.sin6_addr);
+
+ /* test a too short str */
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, 1, &localhost4);
+ printf("Checking osmo_sockaddr_to_str_buf to small IPv4\n");
+ OSMO_ASSERT(result == NULL);
+
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, sizeof(buf), &localhost4);
+ printf("Checking osmo_sockaddr_to_str_buf IPv4\n");
+ OSMO_ASSERT(!strncmp("127.0.0.1:42", result, sizeof(buf)));
+
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, 256, &localhost6);
+ printf("Checking osmo_sockaddr_to_str_buf IPv6\n");
+ OSMO_ASSERT(!strncmp("[::1]:42", result, sizeof(buf)));
+
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, 8, &localhost6);
+ printf("Checking osmo_sockaddr_to_str_buf too short IPv6\n");
+ OSMO_ASSERT(!strncmp("[::1]:4", result, sizeof(buf)));
+
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, 5, &localhost6);
+ printf("Checking osmo_sockaddr_to_str_buf too short IPv6\n");
+ OSMO_ASSERT(result == NULL);
+
+ localhost6.u.sin6.sin6_port = 0;
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, 5, &localhost6);
+ printf("Checking osmo_sockaddr_to_str_buf only 5 bytes IPv6\n");
+ OSMO_ASSERT(result == NULL);
+
+ inet_pton(AF_INET6, "::", &localhost6.u.sin6.sin6_addr);
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, 5, &localhost6);
+ printf("Checking osmo_sockaddr_to_str_buf only 5 bytes IPv6\n");
+ OSMO_ASSERT(!strncmp("[::]", result, sizeof(buf)));
+
+ inet_pton(AF_INET6, "2003:1234:5678:90ab:cdef:1234:4321:4321", &localhost6.u.sin6.sin6_addr);
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, sizeof(buf), &localhost6);
+ printf("Checking osmo_sockaddr_to_str_buf long IPv6\n");
+ OSMO_ASSERT(!strncmp("[2003:1234:5678:90ab:cdef:1234:4321:4321]", result, sizeof(buf)));
+
+ localhost6.u.sin6.sin6_port = htons(23420);
+ memset(&buf[0], 0, sizeof(buf));
+ result = osmo_sockaddr_to_str_buf(buf, sizeof(buf), &localhost6);
+ printf("Checking osmo_sockaddr_to_str_buf long IPv6 port\n");
+ OSMO_ASSERT(!strncmp("[2003:1234:5678:90ab:cdef:1234:4321:4321]:23420", result, sizeof(buf)));
+
+ result = osmo_sockaddr_to_str(&localhost6);
+ printf("Checking osmo_sockaddr_to_str_buf long IPv6 port static buffer\n");
+ OSMO_ASSERT(!strncmp("[2003:1234:5678:90ab:cdef:1234:4321:4321]:23420", result, sizeof(buf)));
+}
+
const struct log_info_cat default_categories[] = {
};
@@ -332,6 +406,7 @@ int main(int argc, char *argv[])
test_sockinit2();
test_get_ip_and_port();
test_sockinit_osa();
+ test_osa_str();
return EXIT_SUCCESS;
}
diff --git a/tests/socket/socket_test.ok b/tests/socket/socket_test.ok
index 9a52d44e..236c0111 100644
--- a/tests/socket/socket_test.ok
+++ b/tests/socket/socket_test.ok
@@ -21,3 +21,13 @@ Checking osmo_sock_init_osa() for combined BIND + CONNECT on IPv6
Checking osmo_sock_init_osa() must fail on mixed IPv4 & IPv6
Checking osmo_sock_init_osa() must fail on mixed IPv6 & IPv4
Checking osmo_sock_init_osa() must fail on invalid osmo_sockaddr
+Checking osmo_sockaddr_to_str_buf to small IPv4
+Checking osmo_sockaddr_to_str_buf IPv4
+Checking osmo_sockaddr_to_str_buf IPv6
+Checking osmo_sockaddr_to_str_buf too short IPv6
+Checking osmo_sockaddr_to_str_buf too short IPv6
+Checking osmo_sockaddr_to_str_buf only 5 bytes IPv6
+Checking osmo_sockaddr_to_str_buf only 5 bytes IPv6
+Checking osmo_sockaddr_to_str_buf long IPv6
+Checking osmo_sockaddr_to_str_buf long IPv6 port
+Checking osmo_sockaddr_to_str_buf long IPv6 port static buffer