]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared: Introduce socket_addr_port_from_string_auto
authorSusant Sahani <ssahani@vmware.com>
Fri, 28 Aug 2020 10:39:40 +0000 (10:39 +0000)
committerSusant Sahani <ssahani@vmware.com>
Wed, 2 Sep 2020 03:25:17 +0000 (03:25 +0000)
src/shared/socket-netlink.c
src/shared/socket-netlink.h
src/test/test-socket-netlink.c

index e117459c10dfaf69c4d1c82e8b0d9ce4f23b7c8c..32e45985b42559fcb9c539a4fede99579fc5d932 100644 (file)
@@ -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;
index e6cd7d9bf190aeac8752911d2934911a605e3e94..143fc8d41a8fa36157ca59291ac54b8f3c2e5df3 100644 (file)
@@ -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);
index 0a2007f0b7ef2428f5101bfff8069c5d0e743ac1..4335d2eb6c5f28edae4c1bb81f15d9f6f9bb9900 100644 (file)
@@ -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;
 }