From 80788fac9e54fd7705b8c8ada78c1985b4842238 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Mon, 12 Oct 2020 01:11:20 +0200 Subject: add osmo_sockaddr_to_str_buf/osmo_sockaddr_to_str Add helper to format osmo_sockaddr into a string. Change-Id: I917f25ebd1239eae5855d973ced15b93731e33a0 --- include/osmocom/core/socket.h | 4 +++ src/socket.c | 62 +++++++++++++++++++++++++++++++++++ tests/socket/socket_test.c | 75 +++++++++++++++++++++++++++++++++++++++++++ tests/socket/socket_test.ok | 10 ++++++ 4 files changed, 151 insertions(+) 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 -- cgit v1.2.3