From: Luca Boccassi Date: Tue, 3 Jan 2023 17:01:28 +0000 (+0100) Subject: src/shared/: split AF_UNIX/AF_VSOCK address parsing into src/basic/ X-Git-Tag: v253-rc1~168^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=747b5d963ef8078032e1f6f7ee98f8725d8fb454;p=thirdparty%2Fsystemd.git src/shared/: split AF_UNIX/AF_VSOCK address parsing into src/basic/ We'll use it from libsystemd0 later, but AF_INET/6 requires some netlink calls and thus the additional library dependency --- diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 54f5f1cc5bc..d7946a3641a 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1472,3 +1472,71 @@ int connect_unix_path(int fd, int dir_fd, const char *path) { return RET_NERRNO(connect(fd, &sa.sa, salen)); } + +int socket_address_parse_unix(SocketAddress *ret_address, const char *s) { + struct sockaddr_un un; + int r; + + assert(ret_address); + assert(s); + + if (!IN_SET(*s, '/', '@')) + return -EPROTO; + + r = sockaddr_un_set_path(&un, s); + if (r < 0) + return r; + + *ret_address = (SocketAddress) { + .sockaddr.un = un, + .size = r, + }; + + return 0; +} + +int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) { + /* AF_VSOCK socket in vsock:cid:port notation */ + _cleanup_free_ char *n = NULL; + char *e, *cid_start; + unsigned port, cid; + int r; + + assert(ret_address); + assert(s); + + cid_start = startswith(s, "vsock:"); + if (!cid_start) + return -EPROTO; + + e = strchr(cid_start, ':'); + if (!e) + return -EINVAL; + + r = safe_atou(e+1, &port); + if (r < 0) + return r; + + n = strndup(cid_start, e - cid_start); + if (!n) + return -ENOMEM; + + if (isempty(n)) + cid = VMADDR_CID_ANY; + else { + r = safe_atou(n, &cid); + if (r < 0) + return r; + } + + *ret_address = (SocketAddress) { + .sockaddr.vm = { + .svm_cid = cid, + .svm_family = AF_VSOCK, + .svm_port = port, + }, + .size = sizeof(struct sockaddr_vm), + }; + + return 0; +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 0b8d53e8954..5cb35f65fb9 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -336,3 +336,9 @@ int socket_get_mtu(int fd, int af, size_t *ret); #define UCRED_INVALID { .pid = 0, .uid = UID_INVALID, .gid = GID_INVALID } int connect_unix_path(int fd, int dir_fd, const char *path); + +/* Parses AF_UNIX and AF_VSOCK addresses. AF_INET[6] require some netlink calls, so it cannot be in + * src/basic/ and is done from 'socket_local_address from src/shared/. Return -EPROTO in case of + * protocol mismatch. */ +int socket_address_parse_unix(SocketAddress *ret_address, const char *s); +int socket_address_parse_vsock(SocketAddress *ret_address, const char *s); diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c index 494047a5d15..e115dff5064 100644 --- a/src/shared/socket-netlink.c +++ b/src/shared/socket-netlink.c @@ -17,120 +17,74 @@ #include "string-util.h" int socket_address_parse(SocketAddress *a, const char *s) { - _cleanup_free_ char *n = NULL; - char *e; + uint16_t port; int r; assert(a); assert(s); - if (IN_SET(*s, '/', '@')) { - /* AF_UNIX socket */ - struct sockaddr_un un; - - r = sockaddr_un_set_path(&un, s); - if (r < 0) - return r; - - *a = (SocketAddress) { - .sockaddr.un = un, - .size = r, - }; + r = socket_address_parse_unix(a, s); + if (r == -EPROTO) + r = socket_address_parse_vsock(a, s); + if (r != -EPROTO) + return r; - } else if (startswith(s, "vsock:")) { - /* AF_VSOCK socket in vsock:cid:port notation */ - const char *cid_start = s + STRLEN("vsock:"); - unsigned port, cid; + r = parse_ip_port(s, &port); + if (r == -ERANGE) + return r; /* Valid port syntax, but the numerical value is wrong for a port. */ + if (r >= 0) { + /* Just a port */ + if (socket_ipv6_is_supported()) + *a = (SocketAddress) { + .sockaddr.in6 = { + .sin6_family = AF_INET6, + .sin6_port = htobe16(port), + .sin6_addr = in6addr_any, + }, + .size = sizeof(struct sockaddr_in6), + }; + else + *a = (SocketAddress) { + .sockaddr.in = { + .sin_family = AF_INET, + .sin_port = htobe16(port), + .sin_addr.s_addr = INADDR_ANY, + }, + .size = sizeof(struct sockaddr_in), + }; - e = strchr(cid_start, ':'); - if (!e) - return -EINVAL; + } else { + union in_addr_union address; + int family, ifindex; - r = safe_atou(e+1, &port); + r = in_addr_port_ifindex_name_from_string_auto(s, &family, &address, &port, &ifindex, NULL); if (r < 0) return r; - n = strndup(cid_start, e - cid_start); - if (!n) - return -ENOMEM; - - if (isempty(n)) - cid = VMADDR_CID_ANY; - else { - r = safe_atou(n, &cid); - if (r < 0) - return r; - } - - *a = (SocketAddress) { - .sockaddr.vm = { - .svm_cid = cid, - .svm_family = AF_VSOCK, - .svm_port = port, - }, - .size = sizeof(struct sockaddr_vm), - }; - - } else { - uint16_t port; - - r = parse_ip_port(s, &port); - if (r == -ERANGE) - return r; /* Valid port syntax, but the numerical value is wrong for a port. */ - if (r >= 0) { - /* Just a port */ - if (socket_ipv6_is_supported()) - *a = (SocketAddress) { - .sockaddr.in6 = { - .sin6_family = AF_INET6, - .sin6_port = htobe16(port), - .sin6_addr = in6addr_any, - }, - .size = sizeof(struct sockaddr_in6), - }; - else - *a = (SocketAddress) { - .sockaddr.in = { - .sin_family = AF_INET, - .sin_port = htobe16(port), - .sin_addr.s_addr = INADDR_ANY, - }, - .size = sizeof(struct sockaddr_in), - }; - - } else { - union in_addr_union address; - int family, ifindex; - - r = in_addr_port_ifindex_name_from_string_auto(s, &family, &address, &port, &ifindex, NULL); - if (r < 0) - return r; - - if (port == 0) /* No port, no go. */ - return -EINVAL; + if (port == 0) /* No port, no go. */ + return -EINVAL; - if (family == AF_INET) - *a = (SocketAddress) { - .sockaddr.in = { - .sin_family = AF_INET, - .sin_addr = address.in, - .sin_port = htobe16(port), - }, - .size = sizeof(struct sockaddr_in), - }; - else if (family == AF_INET6) - *a = (SocketAddress) { - .sockaddr.in6 = { - .sin6_family = AF_INET6, - .sin6_addr = address.in6, - .sin6_port = htobe16(port), - .sin6_scope_id = ifindex, - }, - .size = sizeof(struct sockaddr_in6), - }; - else - assert_not_reached(); - } + if (family == AF_INET) + *a = (SocketAddress) { + .sockaddr.in = { + .sin_family = AF_INET, + .sin_addr = address.in, + .sin_port = htobe16(port), + }, + .size = sizeof(struct sockaddr_in), + }; + else if (family == AF_INET6) + *a = (SocketAddress) { + .sockaddr.in6 = { + .sin6_family = AF_INET6, + .sin6_addr = address.in6, + .sin6_port = htobe16(port), + .sin6_scope_id = ifindex, + }, + .size = sizeof(struct sockaddr_in6), + }; + else + assert_not_reached(); } return 0;