diff options
-rw-r--r-- | src/shared/socket-netlink.c | 27 | ||||
-rw-r--r-- | src/shared/socket-netlink.h | 1 | ||||
-rw-r--r-- | src/test/test-socket-netlink.c | 36 |
3 files changed, 64 insertions, 0 deletions
diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c index e117459c10..32e45985b4 100644 --- a/src/shared/socket-netlink.c +++ b/src/shared/socket-netlink.c @@ -235,6 +235,33 @@ int socket_address_parse_and_warn(SocketAddress *a, const char *s) { return 0; } +int socket_addr_port_from_string_auto(const char *s, uint16_t default_port, SocketAddress *a) { + union in_addr_union address; + uint16_t port = 0; + int family, r; + + assert(a); + assert(s); + + r = in_addr_port_ifindex_name_from_string_auto(s, &family, &address, &port, NULL, NULL); + if (r < 0) + return r; + + if (family == AF_INET) { + memcpy(&a->sockaddr.in.sin_addr, &address.in.s_addr, sizeof(a->sockaddr.in.sin_addr)); + a->sockaddr.in.sin_family = AF_INET; + a->size = sizeof(struct sockaddr_in); + a->sockaddr.in.sin_port = port ? htobe16(port) : htobe16(default_port); + } else { + memcpy(&a->sockaddr.in6.sin6_addr, &address.in6, sizeof(a->sockaddr.in6.sin6_addr)); + a->sockaddr.in6.sin6_family = AF_INET6; + a->sockaddr.in6.sin6_port = port ? htobe16(port) : htobe16(default_port); + a->size = sizeof(struct sockaddr_in6); + } + + return 0; +} + int socket_address_parse_netlink(SocketAddress *a, const char *s) { _cleanup_free_ char *word = NULL; unsigned group = 0; diff --git a/src/shared/socket-netlink.h b/src/shared/socket-netlink.h index e6cd7d9bf1..143fc8d41a 100644 --- a/src/shared/socket-netlink.h +++ b/src/shared/socket-netlink.h @@ -16,6 +16,7 @@ int make_socket_fd(int log_level, const char* address, int type, int flags); int socket_address_parse(SocketAddress *a, const char *s); int socket_address_parse_and_warn(SocketAddress *a, const char *s); int socket_address_parse_netlink(SocketAddress *a, const char *s); +int socket_addr_port_from_string_auto(const char *s, uint16_t default_port, SocketAddress *a); bool socket_address_is(const SocketAddress *a, const char *s, int type); bool socket_address_is_netlink(const SocketAddress *a, const char *s); diff --git a/src/test/test-socket-netlink.c b/src/test/test-socket-netlink.c index 0a2007f0b7..4335d2eb6c 100644 --- a/src/test/test-socket-netlink.c +++ b/src/test/test-socket-netlink.c @@ -213,6 +213,41 @@ static void test_socket_address_is_netlink(void) { assert_se(!socket_address_is_netlink(&a, "route 1")); } +static void test_socket_addr_port_from_string_auto_one(const char *in, uint16_t port, int ret, int family, const char *expected) { + _cleanup_free_ char *out = NULL; + SocketAddress a; + int r; + + r = socket_addr_port_from_string_auto(in, port, &a); + if (r >= 0) + assert_se(sockaddr_pretty(&a.sockaddr.sa, a.size, false, true, &out) >= 0); + + log_info("\"%s\" → %s → \"%s\" (expect \"%s\")", in, + r >= 0 ? "✓" : "✗", empty_to_dash(out), r >= 0 ? expected ?: in : "-"); + assert_se(r == ret); + if (r >= 0) { + assert_se(a.sockaddr.sa.sa_family == family); + assert_se(streq(out, expected ?: in)); + } +} + +static void test_socket_addr_port_from_string_auto(void) { + log_info("/* %s */", __func__); + + test_socket_addr_port_from_string_auto_one("junk", 51, -EINVAL, 0, NULL); + test_socket_addr_port_from_string_auto_one("192.168.1.1", 53, 0, AF_INET, "192.168.1.1:53"); + test_socket_addr_port_from_string_auto_one(".168.1.1", 53, -EINVAL, 0, NULL); + test_socket_addr_port_from_string_auto_one("989.168.1.1", 53, -EINVAL, 0, NULL); + + test_socket_addr_port_from_string_auto_one("[::1]", 53, -EINVAL, 0, NULL); + test_socket_addr_port_from_string_auto_one("[::1]8888", 53, -EINVAL, 0, NULL); + test_socket_addr_port_from_string_auto_one("2001:db8:3c4d:15::1a2f:1a2b", 53, 0, AF_INET6, "[2001:db8:3c4d:15::1a2f:1a2b]:53"); + test_socket_addr_port_from_string_auto_one("[2001:db8:3c4d:15::1a2f:1a2b]:2001", 53, 0, AF_INET6, "[2001:db8:3c4d:15::1a2f:1a2b]:2001"); + test_socket_addr_port_from_string_auto_one("[::1]:0", 53, -EINVAL, 0, NULL); + test_socket_addr_port_from_string_auto_one("[::1]:65536", 53, -ERANGE, 0, NULL); + test_socket_addr_port_from_string_auto_one("[a:b:1]:8888", 53, -EINVAL, 0, NULL); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); @@ -222,6 +257,7 @@ int main(int argc, char *argv[]) { test_socket_address_get_path(); test_socket_address_is(); test_socket_address_is_netlink(); + test_socket_addr_port_from_string_auto(); return 0; } |