summaryrefslogtreecommitdiffstats
path: root/src/shared/socket-netlink.c
diff options
context:
space:
mode:
authorLuca Boccassi <bluca@debian.org>2023-01-03 18:01:28 +0100
committerLuca Boccassi <bluca@debian.org>2023-01-05 18:43:47 +0100
commit747b5d963ef8078032e1f6f7ee98f8725d8fb454 (patch)
treecb8107ba0df346e61b1020785786f3bc2eefb234 /src/shared/socket-netlink.c
parentvconsole: permit configuration of vconsole settings via credentials (diff)
downloadsystemd-747b5d963ef8078032e1f6f7ee98f8725d8fb454.tar.xz
systemd-747b5d963ef8078032e1f6f7ee98f8725d8fb454.zip
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
Diffstat (limited to '')
-rw-r--r--src/shared/socket-netlink.c158
1 files changed, 56 insertions, 102 deletions
diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c
index 494047a5d1..e115dff506 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;