[systemd-commits] 5 commits - Makefile.am src/libsystemd src/machine src/network src/nss-myhostname src/resolve src/shared src/test
Lennart Poettering
lennart at kemper.freedesktop.org
Thu Jul 10 12:35:10 PDT 2014
Makefile.am | 8 -
src/libsystemd/sd-bus/bus-internal.h | 7 -
src/libsystemd/sd-daemon/sd-daemon.c | 11 -
src/libsystemd/sd-rtnl/local-addresses.c | 150 ++++++++++++++++++++++
src/libsystemd/sd-rtnl/local-addresses.h | 37 +++++
src/machine/machine-dbus.c | 103 ++-------------
src/network/networkd-link.c | 8 -
src/network/networkd.h | 5
src/nss-myhostname/addresses.c | 149 ---------------------
src/nss-myhostname/addresses.h | 43 ------
src/nss-myhostname/nss-myhostname.c | 42 +++---
src/resolve/resolved.h | 2
src/shared/in-addr-util.c | 211 +++++++++++++++++++++++++++++++
src/shared/in-addr-util.h | 44 ++++++
src/shared/socket-util.c | 187 ---------------------------
src/shared/socket-util.h | 12 -
src/test/test-socket-util.c | 1
17 files changed, 497 insertions(+), 523 deletions(-)
New commits:
commit 4faefc7ff884eae65a80e82313fd9f4bb859d6db
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jul 10 21:32:44 2014 +0200
networkd: always prefer dhcp routes over ipv4ll routes
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 6257372..3e35090 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -427,7 +427,7 @@ static int link_set_dhcp_routes(Link *link) {
route->in_addr.in = static_routes[i].gw_addr;
route->dst_addr.in = static_routes[i].dst_addr;
route->dst_prefixlen = static_routes[i].dst_prefixlen;
- route->metrics = DHCP_STATIC_ROUTE_METRIC;
+ route->metrics = DHCP_ROUTE_METRIC;
r = route_configure(route, link, &route_handler);
if (r < 0) {
@@ -491,7 +491,7 @@ static int link_enter_set_routes(Link *link) {
route->family = AF_INET;
route->scope = RT_SCOPE_LINK;
- route->metrics = 99;
+ route->metrics = IPV4LL_ROUTE_METRIC;
r = route_configure(route, link, &route_handler);
if (r < 0) {
@@ -539,7 +539,7 @@ static int link_enter_set_routes(Link *link) {
route_gw->dst_addr.in = gateway;
route_gw->dst_prefixlen = 32;
route_gw->scope = RT_SCOPE_LINK;
- route_gw->metrics = DHCP_STATIC_ROUTE_METRIC;
+ route_gw->metrics = DHCP_ROUTE_METRIC;
r = route_configure(route_gw, link, &route_handler);
if (r < 0) {
@@ -552,7 +552,7 @@ static int link_enter_set_routes(Link *link) {
route->family = AF_INET;
route->in_addr.in = gateway;
- route->metrics = DHCP_STATIC_ROUTE_METRIC;
+ route->metrics = DHCP_ROUTE_METRIC;
r = route_configure(route, link, &route_handler);
if (r < 0) {
diff --git a/src/network/networkd.h b/src/network/networkd.h
index c39d221..9132e70 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -42,7 +42,8 @@
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
#define VXLAN_VID_MAX (1u << 24) - 1
-#define DHCP_STATIC_ROUTE_METRIC 1024
+#define DHCP_ROUTE_METRIC 1024
+#define IPV4LL_ROUTE_METRIC 2048
typedef struct NetDev NetDev;
typedef struct Network Network;
commit 496a5a69707653b231fbb350c0d8d837762248bb
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jul 10 21:27:14 2014 +0200
machined: when querying addresses of a container, use same code as nss-myhostname uses
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 6504dba..3741485 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -24,15 +24,14 @@
#include <sys/capability.h>
#include <arpa/inet.h>
-#include "sd-rtnl.h"
#include "bus-util.h"
#include "bus-label.h"
#include "strv.h"
-#include "rtnl-util.h"
#include "bus-errors.h"
#include "copy.h"
#include "fileio.h"
#include "in-addr-util.h"
+#include "local-addresses.h"
#include "machine.h"
static int property_get_id(
@@ -173,9 +172,9 @@ int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void
return sd_bus_error_set_errno(error, -errno);
if (child == 0) {
- _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *resp = NULL;
- _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
- sd_rtnl_message *addr;
+ _cleanup_free_ struct local_address *addresses = NULL;
+ struct local_address *a;
+ int i, n;
pair[0] = safe_close(pair[0]);
@@ -183,97 +182,23 @@ int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void
if (r < 0)
_exit(EXIT_FAILURE);
- r = sd_rtnl_open(&rtnl, 0);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- r = sd_rtnl_call(rtnl, req, 0, &resp);
- if (r < 0)
+ n = local_addresses(&addresses);
+ if (n < 0)
_exit(EXIT_FAILURE);
- for (addr = resp; addr; addr = sd_rtnl_message_next(addr)) {
- uint16_t type;
- unsigned char family, scope;
- union in_addr_union in_addr;
- struct iovec iov[2];
- unsigned char flags;
-
- r = sd_rtnl_message_get_errno(addr);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- r = sd_rtnl_message_get_type(addr, &type);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- if (type != RTM_NEWADDR)
- continue;
-
- r = sd_rtnl_message_addr_get_flags(addr, &flags);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- if (flags & IFA_F_DEPRECATED)
- continue;
-
- r = sd_rtnl_message_addr_get_scope(addr, &scope);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- if (scope == RT_SCOPE_HOST || scope == RT_SCOPE_NOWHERE)
- continue;
-
- r = sd_rtnl_message_addr_get_family(addr, &family);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) };
-
- switch (family) {
-
- case AF_INET:
-
- r = sd_rtnl_message_read_in_addr(addr, IFA_LOCAL, &in_addr.in);
- if (r < 0) {
- r = sd_rtnl_message_read_in_addr(addr, IFA_ADDRESS, &in_addr.in);
- if (r < 0)
- _exit(EXIT_FAILURE);
- }
-
- if (in_addr.in.s_addr == htobe32(INADDR_LOOPBACK))
- continue;
-
- iov[1] = (struct iovec) { .iov_base = &in_addr.in, .iov_len = sizeof(in_addr.in) };
- break;
-
- case AF_INET6:
-
- r = sd_rtnl_message_read_in6_addr(addr, IFA_LOCAL, &in_addr.in6);
- if (r < 0) {
- r = sd_rtnl_message_read_in6_addr(addr, IFA_ADDRESS, &in_addr.in6);
- if (r < 0)
- _exit(EXIT_FAILURE);
- }
-
- if (IN6_IS_ADDR_LOOPBACK(&in_addr.in6))
- continue;
-
- iov[1] = (struct iovec) { .iov_base = &in_addr.in6, .iov_len = sizeof(in_addr.in6) };
- break;
-
- default:
- continue;
- }
+ for (a = addresses, i = 0; i < n; a++, i++) {
+ struct iovec iov[2] = {
+ { .iov_base = &a->family, .iov_len = sizeof(a->family) },
+ { .iov_base = &a->address, .iov_len = PROTO_ADDRESS_SIZE(a->family) },
+ };
r = writev(pair[1], iov, 2);
if (r < 0)
_exit(EXIT_FAILURE);
}
+ pair[1] = safe_close(pair[1]);
+
_exit(EXIT_SUCCESS);
}
commit 3cb4674019567ef93e4a463dd145fd3af6242877
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jul 10 21:16:40 2014 +0200
libsystemd: make use of our common sockaddr_union everywhere
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index d1183d6..618e82c 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -237,12 +237,7 @@ struct sd_bus {
Hashmap *vtable_methods;
Hashmap *vtable_properties;
- union {
- struct sockaddr sa;
- struct sockaddr_un un;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
- } sockaddr;
+ union sockaddr_union sockaddr;
socklen_t sockaddr_size;
char *kernel;
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c
index 7caa63d..46241f7 100644
--- a/src/libsystemd/sd-daemon/sd-daemon.c
+++ b/src/libsystemd/sd-daemon/sd-daemon.c
@@ -37,6 +37,7 @@
#include "util.h"
#include "path-util.h"
+#include "socket-util.h"
#include "sd-daemon.h"
_public_ int sd_listen_fds(int unset_environment) {
@@ -196,14 +197,6 @@ static int sd_is_socket_internal(int fd, int type, int listening) {
return 1;
}
-union sockaddr_union {
- struct sockaddr sa;
- struct sockaddr_in in4;
- struct sockaddr_in6 in6;
- struct sockaddr_un un;
- struct sockaddr_storage storage;
-};
-
_public_ int sd_is_socket(int fd, int family, int type, int listening) {
int r;
@@ -261,7 +254,7 @@ _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint
if (l < sizeof(struct sockaddr_in))
return -EINVAL;
- return htons(port) == sockaddr.in4.sin_port;
+ return htons(port) == sockaddr.in.sin_port;
} else {
if (l < sizeof(struct sockaddr_in6))
return -EINVAL;
commit 3b653205cf7bd3851befd0a9f6a3ded6e267c173
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jul 10 21:15:26 2014 +0200
shared: split out in_addr related calls from socket-util.[ch] into its private in-addr-util.[ch]
These are enough calls for a new file, and they are sufficiently
different from the sockaddr-related calls, hence let's split this out.
diff --git a/Makefile.am b/Makefile.am
index 50e31db..2dd36c8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -765,6 +765,8 @@ libsystemd_shared_la_SOURCES = \
src/shared/pager.h \
src/shared/socket-util.c \
src/shared/socket-util.h \
+ src/shared/in-addr-util.c \
+ src/shared/in-addr-util.h \
src/shared/conf-files.c \
src/shared/conf-files.h \
src/shared/cgroup-util.c \
diff --git a/src/libsystemd/sd-rtnl/local-addresses.h b/src/libsystemd/sd-rtnl/local-addresses.h
index cc26fc4..d3dff8b 100644
--- a/src/libsystemd/sd-rtnl/local-addresses.h
+++ b/src/libsystemd/sd-rtnl/local-addresses.h
@@ -26,7 +26,7 @@
#include <assert.h>
#include <sys/socket.h>
-#include "socket-util.h"
+#include "in-addr-util.h"
struct local_address {
int ifindex;
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 39db505..6504dba 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -32,7 +32,7 @@
#include "bus-errors.h"
#include "copy.h"
#include "fileio.h"
-#include "socket-util.h"
+#include "in-addr-util.h"
#include "machine.h"
static int property_get_id(
diff --git a/src/network/networkd.h b/src/network/networkd.h
index b9c5eee..c39d221 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -38,7 +38,7 @@
#include "list.h"
#include "set.h"
#include "condition-util.h"
-#include "socket-util.h"
+#include "in-addr-util.h"
#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
#define VXLAN_VID_MAX (1u << 24) - 1
diff --git a/src/resolve/resolved.h b/src/resolve/resolved.h
index 48b361d..ad49c63 100644
--- a/src/resolve/resolved.h
+++ b/src/resolve/resolved.h
@@ -26,7 +26,7 @@
#include "util.h"
#include "list.h"
-#include "socket-util.h"
+#include "in-addr-util.h"
typedef struct Address Address;
typedef struct Manager Manager;
diff --git a/src/shared/in-addr-util.c b/src/shared/in-addr-util.c
new file mode 100644
index 0000000..98d2446
--- /dev/null
+++ b/src/shared/in-addr-util.c
@@ -0,0 +1,211 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <arpa/inet.h>
+
+#include "in-addr-util.h"
+
+int in_addr_null(unsigned family, union in_addr_union *u) {
+ assert(u);
+
+ if (family == AF_INET)
+ return u->in.s_addr == 0;
+
+ if (family == AF_INET6)
+ return
+ u->in6.s6_addr32[0] == 0 &&
+ u->in6.s6_addr32[1] == 0 &&
+ u->in6.s6_addr32[2] == 0 &&
+ u->in6.s6_addr32[3] == 0;
+
+ return -EAFNOSUPPORT;
+}
+
+
+int in_addr_equal(unsigned family, union in_addr_union *a, union in_addr_union *b) {
+ assert(a);
+ assert(b);
+
+ if (family == AF_INET)
+ return a->in.s_addr == b->in.s_addr;
+
+ if (family == AF_INET6)
+ return
+ a->in6.s6_addr32[0] == b->in6.s6_addr32[0] &&
+ a->in6.s6_addr32[1] == b->in6.s6_addr32[1] &&
+ a->in6.s6_addr32[2] == b->in6.s6_addr32[2] &&
+ a->in6.s6_addr32[3] == b->in6.s6_addr32[3];
+
+ return -EAFNOSUPPORT;
+}
+
+int in_addr_prefix_intersect(
+ unsigned family,
+ const union in_addr_union *a,
+ unsigned aprefixlen,
+ const union in_addr_union *b,
+ unsigned bprefixlen) {
+
+ unsigned m;
+
+ assert(a);
+ assert(b);
+
+ /* Checks whether there are any addresses that are in both
+ * networks */
+
+ m = MIN(aprefixlen, bprefixlen);
+
+ if (family == AF_INET) {
+ uint32_t x, nm;
+
+ x = be32toh(a->in.s_addr ^ b->in.s_addr);
+ nm = (m == 0) ? 0 : 0xFFFFFFFFUL << (32 - m);
+
+ return (x & nm) == 0;
+ }
+
+ if (family == AF_INET6) {
+ unsigned i;
+
+ if (m > 128)
+ m = 128;
+
+ for (i = 0; i < 16; i++) {
+ uint8_t x, nm;
+
+ x = a->in6.s6_addr[i] ^ b->in6.s6_addr[i];
+
+ if (m < 8)
+ nm = 0xFF << (8 - m);
+ else
+ nm = 0xFF;
+
+ if ((x & nm) != 0)
+ return 0;
+
+ if (m > 8)
+ m -= 8;
+ else
+ m = 0;
+ }
+
+ return 1;
+ }
+
+ return -EAFNOSUPPORT;
+}
+
+int in_addr_prefix_next(unsigned family, union in_addr_union *u, unsigned prefixlen) {
+ assert(u);
+
+ /* Increases the network part of an address by one. Returns
+ * positive it that succeeds, or 0 if this overflows. */
+
+ if (prefixlen <= 0)
+ return 0;
+
+ if (family == AF_INET) {
+ uint32_t c, n;
+
+ if (prefixlen > 32)
+ prefixlen = 32;
+
+ c = be32toh(u->in.s_addr);
+ n = c + (1UL << (32 - prefixlen));
+ if (n < c)
+ return 0;
+ n &= 0xFFFFFFFFUL << (32 - prefixlen);
+
+ u->in.s_addr = htobe32(n);
+ return 1;
+ }
+
+ if (family == AF_INET6) {
+ struct in6_addr add = {}, result;
+ uint8_t overflow = 0;
+ unsigned i;
+
+ if (prefixlen > 128)
+ prefixlen = 128;
+
+ /* First calculate what we have to add */
+ add.s6_addr[(prefixlen-1) / 8] = 1 << (7 - (prefixlen-1) % 8);
+
+ for (i = 16; i > 0; i--) {
+ unsigned j = i - 1;
+
+ result.s6_addr[j] = u->in6.s6_addr[j] + add.s6_addr[j] + overflow;
+ overflow = (result.s6_addr[j] < u->in6.s6_addr[j]);
+ }
+
+ if (overflow)
+ return 0;
+
+ u->in6 = result;
+ return 1;
+ }
+
+ return -EAFNOSUPPORT;
+}
+
+int in_addr_to_string(unsigned family, const union in_addr_union *u, char **ret) {
+ char *x;
+ size_t l;
+
+ assert(u);
+ assert(ret);
+
+ if (family == AF_INET)
+ l = INET_ADDRSTRLEN;
+ else if (family == AF_INET6)
+ l = INET6_ADDRSTRLEN;
+ else
+ return -EAFNOSUPPORT;
+
+ x = new(char, l);
+ if (!x)
+ return -ENOMEM;
+
+ errno = 0;
+ if (!inet_ntop(family, u, x, l)) {
+ free(x);
+ return errno ? -errno : -EINVAL;
+ }
+
+ *ret = x;
+ return 0;
+}
+
+int in_addr_from_string(unsigned family, const char *s, union in_addr_union *ret) {
+
+ assert(s);
+ assert(ret);
+
+ if (!IN_SET(family, AF_INET, AF_INET6))
+ return -EAFNOSUPPORT;
+
+ errno = 0;
+ if (inet_pton(family, s, ret) <= 0)
+ return errno ? -errno : -EINVAL;
+
+ return 0;
+}
diff --git a/src/shared/in-addr-util.h b/src/shared/in-addr-util.h
new file mode 100644
index 0000000..ae3aa90
--- /dev/null
+++ b/src/shared/in-addr-util.h
@@ -0,0 +1,44 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2014 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/in.h>
+
+#include "macro.h"
+#include "util.h"
+
+union in_addr_union {
+ struct in_addr in;
+ struct in6_addr in6;
+};
+
+int in_addr_null(unsigned family, union in_addr_union *u);
+int in_addr_equal(unsigned family, union in_addr_union *a, union in_addr_union *b);
+int in_addr_prefix_intersect(unsigned family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
+int in_addr_prefix_next(unsigned family, union in_addr_union *u, unsigned prefixlen);
+int in_addr_to_string(unsigned family, const union in_addr_union *u, char **ret);
+int in_addr_from_string(unsigned family, const char *s, union in_addr_union *ret);
+
+static inline size_t PROTO_ADDRESS_SIZE(int proto) {
+ assert(proto == AF_INET || proto == AF_INET6);
+ return proto == AF_INET6 ? 16 : 4;
+}
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
index 6f49798..92564e3 100644
--- a/src/shared/socket-util.c
+++ b/src/shared/socket-util.c
@@ -640,193 +640,6 @@ int socket_address_unlink(SocketAddress *a) {
return 1;
}
-int in_addr_null(unsigned family, union in_addr_union *u) {
- assert(u);
-
- if (family == AF_INET)
- return u->in.s_addr == 0;
-
- if (family == AF_INET6)
- return
- u->in6.s6_addr32[0] == 0 &&
- u->in6.s6_addr32[1] == 0 &&
- u->in6.s6_addr32[2] == 0 &&
- u->in6.s6_addr32[3] == 0;
-
- return -EAFNOSUPPORT;
-}
-
-
-int in_addr_equal(unsigned family, union in_addr_union *a, union in_addr_union *b) {
- assert(a);
- assert(b);
-
- if (family == AF_INET)
- return a->in.s_addr == b->in.s_addr;
-
- if (family == AF_INET6)
- return
- a->in6.s6_addr32[0] == b->in6.s6_addr32[0] &&
- a->in6.s6_addr32[1] == b->in6.s6_addr32[1] &&
- a->in6.s6_addr32[2] == b->in6.s6_addr32[2] &&
- a->in6.s6_addr32[3] == b->in6.s6_addr32[3];
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_prefix_intersect(
- unsigned family,
- const union in_addr_union *a,
- unsigned aprefixlen,
- const union in_addr_union *b,
- unsigned bprefixlen) {
-
- unsigned m;
-
- assert(a);
- assert(b);
-
- /* Checks whether there are any addresses that are in both
- * networks */
-
- m = MIN(aprefixlen, bprefixlen);
-
- if (family == AF_INET) {
- uint32_t x, nm;
-
- x = be32toh(a->in.s_addr ^ b->in.s_addr);
- nm = (m == 0) ? 0 : 0xFFFFFFFFUL << (32 - m);
-
- return (x & nm) == 0;
- }
-
- if (family == AF_INET6) {
- unsigned i;
-
- if (m > 128)
- m = 128;
-
- for (i = 0; i < 16; i++) {
- uint8_t x, nm;
-
- x = a->in6.s6_addr[i] ^ b->in6.s6_addr[i];
-
- if (m < 8)
- nm = 0xFF << (8 - m);
- else
- nm = 0xFF;
-
- if ((x & nm) != 0)
- return 0;
-
- if (m > 8)
- m -= 8;
- else
- m = 0;
- }
-
- return 1;
- }
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_prefix_next(unsigned family, union in_addr_union *u, unsigned prefixlen) {
- assert(u);
-
- /* Increases the network part of an address by one. Returns
- * positive it that succeeds, or 0 if this overflows. */
-
- if (prefixlen <= 0)
- return 0;
-
- if (family == AF_INET) {
- uint32_t c, n;
-
- if (prefixlen > 32)
- prefixlen = 32;
-
- c = be32toh(u->in.s_addr);
- n = c + (1UL << (32 - prefixlen));
- if (n < c)
- return 0;
- n &= 0xFFFFFFFFUL << (32 - prefixlen);
-
- u->in.s_addr = htobe32(n);
- return 1;
- }
-
- if (family == AF_INET6) {
- struct in6_addr add = {}, result;
- uint8_t overflow = 0;
- unsigned i;
-
- if (prefixlen > 128)
- prefixlen = 128;
-
- /* First calculate what we have to add */
- add.s6_addr[(prefixlen-1) / 8] = 1 << (7 - (prefixlen-1) % 8);
-
- for (i = 16; i > 0; i--) {
- unsigned j = i - 1;
-
- result.s6_addr[j] = u->in6.s6_addr[j] + add.s6_addr[j] + overflow;
- overflow = (result.s6_addr[j] < u->in6.s6_addr[j]);
- }
-
- if (overflow)
- return 0;
-
- u->in6 = result;
- return 1;
- }
-
- return -EAFNOSUPPORT;
-}
-
-int in_addr_to_string(unsigned family, const union in_addr_union *u, char **ret) {
- char *x;
- size_t l;
-
- assert(u);
- assert(ret);
-
- if (family == AF_INET)
- l = INET_ADDRSTRLEN;
- else if (family == AF_INET6)
- l = INET6_ADDRSTRLEN;
- else
- return -EAFNOSUPPORT;
-
- x = new(char, l);
- if (!x)
- return -ENOMEM;
-
- errno = 0;
- if (!inet_ntop(family, u, x, l)) {
- free(x);
- return errno ? -errno : -EINVAL;
- }
-
- *ret = x;
- return 0;
-}
-
-int in_addr_from_string(unsigned family, const char *s, union in_addr_union *ret) {
-
- assert(s);
- assert(ret);
-
- if (!IN_SET(family, AF_INET, AF_INET6))
- return -EAFNOSUPPORT;
-
- errno = 0;
- if (inet_pton(family, s, ret) <= 0)
- return errno ? -errno : -EINVAL;
-
- return 0;
-}
-
static const char* const netlink_family_table[] = {
[NETLINK_ROUTE] = "route",
[NETLINK_FIREWALL] = "firewall",
diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
index 8d521ae..ec85d94 100644
--- a/src/shared/socket-util.h
+++ b/src/shared/socket-util.h
@@ -41,11 +41,6 @@ union sockaddr_union {
struct sockaddr_ll ll;
};
-union in_addr_union {
- struct in_addr in;
- struct in6_addr in6;
-};
-
typedef struct SocketAddress {
union sockaddr_union sockaddr;
@@ -111,15 +106,3 @@ SocketAddressBindIPv6Only socket_address_bind_ipv6_only_from_string(const char *
int netlink_family_to_string_alloc(int b, char **s);
int netlink_family_from_string(const char *s) _pure_;
-
-int in_addr_null(unsigned family, union in_addr_union *u);
-int in_addr_equal(unsigned family, union in_addr_union *a, union in_addr_union *b);
-int in_addr_prefix_intersect(unsigned family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
-int in_addr_prefix_next(unsigned family, union in_addr_union *u, unsigned prefixlen);
-int in_addr_to_string(unsigned family, const union in_addr_union *u, char **ret);
-int in_addr_from_string(unsigned family, const char *s, union in_addr_union *ret);
-
-static inline size_t PROTO_ADDRESS_SIZE(int proto) {
- assert(proto == AF_INET || proto == AF_INET6);
- return proto == AF_INET6 ? 16 : 4;
-}
diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c
index 9f42dbf..ed183e8 100644
--- a/src/test/test-socket-util.c
+++ b/src/test/test-socket-util.c
@@ -18,6 +18,7 @@
***/
#include "socket-util.h"
+#include "in-addr-util.h"
#include "util.h"
#include "macro.h"
#include "log.h"
commit e80af1bdddbc7a51191e29b0c841e8dcafe7b1cc
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Jul 10 21:01:25 2014 +0200
nss-myhostname: move local address listing logic into shared, so that we can make use of it from machined
diff --git a/Makefile.am b/Makefile.am
index b28fa3f..50e31db 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2320,6 +2320,8 @@ libsystemd_internal_la_SOURCES = \
src/libsystemd/sd-rtnl/rtnl-types.c \
src/libsystemd/sd-rtnl/rtnl-util.h \
src/libsystemd/sd-rtnl/rtnl-util.c \
+ src/libsystemd/sd-rtnl/local-addresses.h \
+ src/libsystemd/sd-rtnl/local-addresses.c \
src/libsystemd/sd-id128/sd-id128.c \
src/libsystemd/sd-daemon/sd-daemon.c \
src/libsystemd/sd-login/sd-login.c \
@@ -4398,9 +4400,7 @@ endif
if HAVE_MYHOSTNAME
libnss_myhostname_la_SOURCES = \
src/nss-myhostname/nss-myhostname.sym \
- src/nss-myhostname/nss-myhostname.c \
- src/nss-myhostname/addresses.h \
- src/nss-myhostname/addresses.c
+ src/nss-myhostname/nss-myhostname.c
libnss_myhostname_la_LDFLAGS = \
$(AM_LDFLAGS) \
diff --git a/src/libsystemd/sd-rtnl/local-addresses.c b/src/libsystemd/sd-rtnl/local-addresses.c
new file mode 100644
index 0000000..dd5cced
--- /dev/null
+++ b/src/libsystemd/sd-rtnl/local-addresses.c
@@ -0,0 +1,150 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2008-2011 Lennart Poettering
+ Copyright 2014 Tom Gundersen
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "sd-rtnl.h"
+#include "rtnl-util.h"
+#include "macro.h"
+#include "local-addresses.h"
+
+static int address_compare(const void *_a, const void *_b) {
+ const struct local_address *a = _a, *b = _b;
+
+ /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */
+
+ if (a->scope < b->scope)
+ return -1;
+ if (a->scope > b->scope)
+ return 1;
+
+ if (a->family == AF_INET && b->family == AF_INET6)
+ return -1;
+ if (a->family == AF_INET6 && b->family == AF_INET)
+ return 1;
+
+ if (a->ifindex < b->ifindex)
+ return -1;
+ if (a->ifindex > b->ifindex)
+ return 1;
+
+ return 0;
+}
+
+int local_addresses(struct local_address **ret) {
+ _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
+ _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+ _cleanup_free_ struct local_address *list = NULL;
+ size_t n_list = 0, n_allocated = 0;
+ sd_rtnl_message *m;
+ int r;
+
+ assert(ret);
+
+ r = sd_rtnl_open(&rtnl, 0);
+ if (r < 0)
+ return r;
+
+ r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
+ if (r < 0)
+ return r;
+
+ r = sd_rtnl_call(rtnl, req, 0, &reply);
+ if (r < 0)
+ return r;
+
+ for (m = reply; m; m = sd_rtnl_message_next(m)) {
+ struct local_address *a;
+ unsigned char flags;
+ uint16_t type;
+
+ r = sd_rtnl_message_get_errno(m);
+ if (r < 0)
+ return r;
+
+ r = sd_rtnl_message_get_type(m, &type);
+ if (r < 0)
+ return r;
+
+ if (type != RTM_NEWADDR)
+ continue;
+
+ r = sd_rtnl_message_addr_get_flags(m, &flags);
+ if (r < 0)
+ return r;
+
+ if (flags & IFA_F_DEPRECATED)
+ continue;
+
+ if (!GREEDY_REALLOC(list, n_allocated, n_list+1))
+ return -ENOMEM;
+
+ a = list + n_list;
+
+ r = sd_rtnl_message_addr_get_scope(m, &a->scope);
+ if (r < 0)
+ return r;
+
+ if (a->scope == RT_SCOPE_HOST || a->scope == RT_SCOPE_NOWHERE)
+ continue;
+
+ r = sd_rtnl_message_addr_get_family(m, &a->family);
+ if (r < 0)
+ return r;
+
+ switch (a->family) {
+
+ case AF_INET:
+ r = sd_rtnl_message_read_in_addr(m, IFA_LOCAL, &a->address.in);
+ if (r < 0) {
+ r = sd_rtnl_message_read_in_addr(m, IFA_ADDRESS, &a->address.in);
+ if (r < 0)
+ continue;
+ }
+ break;
+
+ case AF_INET6:
+ r = sd_rtnl_message_read_in6_addr(m, IFA_LOCAL, &a->address.in6);
+ if (r < 0) {
+ r = sd_rtnl_message_read_in6_addr(m, IFA_ADDRESS, &a->address.in6);
+ if (r < 0)
+ continue;
+ }
+ break;
+
+ default:
+ continue;
+ }
+
+ r = sd_rtnl_message_addr_get_ifindex(m, &a->ifindex);
+ if (r < 0)
+ return r;
+
+ n_list++;
+ };
+
+ if (n_list)
+ qsort(list, n_list, sizeof(struct local_address), address_compare);
+
+ *ret = list;
+ list = NULL;
+
+ return (int) n_list;
+}
diff --git a/src/libsystemd/sd-rtnl/local-addresses.h b/src/libsystemd/sd-rtnl/local-addresses.h
new file mode 100644
index 0000000..cc26fc4
--- /dev/null
+++ b/src/libsystemd/sd-rtnl/local-addresses.h
@@ -0,0 +1,37 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2008-2011 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <inttypes.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <sys/socket.h>
+
+#include "socket-util.h"
+
+struct local_address {
+ int ifindex;
+ unsigned char family, scope;
+ union in_addr_union address;
+};
+
+int local_addresses(struct local_address **ret);
diff --git a/src/nss-myhostname/addresses.c b/src/nss-myhostname/addresses.c
deleted file mode 100644
index d75e850..0000000
--- a/src/nss-myhostname/addresses.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2008-2011 Lennart Poettering
- Copyright 2014 Tom Gundersen
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-rtnl.h"
-#include "rtnl-util.h"
-#include "macro.h"
-#include "addresses.h"
-
-static int address_compare(const void *_a, const void *_b) {
- const struct address *a = _a, *b = _b;
-
- /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */
-
- if (a->scope < b->scope)
- return -1;
- if (a->scope > b->scope)
- return 1;
-
- if (a->family == AF_INET && b->family == AF_INET6)
- return -1;
- if (a->family == AF_INET6 && b->family == AF_INET)
- return 1;
-
- if (a->ifindex < b->ifindex)
- return -1;
- if (a->ifindex > b->ifindex)
- return 1;
-
- return 0;
-}
-
-int acquire_addresses(struct address **_list, unsigned *_n_list) {
- _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
- _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
- _cleanup_free_ struct address *list = NULL;
- size_t n_list = 0, n_allocated = 0;
- sd_rtnl_message *m;
- int r;
-
- r = sd_rtnl_open(&rtnl, 0);
- if (r < 0)
- return r;
-
- r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
- if (r < 0)
- return r;
-
- r = sd_rtnl_call(rtnl, req, 0, &reply);
- if (r < 0)
- return r;
-
- for (m = reply; m; m = sd_rtnl_message_next(m)) {
- struct address *a;
- unsigned char flags;
- uint16_t type;
-
- r = sd_rtnl_message_get_errno(m);
- if (r < 0)
- return r;
-
- r = sd_rtnl_message_get_type(m, &type);
- if (r < 0)
- return r;
-
- if (type != RTM_NEWADDR)
- continue;
-
- r = sd_rtnl_message_addr_get_flags(m, &flags);
- if (r < 0)
- return r;
-
- if (flags & IFA_F_DEPRECATED)
- continue;
-
- if (!GREEDY_REALLOC(list, n_allocated, n_list+1))
- return -ENOMEM;
-
- a = list + n_list;
-
- r = sd_rtnl_message_addr_get_scope(m, &a->scope);
- if (r < 0)
- return r;
-
- if (a->scope == RT_SCOPE_HOST || a->scope == RT_SCOPE_NOWHERE)
- continue;
-
- r = sd_rtnl_message_addr_get_family(m, &a->family);
- if (r < 0)
- return r;
-
- switch (a->family) {
-
- case AF_INET:
- r = sd_rtnl_message_read_in_addr(m, IFA_LOCAL, &a->address.in);
- if (r < 0) {
- r = sd_rtnl_message_read_in_addr(m, IFA_ADDRESS, &a->address.in);
- if (r < 0)
- continue;
- }
- break;
-
- case AF_INET6:
- r = sd_rtnl_message_read_in6_addr(m, IFA_LOCAL, &a->address.in6);
- if (r < 0) {
- r = sd_rtnl_message_read_in6_addr(m, IFA_ADDRESS, &a->address.in6);
- if (r < 0)
- continue;
- }
- break;
-
- default:
- continue;
- }
-
- r = sd_rtnl_message_addr_get_ifindex(m, &a->ifindex);
- if (r < 0)
- return r;
-
- n_list++;
- };
-
- if (n_list)
- qsort(list, n_list, sizeof(struct address), address_compare);
-
- *_list = list;
- list = NULL;
- *_n_list = n_list;
-
- return 0;
-}
diff --git a/src/nss-myhostname/addresses.h b/src/nss-myhostname/addresses.h
deleted file mode 100644
index 1bfb357..0000000
--- a/src/nss-myhostname/addresses.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2008-2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <sys/socket.h>
-
-#include "socket-util.h"
-
-struct address {
- unsigned char family, scope;
- union in_addr_union address;
- int ifindex;
-};
-
-static inline size_t PROTO_ADDRESS_SIZE(int proto) {
- assert(proto == AF_INET || proto == AF_INET6);
-
- return proto == AF_INET6 ? 16 : 4;
-}
-
-int acquire_addresses(struct address **_list, unsigned *_n_list);
diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c
index 6551ac9..15a35f3 100644
--- a/src/nss-myhostname/nss-myhostname.c
+++ b/src/nss-myhostname/nss-myhostname.c
@@ -30,7 +30,7 @@
#include <stdlib.h>
#include <arpa/inet.h>
-#include "addresses.h"
+#include "local-addresses.h"
#include "macro.h"
/* Ensure that glibc's assert is used. We cannot use assert from macro.h, as
@@ -99,15 +99,15 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
int32_t *ttlp) {
struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL;
- _cleanup_free_ struct address *addresses = NULL;
+ _cleanup_free_ struct local_address *addresses = NULL;
_cleanup_free_ char *hn = NULL;
const char *canonical = NULL;
- unsigned n_addresses = 0, n;
+ int n_addresses = 0, lo_ifi;
uint32_t local_address_ipv4;
- struct address *a;
+ struct local_address *a;
size_t l, idx, ms;
char *r_name;
- int lo_ifi;
+ unsigned n;
assert(name);
assert(pat);
@@ -136,8 +136,9 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
return NSS_STATUS_NOTFOUND;
}
- /* If this fails, n_addresses is 0. Which is fine */
- acquire_addresses(&addresses, &n_addresses);
+ n_addresses = local_addresses(&addresses);
+ if (n_addresses < 0)
+ n_addresses = 0;
canonical = hn;
local_address_ipv4 = LOCALADDRESS_IPV4;
@@ -184,7 +185,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
}
/* Fourth, fill actual addresses in, but in backwards order */
- for (a = addresses + n_addresses - 1, n = 0; n < n_addresses; n++, a--) {
+ for (a = addresses + n_addresses - 1, n = 0; (int) n < n_addresses; n++, a--) {
r_tuple = (struct gaih_addrtuple*) (buffer + idx);
r_tuple->next = r_tuple_prev;
r_tuple->name = r_name;
@@ -214,7 +215,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
static enum nss_status fill_in_hostent(
const char *canonical, const char *additional,
int af,
- struct address *addresses, unsigned n_addresses,
+ struct local_address *addresses, unsigned n_addresses,
uint32_t local_address_ipv4,
struct hostent *result,
char *buffer, size_t buflen,
@@ -225,7 +226,7 @@ static enum nss_status fill_in_hostent(
size_t l_canonical, l_additional, idx, ms;
char *r_addr, *r_name, *r_aliases, *r_alias = NULL, *r_addr_list;
size_t alen;
- struct address *a;
+ struct local_address *a;
unsigned n, c;
assert(canonical);
@@ -351,11 +352,11 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
int32_t *ttlp,
char **canonp) {
- _cleanup_free_ struct address *addresses = NULL;
+ _cleanup_free_ struct local_address *addresses = NULL;
const char *canonical, *additional = NULL;
_cleanup_free_ char *hn = NULL;
uint32_t local_address_ipv4;
- unsigned n_addresses = 0;
+ int n_addresses = 0;
assert(name);
assert(host);
@@ -389,7 +390,9 @@ enum nss_status _nss_myhostname_gethostbyname3_r(
return NSS_STATUS_NOTFOUND;
}
- acquire_addresses(&addresses, &n_addresses);
+ n_addresses = local_addresses(&addresses);
+ if (n_addresses < 0)
+ n_addresses = 0;
canonical = hn;
additional = n_addresses <= 0 && af == AF_INET6 ? "localhost" : NULL;
@@ -451,10 +454,11 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
const char *canonical = NULL, *additional = NULL;
uint32_t local_address_ipv4 = LOCALADDRESS_IPV4;
- _cleanup_free_ struct address *addresses = NULL;
+ _cleanup_free_ struct local_address *addresses = NULL;
_cleanup_free_ char *hn = NULL;
- unsigned n_addresses = 0, n;
- struct address *a;
+ int n_addresses = 0;
+ struct local_address *a;
+ unsigned n;
assert(addr);
assert(host);
@@ -492,9 +496,11 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
return NSS_STATUS_UNAVAIL;
}
- acquire_addresses(&addresses, &n_addresses);
+ n_addresses = local_addresses(&addresses);
+ if (n_addresses < 0)
+ n_addresses = 0;
- for (a = addresses, n = 0; n < n_addresses; n++, a++) {
+ for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) {
if (af != a->family)
continue;
diff --git a/src/shared/socket-util.h b/src/shared/socket-util.h
index 25c4a7e..8d521ae 100644
--- a/src/shared/socket-util.h
+++ b/src/shared/socket-util.h
@@ -118,3 +118,8 @@ int in_addr_prefix_intersect(unsigned family, const union in_addr_union *a, unsi
int in_addr_prefix_next(unsigned family, union in_addr_union *u, unsigned prefixlen);
int in_addr_to_string(unsigned family, const union in_addr_union *u, char **ret);
int in_addr_from_string(unsigned family, const char *s, union in_addr_union *ret);
+
+static inline size_t PROTO_ADDRESS_SIZE(int proto) {
+ assert(proto == AF_INET || proto == AF_INET6);
+ return proto == AF_INET6 ? 16 : 4;
+}
More information about the systemd-commits
mailing list