summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/core/socket.h3
-rw-r--r--src/socket.c20
-rw-r--r--tests/utils/utils_test.c115
-rw-r--r--tests/utils/utils_test.ok10
4 files changed, 148 insertions, 0 deletions
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 <osmocom/core/select.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -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 <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/socket.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
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