From 59f4caf4efcbd76478cdd2a1d800c0978144c5ba Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 19 Jul 2018 22:13:19 +0200 Subject: add osmo_sockaddr_to_str_and_uint() This came from osmo-bsc refactoring patch I82e3f918295daa83274a4cf803f046979f284366 https://gerrit.osmocom.org/#/c/osmo-bsc/+/9671/6/src/osmo-bsc/gsm_data.c@1708 Add regression test in utils_test.c. Change-Id: I1f2918418c38918c5ac70acaa51a47adfca12b5e --- include/osmocom/core/socket.h | 3 ++ src/socket.c | 20 ++++++++ tests/utils/utils_test.c | 115 ++++++++++++++++++++++++++++++++++++++++++ tests/utils/utils_test.ok | 10 ++++ 4 files changed, 148 insertions(+) diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h index 47d9f308..20515b99 100644 --- a/include/osmocom/core/socket.h +++ b/include/osmocom/core/socket.h @@ -44,6 +44,9 @@ int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type, int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen); +unsigned int osmo_sockaddr_to_str_and_uint(char *addr, unsigned int addr_len, uint16_t *port, + const struct sockaddr *sa); + int osmo_sock_unix_init(uint16_t type, uint8_t proto, const char *socket_path, unsigned int flags); diff --git a/src/socket.c b/src/socket.c index cd73f17c..04058474 100644 --- a/src/socket.c +++ b/src/socket.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -553,6 +554,25 @@ int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen) return 0; } +/*! Convert sockaddr to IP address as char string and port as uint16_t. + * \param[out] addr String buffer to write IP address to, or NULL. + * \param[out] addr_len Size of \a addr. + * \param[out] port Pointer to uint16_t to write the port number to, or NULL. + * \param[in] sa Sockaddr to convert. + * \returns the required string buffer size, like osmo_strlcpy(), or 0 if \a addr is NULL. + */ +unsigned int osmo_sockaddr_to_str_and_uint(char *addr, unsigned int addr_len, uint16_t *port, + const struct sockaddr *sa) +{ + const struct sockaddr_in *sin = (const struct sockaddr_in *)sa; + + if (port) + *port = ntohs(sin->sin_port); + if (addr) + return osmo_strlcpy(addr, inet_ntoa(sin->sin_addr), addr_len); + return 0; +} + /*! Initialize a unix domain socket (including bind/connect) * \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM * \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index 84964f57..a146190d 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -24,10 +24,13 @@ #include #include +#include #include #include #include +#include +#include static void hexdump_test(void) { @@ -446,6 +449,117 @@ static void isqrt_test(void) } } + +struct osmo_sockaddr_to_str_and_uint_test_case { + uint16_t port; + bool omit_port; + const char *addr; + unsigned int addr_len; + bool omit_addr; + unsigned int expect_rc; + const char *expect_returned_addr; +}; + +struct osmo_sockaddr_to_str_and_uint_test_case osmo_sockaddr_to_str_and_uint_test_data[] = { + { + .port = 0, + .addr = "0.0.0.0", + .addr_len = 20, + .expect_rc = 7, + }, + { + .port = 65535, + .addr = "255.255.255.255", + .addr_len = 20, + .expect_rc = 15, + }, + { + .port = 1234, + .addr = "234.23.42.123", + .addr_len = 20, + .expect_rc = 13, + }, + { + .port = 1234, + .addr = "234.23.42.123", + .addr_len = 10, + .expect_rc = 13, + .expect_returned_addr = "234.23.42", + }, + { + .port = 1234, + .omit_port = true, + .addr = "234.23.42.123", + .addr_len = 20, + .expect_rc = 13, + }, + { + .port = 1234, + .addr = "234.23.42.123", + .omit_addr = true, + .expect_rc = 0, + .expect_returned_addr = "", + }, + { + .port = 1234, + .addr = "234.23.42.123", + .addr_len = 0, + .expect_rc = 13, + .expect_returned_addr = "", + }, + { + .port = 1234, + .addr = "234.23.42.123", + .omit_port = true, + .omit_addr = true, + .expect_rc = 0, + .expect_returned_addr = "", + }, +}; + +static void osmo_sockaddr_to_str_and_uint_test(void) +{ + int i; + printf("\n%s\n", __func__); + + for (i = 0; i < ARRAY_SIZE(osmo_sockaddr_to_str_and_uint_test_data); i++) { + struct osmo_sockaddr_to_str_and_uint_test_case *t = + &osmo_sockaddr_to_str_and_uint_test_data[i]; + + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_port = htons(t->port), + }; + inet_aton(t->addr, &sin.sin_addr); + + char addr[20] = {}; + uint16_t port = 0; + unsigned int rc; + + rc = osmo_sockaddr_to_str_and_uint( + t->omit_addr? NULL : addr, t->addr_len, + t->omit_port? NULL : &port, + (const struct sockaddr*)&sin); + + printf("[%d] %s:%u%s%s addr_len=%u --> %s:%u rc=%u\n", + i, + t->addr ? : "-", + t->port, + t->omit_addr ? " (omit addr)" : "", + t->omit_port ? " (omit port)" : "", + t->addr_len, + addr, port, rc); + if (rc != t->expect_rc) + printf("ERROR: Expected rc = %u\n", t->expect_rc); + if (!t->expect_returned_addr) + t->expect_returned_addr = t->addr; + if (strcmp(t->expect_returned_addr, addr)) + printf("ERROR: Expected addr = '%s'\n", t->expect_returned_addr); + if (!t->omit_port && port != t->port) + printf("ERROR: Expected port = %u\n", t->port); + } +} + int main(int argc, char **argv) { static const struct log_info log_info = {}; @@ -459,5 +573,6 @@ int main(int argc, char **argv) str_escape_test(); str_quote_test(); isqrt_test(); + osmo_sockaddr_to_str_and_uint_test(); return 0; } diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok index ea9216f0..b158bf7b 100644 --- a/tests/utils/utils_test.ok +++ b/tests/utils/utils_test.ok @@ -139,3 +139,13 @@ NOT passed through. '"printable"' 'NULL' Testing integer square-root + +osmo_sockaddr_to_str_and_uint_test +[0] 0.0.0.0:0 addr_len=20 --> 0.0.0.0:0 rc=7 +[1] 255.255.255.255:65535 addr_len=20 --> 255.255.255.255:65535 rc=15 +[2] 234.23.42.123:1234 addr_len=20 --> 234.23.42.123:1234 rc=13 +[3] 234.23.42.123:1234 addr_len=10 --> 234.23.42:1234 rc=13 +[4] 234.23.42.123:1234 (omit port) addr_len=20 --> 234.23.42.123:0 rc=13 +[5] 234.23.42.123:1234 (omit addr) addr_len=0 --> :1234 rc=0 +[6] 234.23.42.123:1234 addr_len=0 --> :1234 rc=13 +[7] 234.23.42.123:1234 (omit addr) (omit port) addr_len=0 --> :0 rc=0 -- cgit v1.2.3