summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-12-21 22:06:22 +0100
committerMichael Biebl <biebl@debian.org>2018-12-21 22:06:22 +0100
commit6e866b331d7cd4a5e0759dd160dea6edabd3678e (patch)
tree4d24c1ffe4ae946f04d8910956090e8d13aecd9a /src/libsystemd-network
parentb012e92123bdc9fa10c2f079ec5bd9313b23e21a (diff)
downloadsystemd-6e866b331d7cd4a5e0759dd160dea6edabd3678e.tar.gz
New upstream version 240
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/dhcp-identifier.c140
-rw-r--r--src/libsystemd-network/dhcp-identifier.h17
-rw-r--r--src/libsystemd-network/dhcp-network.c30
-rw-r--r--src/libsystemd-network/dhcp-packet.c82
-rw-r--r--src/libsystemd-network/dhcp-server-internal.h4
-rw-r--r--src/libsystemd-network/dhcp6-internal.h8
-rw-r--r--src/libsystemd-network/dhcp6-lease-internal.h2
-rw-r--r--src/libsystemd-network/dhcp6-network.c14
-rw-r--r--src/libsystemd-network/dhcp6-option.c171
-rw-r--r--src/libsystemd-network/icmp6-util.c37
-rw-r--r--src/libsystemd-network/lldp-internal.h4
-rw-r--r--src/libsystemd-network/lldp-neighbor.c54
-rw-r--r--src/libsystemd-network/lldp-neighbor.h3
-rw-r--r--src/libsystemd-network/lldp-network.c1
-rw-r--r--src/libsystemd-network/lldp-network.h1
-rw-r--r--src/libsystemd-network/ndisc-internal.h3
-rw-r--r--src/libsystemd-network/ndisc-router.c29
-rw-r--r--src/libsystemd-network/network-internal.c51
-rw-r--r--src/libsystemd-network/network-internal.h8
-rw-r--r--src/libsystemd-network/radv-internal.h1
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c324
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c46
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c66
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c435
-rw-r--r--src/libsystemd-network/sd-dhcp6-lease.c56
-rw-r--r--src/libsystemd-network/sd-ipv4acd.c59
-rw-r--r--src/libsystemd-network/sd-ipv4ll.c23
-rw-r--r--src/libsystemd-network/sd-lldp.c111
-rw-r--r--src/libsystemd-network/sd-ndisc.c126
-rw-r--r--src/libsystemd-network/sd-radv.c208
-rw-r--r--src/libsystemd-network/test-acd.c5
-rw-r--r--src/libsystemd-network/test-dhcp-client.c43
-rw-r--r--src/libsystemd-network/test-dhcp-server.c10
-rw-r--r--src/libsystemd-network/test-dhcp6-client.c83
-rw-r--r--src/libsystemd-network/test-ipv4ll-manual.c5
-rw-r--r--src/libsystemd-network/test-ipv4ll.c7
-rw-r--r--src/libsystemd-network/test-lldp.c132
-rw-r--r--src/libsystemd-network/test-ndisc-ra.c9
-rw-r--r--src/libsystemd-network/test-ndisc-rs.c7
39 files changed, 1211 insertions, 1204 deletions
diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c
index 91c485c6c2..07496adaa3 100644
--- a/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libsystemd-network/dhcp-identifier.c
@@ -1,6 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
-#include "libudev.h"
+#include <linux/if_infiniband.h>
+#include <net/if_arp.h>
+
+#include "sd-device.h"
#include "sd-id128.h"
#include "dhcp-identifier.h"
@@ -8,19 +11,26 @@
#include "network-internal.h"
#include "siphash24.h"
#include "sparse-endian.h"
-#include "udev-util.h"
#include "virt.h"
-#define SYSTEMD_PEN 43793
-#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
+#define SYSTEMD_PEN 43793
+#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
+#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
+#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */
-int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
+int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict) {
struct duid d;
assert_cc(sizeof(d.raw) >= MAX_DUID_LEN);
if (duid_len > MAX_DUID_LEN)
return -EINVAL;
+ if (!strict) {
+ /* Strict validation is not requested. We only ensure that the
+ * DUID is not too long. */
+ return 0;
+ }
+
switch (duid_type) {
case DUID_TYPE_LLT:
if (duid_len <= sizeof(d.llt))
@@ -45,6 +55,56 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) {
return 0;
}
+int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
+ uint16_t time_from_2000y;
+
+ assert(duid);
+ assert(len);
+ assert(addr);
+
+ if (arp_type == ARPHRD_ETHER)
+ assert_return(addr_len == ETH_ALEN, -EINVAL);
+ else if (arp_type == ARPHRD_INFINIBAND)
+ assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+ else
+ return -EINVAL;
+
+ if (t < USEC_2000)
+ time_from_2000y = 0;
+ else
+ time_from_2000y = (uint16_t) (((t - USEC_2000) / USEC_PER_SEC) & 0xffffffff);
+
+ unaligned_write_be16(&duid->type, DUID_TYPE_LLT);
+ unaligned_write_be16(&duid->llt.htype, arp_type);
+ unaligned_write_be32(&duid->llt.time, time_from_2000y);
+ memcpy(duid->llt.haddr, addr, addr_len);
+
+ *len = sizeof(duid->type) + sizeof(duid->llt.htype) + sizeof(duid->llt.time) + addr_len;
+
+ return 0;
+}
+
+int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len) {
+ assert(duid);
+ assert(len);
+ assert(addr);
+
+ if (arp_type == ARPHRD_ETHER)
+ assert_return(addr_len == ETH_ALEN, -EINVAL);
+ else if (arp_type == ARPHRD_INFINIBAND)
+ assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+ else
+ return -EINVAL;
+
+ unaligned_write_be16(&duid->type, DUID_TYPE_LL);
+ unaligned_write_be16(&duid->ll.htype, arp_type);
+ memcpy(duid->ll.haddr, addr, addr_len);
+
+ *len = sizeof(duid->type) + sizeof(duid->ll.htype) + addr_len;
+
+ return 0;
+}
+
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
sd_id128_t machine_id;
uint64_t hash;
@@ -54,8 +114,13 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
assert(len);
r = sd_id128_get_machine(&machine_id);
- if (r < 0)
+ if (r < 0) {
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ machine_id = SD_ID128_MAKE(01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10);
+#else
return r;
+#endif
+ }
unaligned_write_be16(&duid->type, DUID_TYPE_EN);
unaligned_write_be32(&duid->en.pen, SYSTEMD_PEN);
@@ -63,33 +128,56 @@ int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len) {
*len = sizeof(duid->type) + sizeof(duid->en);
/* a bit of snake-oil perhaps, but no need to expose the machine-id
- directly; duid->en.id might not be aligned, so we need to copy */
+ * directly; duid->en.id might not be aligned, so we need to copy */
hash = htole64(siphash24(&machine_id, sizeof(machine_id), HASH_KEY.bytes));
memcpy(duid->en.id, &hash, sizeof(duid->en.id));
return 0;
}
-int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id) {
- /* name is a pointer to memory in the udev_device struct, so must
- have the same scope */
- _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
+int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len) {
+ sd_id128_t machine_id;
+ int r;
+
+ assert(duid);
+ assert(len);
+
+ r = sd_id128_get_machine_app_specific(APPLICATION_ID, &machine_id);
+ if (r < 0)
+ return r;
+
+ unaligned_write_be16(&duid->type, DUID_TYPE_UUID);
+ memcpy(&duid->raw.data, &machine_id, sizeof(machine_id));
+
+ *len = sizeof(duid->type) + sizeof(machine_id);
+
+ return 0;
+}
+
+int dhcp_identifier_set_iaid(
+ int ifindex,
+ const uint8_t *mac,
+ size_t mac_len,
+ bool legacy_unstable_byteorder,
+ void *_id) {
+ /* name is a pointer to memory in the sd_device struct, so must
+ * have the same scope */
+ _cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *name = NULL;
uint64_t id;
+ uint32_t id32;
if (detect_container() <= 0) {
/* not in a container, udev will be around */
- _cleanup_(udev_unrefp) struct udev *udev;
char ifindex_str[2 + DECIMAL_STR_MAX(int)];
-
- udev = udev_new();
- if (!udev)
- return -ENOMEM;
+ int r;
sprintf(ifindex_str, "n%d", ifindex);
- device = udev_device_new_from_device_id(udev, ifindex_str);
- if (device) {
- if (udev_device_get_is_initialized(device) <= 0)
+ if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
+ r = sd_device_get_is_initialized(device);
+ if (r < 0)
+ return r;
+ if (r == 0)
/* not yet ready */
return -EBUSY;
@@ -103,10 +191,18 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_i
/* fall back to MAC address if no predictable name available */
id = siphash24(mac, mac_len, HASH_KEY.bytes);
- id = htole64(id);
+ id32 = (id & 0xffffffff) ^ (id >> 32);
- /* fold into 32 bits */
- unaligned_write_be32(_id, (id & 0xffffffff) ^ (id >> 32));
+ if (legacy_unstable_byteorder)
+ /* for historical reasons (a bug), the bits were swapped and thus
+ * the result was endianness dependant. Preserve that behavior. */
+ id32 = __bswap_32(id32);
+ else
+ /* the fixed behavior returns a stable byte order. Since LE is expected
+ * to be more common, swap the bytes on LE to give the same as legacy
+ * behavior. */
+ id32 = be32toh(id32);
+ unaligned_write_ne32(_id, id32);
return 0;
}
diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h
index b92c580d40..b3115125d9 100644
--- a/src/libsystemd-network/dhcp-identifier.h
+++ b/src/libsystemd-network/dhcp-identifier.h
@@ -1,11 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-
#include "sd-id128.h"
#include "macro.h"
#include "sparse-endian.h"
+#include "time-util.h"
#include "unaligned.h"
typedef enum DUIDType {
@@ -28,18 +28,18 @@ struct duid {
union {
struct {
/* DUID_TYPE_LLT */
- uint16_t htype;
- uint32_t time;
+ be16_t htype;
+ be32_t time;
uint8_t haddr[0];
} _packed_ llt;
struct {
/* DUID_TYPE_EN */
- uint32_t pen;
+ be32_t pen;
uint8_t id[8];
} _packed_ en;
struct {
/* DUID_TYPE_LL */
- int16_t htype;
+ be16_t htype;
uint8_t haddr[0];
} _packed_ ll;
struct {
@@ -52,6 +52,9 @@ struct duid {
};
} _packed_;
-int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len);
+int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict);
+int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
+int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
-int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, void *_id);
+int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len);
+int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, void *_id);
diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c
index 77638338f2..0e5b4147a9 100644
--- a/src/libsystemd-network/dhcp-network.c
+++ b/src/libsystemd-network/dhcp-network.c
@@ -78,7 +78,7 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
.filter = filter
};
_cleanup_close_ int s = -1;
- int r, on = 1;
+ int r;
assert(ifindex > 0);
assert(link);
@@ -87,9 +87,9 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
if (s < 0)
return -errno;
- r = setsockopt(s, SOL_PACKET, PACKET_AUXDATA, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_PACKET, PACKET_AUXDATA, true);
if (r < 0)
- return -errno;
+ return r;
r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
if (r < 0)
@@ -126,8 +126,6 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
const uint8_t *bcast_addr = NULL;
uint8_t dhcp_hlen = 0;
- assert_return(mac_addr_len > 0, -EINVAL);
-
if (arp_type == ARPHRD_ETHER) {
assert_return(mac_addr_len == ETH_ALEN, -EINVAL);
memcpy(&eth_mac, mac_addr, ETH_ALEN);
@@ -151,19 +149,19 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
};
_cleanup_close_ int s = -1;
char ifname[IF_NAMESIZE] = "";
- int r, on = 1, tos = IPTOS_CLASS_CS6;
+ int r;
s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (s < 0)
return -errno;
- r = setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
+ r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
- return -errno;
+ return r;
if (ifindex > 0) {
if (if_indextoname(ifindex, ifname) == 0)
@@ -175,18 +173,18 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
}
if (address == INADDR_ANY) {
- r = setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_BROADCAST, true);
if (r < 0)
- return -errno;
+ return r;
} else {
- r = setsockopt(s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IP, IP_FREEBIND, true);
if (r < 0)
- return -errno;
+ return r;
}
r = bind(s, &src.sa, sizeof(src.in));
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index d29cd06cb1..ad5f8e267a 100644
--- a/src/libsystemd-network/dhcp-packet.c
+++ b/src/libsystemd-network/dhcp-packet.c
@@ -106,70 +106,62 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, ui
/* IP */
- if (packet->ip.version != IPVERSION) {
- log_debug("ignoring packet: not IPv4");
- return -EINVAL;
- }
+ if (packet->ip.version != IPVERSION)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: not IPv4");
- if (packet->ip.ihl < 5) {
- log_debug("ignoring packet: IPv4 IHL (%u words) invalid",
- packet->ip.ihl);
- return -EINVAL;
- }
+ if (packet->ip.ihl < 5)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: IPv4 IHL (%u words) invalid",
+ packet->ip.ihl);
hdrlen = packet->ip.ihl * 4;
- if (hdrlen < 20) {
- log_debug("ignoring packet: IPv4 IHL (%zu bytes) "
- "smaller than minimum (20 bytes)", hdrlen);
- return -EINVAL;
- }
-
- if (len < hdrlen) {
- log_debug("ignoring packet: packet (%zu bytes) "
- "smaller than expected (%zu) by IP header", len,
- hdrlen);
- return -EINVAL;
- }
+ if (hdrlen < 20)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: IPv4 IHL (%zu bytes) "
+ "smaller than minimum (20 bytes)",
+ hdrlen);
+
+ if (len < hdrlen)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: packet (%zu bytes) "
+ "smaller than expected (%zu) by IP header",
+ len, hdrlen);
/* UDP */
- if (packet->ip.protocol != IPPROTO_UDP) {
- log_debug("ignoring packet: not UDP");
- return -EINVAL;
- }
+ if (packet->ip.protocol != IPPROTO_UDP)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: not UDP");
- if (len < hdrlen + be16toh(packet->udp.len)) {
- log_debug("ignoring packet: packet (%zu bytes) "
- "smaller than expected (%zu) by UDP header", len,
- hdrlen + be16toh(packet->udp.len));
- return -EINVAL;
- }
+ if (len < hdrlen + be16toh(packet->udp.len))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: packet (%zu bytes) "
+ "smaller than expected (%zu) by UDP header",
+ len, hdrlen + be16toh(packet->udp.len));
- if (be16toh(packet->udp.dest) != port) {
- log_debug("ignoring packet: to port %u, which "
- "is not the DHCP client port (%u)",
- be16toh(packet->udp.dest), port);
- return -EINVAL;
- }
+ if (be16toh(packet->udp.dest) != port)
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: to port %u, which "
+ "is not the DHCP client port (%u)",
+ be16toh(packet->udp.dest), port);
/* checksums - computing these is relatively expensive, so only do it
if all the other checks have passed
*/
- if (dhcp_packet_checksum((uint8_t*)&packet->ip, hdrlen)) {
- log_debug("ignoring packet: invalid IP checksum");
- return -EINVAL;
- }
+ if (dhcp_packet_checksum((uint8_t*)&packet->ip, hdrlen))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: invalid IP checksum");
if (checksum && packet->udp.check) {
packet->ip.check = packet->udp.len;
packet->ip.ttl = 0;
if (dhcp_packet_checksum((uint8_t*)&packet->ip.ttl,
- be16toh(packet->udp.len) + 12)) {
- log_debug("ignoring packet: invalid UDP checksum");
- return -EINVAL;
- }
+ be16toh(packet->udp.len) + 12))
+ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+ "ignoring packet: invalid UDP checksum");
}
return 0;
diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h
index 6355128ddb..8a7c5bc28f 100644
--- a/src/libsystemd-network/dhcp-server-internal.h
+++ b/src/libsystemd-network/dhcp-server-internal.h
@@ -78,5 +78,5 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
DHCPRequest *req, DHCPPacket *packet,
int type, size_t optoffset);
-void client_id_hash_func(const void *p, struct siphash *state);
-int client_id_compare_func(const void *_a, const void *_b);
+void client_id_hash_func(const DHCPClientId *p, struct siphash *state);
+int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b);
diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h
index f1cbd6a4f1..157fc0aadd 100644
--- a/src/libsystemd-network/dhcp6-internal.h
+++ b/src/libsystemd-network/dhcp6-internal.h
@@ -73,8 +73,6 @@ struct DHCP6IA {
struct ia_pd ia_pd;
struct ia_ta ia_ta;
};
- sd_event_source *timeout_t1;
- sd_event_source *timeout_t2;
LIST_HEAD(DHCP6Address, addresses);
};
@@ -86,12 +84,12 @@ typedef struct DHCP6IA DHCP6IA;
int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
size_t optlen, const void *optval);
-int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia);
-int dhcp6_option_append_pd(uint8_t *buf, size_t len, DHCP6IA *pd);
+int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
+int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd);
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);
-int dhcp6_option_parse_status(DHCP6Option *option);
+int dhcp6_option_parse_status(DHCP6Option *option, size_t len);
int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia);
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
struct in6_addr **addrs, size_t count,
diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h
index ff0b0f00ce..e004f48b4e 100644
--- a/src/libsystemd-network/dhcp6-lease-internal.h
+++ b/src/libsystemd-network/dhcp6-lease-internal.h
@@ -37,7 +37,6 @@ struct sd_dhcp6_lease {
size_t ntp_fqdn_count;
};
-int dhcp6_lease_clear_timers(DHCP6IA *ia);
int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire);
DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia);
@@ -50,6 +49,7 @@ int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease);
int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit);
int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
+int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
int dhcp6_lease_set_dns(sd_dhcp6_lease *lease, uint8_t *optval, size_t optlen);
int dhcp6_lease_set_domains(sd_dhcp6_lease *lease, uint8_t *optval,
diff --git a/src/libsystemd-network/dhcp6-network.c b/src/libsystemd-network/dhcp6-network.c
index 78cd383669..580f43ba40 100644
--- a/src/libsystemd-network/dhcp6-network.c
+++ b/src/libsystemd-network/dhcp6-network.c
@@ -25,7 +25,7 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
.in6.sin6_scope_id = index,
};
_cleanup_close_ int s = -1;
- int r, off = 0, on = 1;
+ int r;
assert(index > 0);
assert(local_address);
@@ -36,17 +36,17 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
if (s < 0)
return -errno;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
- return -errno;
+ return r;
r = bind(s, &src.sa, sizeof(src.in6));
if (r < 0)
diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c
index 18196b1257..a2aac9a793 100644
--- a/src/libsystemd-network/dhcp6-option.c
+++ b/src/libsystemd-network/dhcp6-option.c
@@ -37,9 +37,9 @@ typedef struct DHCP6PDPrefixOption {
uint8_t options[];
} _packed_ DHCP6PDPrefixOption;
-#define DHCP6_OPTION_IA_NA_LEN (sizeof(struct ia_na))
-#define DHCP6_OPTION_IA_PD_LEN (sizeof(struct ia_pd))
-#define DHCP6_OPTION_IA_TA_LEN (sizeof(struct ia_ta))
+#define DHCP6_OPTION_IA_NA_LEN (sizeof(struct ia_na))
+#define DHCP6_OPTION_IA_PD_LEN (sizeof(struct ia_pd))
+#define DHCP6_OPTION_IA_TA_LEN (sizeof(struct ia_ta))
static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode,
size_t optlen) {
@@ -49,14 +49,14 @@ static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode,
assert_return(*buf, -EINVAL);
assert_return(buflen, -EINVAL);
- if (optlen > 0xffff || *buflen < optlen + sizeof(DHCP6Option))
+ if (optlen > 0xffff || *buflen < optlen + offsetof(DHCP6Option, data))
return -ENOBUFS;
option->code = htobe16(optcode);
option->len = htobe16(optlen);
- *buf += sizeof(DHCP6Option);
- *buflen -= sizeof(DHCP6Option);
+ *buf += offsetof(DHCP6Option, data);
+ *buflen -= offsetof(DHCP6Option, data);
return 0;
}
@@ -79,14 +79,17 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
return 0;
}
-int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
+int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
uint16_t len;
uint8_t *ia_hdr;
size_t iaid_offset, ia_buflen, ia_addrlen = 0;
DHCP6Address *addr;
int r;
- assert_return(buf && *buf && buflen && ia, -EINVAL);
+ assert_return(buf, -EINVAL);
+ assert_return(*buf, -EINVAL);
+ assert_return(buflen, -EINVAL);
+ assert_return(ia, -EINVAL);
switch (ia->type) {
case SD_DHCP6_OPTION_IA_NA:
@@ -103,14 +106,14 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
return -EINVAL;
}
- if (*buflen < len)
+ if (*buflen < offsetof(DHCP6Option, data) + len)
return -ENOBUFS;
ia_hdr = *buf;
ia_buflen = *buflen;
- *buf += sizeof(DHCP6Option);
- *buflen -= sizeof(DHCP6Option);
+ *buf += offsetof(DHCP6Option, data);
+ *buflen -= offsetof(DHCP6Option, data);
memcpy(*buf, (char*) ia + iaid_offset, len);
@@ -128,7 +131,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) {
*buf += sizeof(addr->iaaddr);
*buflen -= sizeof(addr->iaaddr);
- ia_addrlen += sizeof(DHCP6Option) + sizeof(addr->iaaddr);
+ ia_addrlen += offsetof(DHCP6Option, data) + sizeof(addr->iaaddr);
}
r = option_append_hdr(&ia_hdr, &ia_buflen, ia->type, len + ia_addrlen);
@@ -165,7 +168,7 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
return r;
}
-int dhcp6_option_append_pd(uint8_t *buf, size_t len, DHCP6IA *pd) {
+int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) {
DHCP6Option *option = (DHCP6Option *)buf;
size_t i = sizeof(*option) + sizeof(pd->ia_pd);
DHCP6Address *prefix;
@@ -210,7 +213,7 @@ static int option_parse_hdr(uint8_t **buf, size_t *buflen, uint16_t *optcode, si
assert_return(optcode, -EINVAL);
assert_return(optlen, -EINVAL);
- if (*buflen < sizeof(DHCP6Option))
+ if (*buflen < offsetof(DHCP6Option, data))
return -ENOMSG;
len = be16toh(option->len);
@@ -247,10 +250,11 @@ int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
return 0;
}
-int dhcp6_option_parse_status(DHCP6Option *option) {
+int dhcp6_option_parse_status(DHCP6Option *option, size_t len) {
DHCP6StatusOption *statusopt = (DHCP6StatusOption *)option;
- if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*statusopt))
+ if (len < sizeof(DHCP6StatusOption) ||
+ be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(DHCP6StatusOption))
return -ENOBUFS;
return be16toh(statusopt->status);
@@ -263,7 +267,7 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia,
uint32_t lt_valid, lt_pref;
int r;
- if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*addr_option))
+ if (be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(*addr_option))
return -ENOBUFS;
lt_valid = be32toh(addr_option->iaaddr.lifetime_valid);
@@ -276,8 +280,8 @@ static int dhcp6_option_parse_address(DHCP6Option *option, DHCP6IA *ia,
return 0;
}
- if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*addr_option)) {
- r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options);
+ if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*addr_option)) {
+ r = dhcp6_option_parse_status((DHCP6Option *)addr_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*addr_option));
if (r != 0)
return r < 0 ? r: 0;
}
@@ -303,7 +307,7 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
uint32_t lt_valid, lt_pref;
int r;
- if (be16toh(option->len) + sizeof(DHCP6Option) < sizeof(*pdprefix_option))
+ if (be16toh(option->len) + offsetof(DHCP6Option, data) < sizeof(*pdprefix_option))
return -ENOBUFS;
lt_valid = be32toh(pdprefix_option->iapdprefix.lifetime_valid);
@@ -316,8 +320,8 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia,
return 0;
}
- if (be16toh(option->len) + sizeof(DHCP6Option) > sizeof(*pdprefix_option)) {
- r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options);
+ if (be16toh(option->len) + offsetof(DHCP6Option, data) > sizeof(*pdprefix_option)) {
+ r = dhcp6_option_parse_status((DHCP6Option *)pdprefix_option->options, be16toh(option->len) + offsetof(DHCP6Option, data) - sizeof(*pdprefix_option));
if (r != 0)
return r < 0 ? r: 0;
}
@@ -353,10 +357,8 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
switch (iatype) {
case SD_DHCP6_OPTION_IA_NA:
- if (len < DHCP6_OPTION_IA_NA_LEN) {
- r = -ENOBUFS;
- goto error;
- }
+ if (len < DHCP6_OPTION_IA_NA_LEN)
+ return -ENOBUFS;
iaaddr_offset = DHCP6_OPTION_IA_NA_LEN;
memcpy(&ia->ia_na, iaoption->data, sizeof(ia->ia_na));
@@ -367,18 +369,15 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
if (lt_t1 && lt_t2 && lt_t1 > lt_t2) {
log_dhcp6_client(client, "IA NA T1 %ds > T2 %ds",
lt_t1, lt_t2);
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
break;
case SD_DHCP6_OPTION_IA_PD:
- if (len < sizeof(ia->ia_pd)) {
- r = -ENOBUFS;
- goto error;
- }
+ if (len < sizeof(ia->ia_pd))
+ return -ENOBUFS;
iaaddr_offset = sizeof(ia->ia_pd);
memcpy(&ia->ia_pd, iaoption->data, sizeof(ia->ia_pd));
@@ -389,17 +388,14 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
if (lt_t1 && lt_t2 && lt_t1 > lt_t2) {
log_dhcp6_client(client, "IA PD T1 %ds > T2 %ds",
lt_t1, lt_t2);
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
break;
case SD_DHCP6_OPTION_IA_TA:
- if (len < DHCP6_OPTION_IA_TA_LEN) {
- r = -ENOBUFS;
- goto error;
- }
+ if (len < DHCP6_OPTION_IA_TA_LEN)
+ return -ENOBUFS;
iaaddr_offset = DHCP6_OPTION_IA_TA_LEN;
memcpy(&ia->ia_ta.id, iaoption->data, sizeof(ia->ia_ta));
@@ -407,8 +403,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
break;
default:
- r = -ENOMSG;
- goto error;
+ return -ENOMSG;
}
ia->type = iatype;
@@ -417,10 +412,8 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
while (i < len) {
DHCP6Option *option = (DHCP6Option *)&iaoption->data[i];
- if (len < i + sizeof(*option) || len < i + sizeof(*option) + be16toh(option->len)) {
- r = -ENOBUFS;
- goto error;
- }
+ if (len < i + sizeof(*option) || len < i + sizeof(*option) + be16toh(option->len))
+ return -ENOBUFS;
opt = be16toh(option->code);
optlen = be16toh(option->len);
@@ -430,13 +423,12 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_NA, SD_DHCP6_OPTION_IA_TA)) {
log_dhcp6_client(client, "IA Address option not in IA NA or TA option");
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
r = dhcp6_option_parse_address(option, ia, &lt_valid);
if (r < 0)
- goto error;
+ return r;
if (lt_valid < lt_min)
lt_min = lt_valid;
@@ -447,13 +439,12 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
if (!IN_SET(ia->type, SD_DHCP6_OPTION_IA_PD)) {
log_dhcp6_client(client, "IA PD Prefix option not in IA PD option");
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
r = dhcp6_option_parse_pdprefix(option, ia, &lt_valid);
if (r < 0)
- goto error;
+ return r;
if (lt_valid < lt_min)
lt_min = lt_valid;
@@ -462,15 +453,14 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
case SD_DHCP6_OPTION_STATUS_CODE:
- status = dhcp6_option_parse_status(option);
- if (status) {
+ status = dhcp6_option_parse_status(option, optlen + offsetof(DHCP6Option, data));
+ if (status < 0)
+ return status;
+ if (status > 0) {
log_dhcp6_client(client, "IA status %d",
status);
- dhcp6_lease_free_ia(ia);
-
- r = -EINVAL;
- goto error;
+ return -EINVAL;
}
break;
@@ -514,8 +504,7 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia) {
break;
}
-error:
- return r;
+ return 0;
}
int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen,
@@ -550,6 +539,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
bool first = true;
for (;;) {
+ const char *label;
uint8_t c;
c = optval[pos++];
@@ -557,47 +547,41 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
if (c == 0)
/* End of name */
break;
- else if (c <= 63) {
- const char *label;
-
- /* Literal label */
- label = (const char *)&optval[pos];
- pos += c;
- if (pos > optlen)
- return -EMSGSIZE;
-
- if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (first)
- first = false;
- else
- ret[n++] = '.';
-
- r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
- if (r < 0)
- goto fail;
-
- n += r;
- continue;
- } else {
- r = -EBADMSG;
- goto fail;
- }
- }
+ if (c > 63)
+ return -EBADMSG;
+
+ /* Literal label */
+ label = (const char *)&optval[pos];
+ pos += c;
+ if (pos >= optlen)
+ return -EMSGSIZE;
+
+ if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
+ return -ENOMEM;
+
+ if (first)
+ first = false;
+ else
+ ret[n++] = '.';
- if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
- r = -ENOMEM;
- goto fail;
+ r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
+ if (r < 0)
+ return r;
+
+ n += r;
}
+ if (n == 0)
+ continue;
+
+ if (!GREEDY_REALLOC(ret, allocated, n + 1))
+ return -ENOMEM;
+
ret[n] = 0;
r = strv_extend(&names, ret);
if (r < 0)
- goto fail;
+ return r;
idx++;
}
@@ -605,7 +589,4 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
*str_arr = TAKE_PTR(names);
return idx;
-
-fail:
- return r;
}
diff --git a/src/libsystemd-network/icmp6-util.c b/src/libsystemd-network/icmp6-util.c
index 736df222f0..e535b12cda 100644
--- a/src/libsystemd-network/icmp6-util.c
+++ b/src/libsystemd-network/icmp6-util.c
@@ -17,8 +17,9 @@
#include "fd-util.h"
#include "icmp6-util.h"
-#include "socket-util.h"
#include "in-addr-util.h"
+#include "io-util.h"
+#include "socket-util.h"
#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
@@ -33,7 +34,6 @@ static int icmp6_bind_router_message(const struct icmp6_filter *filter,
int index = mreq->ipv6mr_interface;
_cleanup_close_ int s = -1;
char ifname[IF_NAMESIZE] = "";
- static const int zero = 0, one = 1, hops = 255;
int r;
s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
@@ -52,29 +52,29 @@ static int icmp6_bind_router_message(const struct icmp6_filter *filter,
IPV6_PKTINFO socket option also applies for ICMPv6 multicast.
Empirical experiments indicates otherwise and therefore an
IPV6_MULTICAST_IF socket option is used here instead */
- r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, index);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 255);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof(hops));
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 255);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
+ r = setsockopt_int(s, SOL_IPV6, IPV6_RECVHOPLIMIT, true);
if (r < 0)
- return -errno;
+ return r;
- r = setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
+ r = setsockopt_int(s, SOL_SOCKET, SO_TIMESTAMP, true);
if (r < 0)
- return -errno;
+ return r;
if (if_indextoname(index, ifname) == 0)
return -errno;
@@ -170,16 +170,11 @@ int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst,
struct cmsghdr *cmsg;
ssize_t len;
- iov.iov_base = buffer;
- iov.iov_len = size;
+ iov = IOVEC_MAKE(buffer, size);
len = recvmsg(fd, &msg, MSG_DONTWAIT);
- if (len < 0) {
- if (IN_SET(errno, EAGAIN, EINTR))
- return 0;
-
+ if (len < 0)
return -errno;
- }
if ((size_t) len != size)
return -EINVAL;
diff --git a/src/libsystemd-network/lldp-internal.h b/src/libsystemd-network/lldp-internal.h
index 7c10a67a35..88b54933c3 100644
--- a/src/libsystemd-network/lldp-internal.h
+++ b/src/libsystemd-network/lldp-internal.h
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-
#include "sd-event.h"
#include "sd-lldp.h"
@@ -35,3 +34,6 @@ struct sd_lldp {
#define log_lldp_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "LLDP: " fmt, ##__VA_ARGS__)
#define log_lldp(fmt, ...) log_lldp_errno(0, fmt, ##__VA_ARGS__)
+
+const char* lldp_event_to_string(sd_lldp_event e) _const_;
+sd_lldp_event lldp_event_from_string(const char *s) _pure_;
diff --git a/src/libsystemd-network/lldp-neighbor.c b/src/libsystemd-network/lldp-neighbor.c
index 5dcb051373..43fc8e03c0 100644
--- a/src/libsystemd-network/lldp-neighbor.c
+++ b/src/libsystemd-network/lldp-neighbor.c
@@ -7,58 +7,29 @@
#include "in-addr-util.h"
#include "lldp-internal.h"
#include "lldp-neighbor.h"
+#include "missing.h"
#include "unaligned.h"
+#include "util.h"
-static void lldp_neighbor_id_hash_func(const void *p, struct siphash *state) {
- const LLDPNeighborID *id = p;
-
+static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) {
siphash24_compress(id->chassis_id, id->chassis_id_size, state);
siphash24_compress(&id->chassis_id_size, sizeof(id->chassis_id_size), state);
siphash24_compress(id->port_id, id->port_id_size, state);
siphash24_compress(&id->port_id_size, sizeof(id->port_id_size), state);
}
-static int lldp_neighbor_id_compare_func(const void *a, const void *b) {
- const LLDPNeighborID *x = a, *y = b;
- int r;
-
- r = memcmp(x->chassis_id, y->chassis_id, MIN(x->chassis_id_size, y->chassis_id_size));
- if (r != 0)
- return r;
-
- if (x->chassis_id_size < y->chassis_id_size)
- return -1;
-
- if (x->chassis_id_size > y->chassis_id_size)
- return 1;
-
- r = memcmp(x->port_id, y->port_id, MIN(x->port_id_size, y->port_id_size));
- if (r != 0)
- return r;
-
- if (x->port_id_size < y->port_id_size)
- return -1;
- if (x->port_id_size > y->port_id_size)
- return 1;
-
- return 0;
+int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y) {
+ return memcmp_nn(x->chassis_id, x->chassis_id_size, y->chassis_id, y->chassis_id_size)
+ ?: memcmp_nn(x->port_id, x->port_id_size, y->port_id, y->port_id_size);
}
-const struct hash_ops lldp_neighbor_id_hash_ops = {
- .hash = lldp_neighbor_id_hash_func,
- .compare = lldp_neighbor_id_compare_func
-};
+DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(lldp_neighbor_hash_ops, LLDPNeighborID, lldp_neighbor_id_hash_func, lldp_neighbor_id_compare_func,
+ sd_lldp_neighbor, lldp_neighbor_unlink);
int lldp_neighbor_prioq_compare_func(const void *a, const void *b) {
const sd_lldp_neighbor *x = a, *y = b;
- if (x->until < y->until)
- return -1;
-
- if (x->until > y->until)
- return 1;
-
- return 0;
+ return CMP(x->until, y->until);
}
_public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) {
@@ -111,7 +82,12 @@ sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n) {
if (!n->lldp)
return NULL;
- assert_se(hashmap_remove(n->lldp->neighbor_by_id, &n->id) == n);
+ /* Only remove the neighbor object from the hash table if it's in there, don't complain if it isn't. This is
+ * because we are used as destructor call for hashmap_clear() and thus sometimes are called to de-register
+ * ourselves from the hashtable and sometimes are called after we already are de-registered. */
+
+ (void) hashmap_remove_value(n->lldp->neighbor_by_id, &n->id, n);
+
assert_se(prioq_remove(n->lldp->neighbor_by_expiry, n, &n->prioq_idx) >= 0);
n->lldp = NULL;
diff --git a/src/libsystemd-network/lldp-neighbor.h b/src/libsystemd-network/lldp-neighbor.h
index 494bc51760..62dbff42ca 100644
--- a/src/libsystemd-network/lldp-neighbor.h
+++ b/src/libsystemd-network/lldp-neighbor.h
@@ -80,7 +80,8 @@ static inline void* LLDP_NEIGHBOR_TLV_DATA(const sd_lldp_neighbor *n) {
return ((uint8_t*) LLDP_NEIGHBOR_RAW(n)) + n->rindex + 2;
}
-extern const struct hash_ops lldp_neighbor_id_hash_ops;
+extern const struct hash_ops lldp_neighbor_hash_ops;
+int lldp_neighbor_id_compare_func(const LLDPNeighborID *x, const LLDPNeighborID *y);
int lldp_neighbor_prioq_compare_func(const void *a, const void *b);
sd_lldp_neighbor *lldp_neighbor_unlink(sd_lldp_neighbor *n);
diff --git a/src/libsystemd-network/lldp-network.c b/src/libsystemd-network/lldp-network.c
index a4020d1e19..870584c0db 100644
--- a/src/libsystemd-network/lldp-network.c
+++ b/src/libsystemd-network/lldp-network.c
@@ -5,6 +5,7 @@
#include "fd-util.h"
#include "lldp-network.h"
+#include "missing.h"
#include "socket-util.h"
int lldp_network_bind_raw_socket(int ifindex) {
diff --git a/src/libsystemd-network/lldp-network.h b/src/libsystemd-network/lldp-network.h
index 914139793c..e4ed2898a5 100644
--- a/src/libsystemd-network/lldp-network.h
+++ b/src/libsystemd-network/lldp-network.h
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-
#include "sd-event.h"
int lldp_network_bind_raw_socket(int ifindex);
diff --git a/src/libsystemd-network/ndisc-internal.h b/src/libsystemd-network/ndisc-internal.h
index fdabbc1b0e..0c04fea8e5 100644
--- a/src/libsystemd-network/ndisc-internal.h
+++ b/src/libsystemd-network/ndisc-internal.h
@@ -38,3 +38,6 @@ struct sd_ndisc {
#define log_ndisc_errno(error, fmt, ...) log_internal(LOG_DEBUG, error, __FILE__, __LINE__, __func__, "NDISC: " fmt, ##__VA_ARGS__)
#define log_ndisc(fmt, ...) log_ndisc_errno(0, fmt, ##__VA_ARGS__)
+
+const char* ndisc_event_to_string(sd_ndisc_event e) _const_;
+sd_ndisc_event ndisc_event_from_string(const char *s) _pure_;
diff --git a/src/libsystemd-network/ndisc-router.c b/src/libsystemd-network/ndisc-router.c
index 25b693a458..6935311b9a 100644
--- a/src/libsystemd-network/ndisc-router.c
+++ b/src/libsystemd-network/ndisc-router.c
@@ -15,28 +15,7 @@
#include "ndisc-router.h"
#include "strv.h"
-_public_ sd_ndisc_router* sd_ndisc_router_ref(sd_ndisc_router *rt) {
- if (!rt)
- return NULL;
-
- assert(rt->n_ref > 0);
- rt->n_ref++;
-
- return rt;
-}
-
-_public_ sd_ndisc_router* sd_ndisc_router_unref(sd_ndisc_router *rt) {
- if (!rt)
- return NULL;
-
- assert(rt->n_ref > 0);
- rt->n_ref--;
-
- if (rt->n_ref > 0)
- return NULL;
-
- return mfree(rt);
-}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc_router, sd_ndisc_router, mfree);
sd_ndisc_router *ndisc_router_new(size_t raw_size) {
sd_ndisc_router *rt;
@@ -189,7 +168,7 @@ int ndisc_router_parse(sd_ndisc_router *rt) {
if (has_mtu) {
log_ndisc("MTU option specified twice, ignoring.");
- continue;
+ break;
}
if (length != 8) {
@@ -230,7 +209,7 @@ int ndisc_router_parse(sd_ndisc_router *rt) {
if (has_flag_extension) {
log_ndisc("Flags extension option specified twice, ignoring.");
- continue;
+ break;
}
if (length < 1*8) {
@@ -697,7 +676,7 @@ _public_ int sd_ndisc_router_dnssl_get_domains(sd_ndisc_router *rt, char ***ret)
_cleanup_free_ char *normalized = NULL;
e[n] = 0;
- r = dns_name_normalize(e, &normalized);
+ r = dns_name_normalize(e, 0, &normalized);
if (r < 0)
return r;
diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c
index 0849b44ee2..b3b134d650 100644
--- a/src/libsystemd-network/network-internal.c
+++ b/src/libsystemd-network/network-internal.c
@@ -23,24 +23,22 @@
#include "utf8.h"
#include "util.h"
-const char *net_get_name(struct udev_device *device) {
+const char *net_get_name(sd_device *device) {
const char *name, *field;
assert(device);
/* fetch some persistent data unique (on this machine) to this device */
- FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") {
- name = udev_device_get_property_value(device, field);
- if (name)
+ FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC")
+ if (sd_device_get_property_value(device, field, &name) >= 0)
return name;
- }
return NULL;
}
#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a)
-int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result) {
+int net_get_unique_predictable_data(sd_device *device, uint64_t *result) {
size_t l, sz = 0;
const char *name = NULL;
int r;
@@ -124,7 +122,7 @@ bool net_match_config(Set *match_mac,
if (match_arch && condition_test(match_arch) <= 0)
return false;
- if (match_mac && dev_mac && !set_contains(match_mac, dev_mac))
+ if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac)))
return false;
if (!net_condition_test_strv(match_paths, dev_path))
@@ -257,11 +255,10 @@ int config_parse_ifalias(const char *unit,
return 0;
}
- free(*s);
- if (*n)
- *s = TAKE_PTR(n);
+ if (isempty(n))
+ *s = mfree(*s);
else
- *s = NULL;
+ free_and_replace(*s, n);
return 0;
}
@@ -296,7 +293,7 @@ int config_parse_hwaddr(const char *unit,
return 0;
}
- *hwaddr = TAKE_PTR(n);
+ free_and_replace(*hwaddr, n);
return 0;
}
@@ -374,36 +371,6 @@ int config_parse_hwaddrs(const char *unit,
return 0;
}
-int config_parse_iaid(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
- uint32_t iaid;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- r = safe_atou32(rvalue, &iaid);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Unable to read IAID, ignoring assignment: %s", rvalue);
- return 0;
- }
-
- *((uint32_t *)data) = iaid;
-
- return 0;
-}
-
int config_parse_bridge_port_priority(
const char *unit,
const char *filename,
diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h
index 883f34b95c..0c8da848c1 100644
--- a/src/libsystemd-network/network-internal.h
+++ b/src/libsystemd-network/network-internal.h
@@ -1,15 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
-
#include <stdbool.h>
+#include "sd-device.h"
#include "sd-dhcp-lease.h"
#include "condition.h"
#include "conf-parser.h"
#include "set.h"
-#include "udev.h"
#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128
#define LINK_BRIDGE_PORT_PRIORITY_MAX 63
@@ -36,11 +35,10 @@ CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
-CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority);
-int net_get_unique_predictable_data(struct udev_device *device, uint64_t *result);
-const char *net_get_name(struct udev_device *device);
+int net_get_unique_predictable_data(sd_device *device, uint64_t *result);
+const char *net_get_name(sd_device *device);
void serialize_in_addrs(FILE *f, const struct in_addr *addresses, size_t size);
int deserialize_in_addrs(struct in_addr **addresses, const char *string);
diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h
index b221c6f6c5..cd44352307 100644
--- a/src/libsystemd-network/radv-internal.h
+++ b/src/libsystemd-network/radv-internal.h
@@ -85,5 +85,4 @@ struct sd_radv_prefix {
#define log_radv_full(level, error, fmt, ...) log_internal(level, error, __FILE__, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__)
#define log_radv_errno(error, fmt, ...) log_radv_full(LOG_DEBUG, error, fmt, ##__VA_ARGS__)
-#define log_radv_warning_errno(error, fmt, ...) log_radv_full(LOG_WARNING, error, fmt, ##__VA_ARGS__)
#define log_radv(fmt, ...) log_radv_errno(0, fmt, ##__VA_ARGS__)
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index ff434f8ce7..2d7ffd22ca 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -21,11 +21,13 @@
#include "dhcp-lease-internal.h"
#include "dhcp-protocol.h"
#include "dns-domain.h"
+#include "event-util.h"
#include "hostname-util.h"
+#include "io-util.h"
#include "random-util.h"
#include "string-util.h"
-#include "util.h"
#include "strv.h"
+#include "util.h"
#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN) /* Arbitrary limit */
#define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
@@ -86,7 +88,7 @@ struct sd_dhcp_client {
uint32_t mtu;
uint32_t xid;
usec_t start_time;
- unsigned int attempt;
+ unsigned attempt;
usec_t request_sent;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
@@ -298,27 +300,22 @@ int sd_dhcp_client_set_client_id(
assert_return(data, -EINVAL);
assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
- switch (type) {
-
- case ARPHRD_ETHER:
- if (data_len != ETH_ALEN)
- return -EINVAL;
- break;
-
- case ARPHRD_INFINIBAND:
- if (data_len != INFINIBAND_ALEN)
- return -EINVAL;
- break;
-
- default:
- break;
- }
-
if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
client->client_id.type == type &&
memcmp(&client->client_id.raw.data, data, data_len) == 0)
return 0;
+ /* For hardware types, log debug message about unexpected data length.
+ *
+ * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only
+ * last last 8 bytes of the address are stable and suitable to put into
+ * the client-id. The caller is advised to account for that. */
+ if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) ||
+ (type == ARPHRD_INFINIBAND && data_len != 8))
+ log_dhcp_client(client, "Changing client ID to hardware type %u with "
+ "unexpected address length %zu",
+ type, data_len);
+
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
log_dhcp_client(client, "Changing client ID on running DHCP "
"client, restarting");
@@ -341,13 +338,15 @@ int sd_dhcp_client_set_client_id(
* without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned.
*/
-static int dhcp_client_set_iaid_duid(
+static int dhcp_client_set_iaid_duid_internal(
sd_dhcp_client *client,
+ bool iaid_append,
+ bool iaid_set,
uint32_t iaid,
- bool append_iaid,
uint16_t duid_type,
const void *duid,
- size_t duid_len) {
+ size_t duid_len,
+ usec_t llt_time) {
DHCP_CLIENT_DONT_DESTROY(client);
int r;
@@ -357,7 +356,7 @@ static int dhcp_client_set_iaid_duid(
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
if (duid != NULL) {
- r = dhcp_validate_duid_len(duid_type, duid_len);
+ r = dhcp_validate_duid_len(duid_type, duid_len, true);
if (r < 0)
return r;
}
@@ -365,34 +364,60 @@ static int dhcp_client_set_iaid_duid(
zero(client->client_id);
client->client_id.type = 255;
- if (append_iaid) {
- /* If IAID is not configured, generate it. */
- if (iaid == 0) {
+ if (iaid_append) {
+ if (iaid_set)
+ client->client_id.ns.iaid = htobe32(iaid);
+ else {
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
client->mac_addr_len,
+ true,
&client->client_id.ns.iaid);
if (r < 0)
return r;
- } else
- client->client_id.ns.iaid = htobe32(iaid);
+ }
}
if (duid != NULL) {
client->client_id.ns.duid.type = htobe16(duid_type);
memcpy(&client->client_id.ns.duid.raw.data, duid, duid_len);
len = sizeof(client->client_id.ns.duid.type) + duid_len;
- } else if (duid_type == DUID_TYPE_EN) {
- r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
- if (r < 0)
- return r;
} else
- return -EOPNOTSUPP;
+ switch (duid_type) {
+ case DUID_TYPE_LLT:
+ if (client->mac_addr_len == 0)
+ return -EOPNOTSUPP;
+
+ r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_EN:
+ r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_LL:
+ if (client->mac_addr_len == 0)
+ return -EOPNOTSUPP;
+
+ r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_UUID:
+ r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len);
+ if (r < 0)
+ return r;
+ break;
+ default:
+ return -EINVAL;
+ }
client->client_id_len = sizeof(client->client_id.type) + len +
- (append_iaid ? sizeof(client->client_id.ns.iaid) : 0);
+ (iaid_append ? sizeof(client->client_id.ns.iaid) : 0);
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
- log_dhcp_client(client, "Configured IAID+DUID, restarting.");
+ log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : "");
client_stop(client, SD_DHCP_CLIENT_EVENT_STOP);
sd_dhcp_client_start(client);
}
@@ -402,11 +427,20 @@ static int dhcp_client_set_iaid_duid(
int sd_dhcp_client_set_iaid_duid(
sd_dhcp_client *client,
+ bool iaid_set,
uint32_t iaid,
uint16_t duid_type,
const void *duid,
size_t duid_len) {
- return dhcp_client_set_iaid_duid(client, iaid, true, duid_type, duid, duid_len);
+ return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, duid_type, duid, duid_len, 0);
+}
+
+int sd_dhcp_client_set_iaid_duid_llt(
+ sd_dhcp_client *client,
+ bool iaid_set,
+ uint32_t iaid,
+ usec_t llt_time) {
+ return dhcp_client_set_iaid_duid_internal(client, true, iaid_set, iaid, DUID_TYPE_LLT, NULL, 0, llt_time);
}
int sd_dhcp_client_set_duid(
@@ -414,7 +448,13 @@ int sd_dhcp_client_set_duid(
uint16_t duid_type,
const void *duid,
size_t duid_len) {
- return dhcp_client_set_iaid_duid(client, 0, false, duid_type, duid, duid_len);
+ return dhcp_client_set_iaid_duid_internal(client, false, false, 0, duid_type, duid, duid_len, 0);
+}
+
+int sd_dhcp_client_set_duid_llt(
+ sd_dhcp_client *client,
+ usec_t llt_time) {
+ return dhcp_client_set_iaid_duid_internal(client, false, false, 0, DUID_TYPE_LLT, NULL, 0, llt_time);
}
int sd_dhcp_client_set_hostname(
@@ -506,11 +546,10 @@ static int client_initialize(sd_dhcp_client *client) {
client->fd = asynchronous_close(client->fd);
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
-
- client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
- client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
- client->timeout_expire = sd_event_source_unref(client->timeout_expire);
+ (void) event_source_disable(client->timeout_resend);
+ (void) event_source_disable(client->timeout_t1);
+ (void) event_source_disable(client->timeout_t2);
+ (void) event_source_disable(client->timeout_expire);
client->attempt = 1;
@@ -611,7 +650,8 @@ static int client_message_init(
client->client_id.type = 255;
- r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
+ r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len,
+ true, &client->client_id.ns.iaid);
if (r < 0)
return r;
@@ -659,7 +699,7 @@ static int client_message_init(
let the server know how large the server may make its DHCP messages.
Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
- than the defined default size unless the Maximum Messge Size option
+ than the defined default size unless the Maximum Message Size option
is explicitly set
RFC3442 "Requirements to Avoid Sizing Constraints":
@@ -1024,22 +1064,11 @@ static int client_timeout_resend(
next_timeout += (random_u32() & 0x1fffff);
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
-
- r = sd_event_add_time(client->event,
- &client->timeout_resend,
- clock_boottime_or_monotonic(),
- next_timeout, 10 * USEC_PER_MSEC,
- client_timeout_resend, client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend,
- client->event_priority);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
+ r = event_reset_time(client->event, &client->timeout_resend,
+ clock_boottime_or_monotonic(),
+ next_timeout, 10 * USEC_PER_MSEC,
+ client_timeout_resend, client,
+ client->event_priority, "dhcp4-resend-timer", true);
if (r < 0)
goto error;
@@ -1136,31 +1165,16 @@ static int client_initialize_time_events(sd_dhcp_client *client) {
assert(client);
assert(client->event);
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
-
if (client->start_delay) {
assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0);
usec += client->start_delay;
}
- r = sd_event_add_time(client->event,
- &client->timeout_resend,
- clock_boottime_or_monotonic(),
- usec, 0,
- client_timeout_resend, client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend,
- client->event_priority);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
- if (r < 0)
- goto error;
-
-error:
+ r = event_reset_time(client->event, &client->timeout_resend,
+ clock_boottime_or_monotonic(),
+ usec, 0,
+ client_timeout_resend, client,
+ client->event_priority, "dhcp4-resend-timer", true);
if (r < 0)
client_stop(client, r);
@@ -1418,13 +1432,14 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
assert(client->lease);
assert(client->lease->lifetime);
- client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
- client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
- client->timeout_expire = sd_event_source_unref(client->timeout_expire);
-
/* don't set timers for infinite leases */
- if (client->lease->lifetime == 0xffffffff)
+ if (client->lease->lifetime == 0xffffffff) {
+ (void) event_source_disable(client->timeout_t1);
+ (void) event_source_disable(client->timeout_t2);
+ (void) event_source_disable(client->timeout_expire);
+
return 0;
+ }
r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
@@ -1476,19 +1491,11 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
}
/* arm lifetime timeout */
- r = sd_event_add_time(client->event, &client->timeout_expire,
- clock_boottime_or_monotonic(),
- lifetime_timeout, 10 * USEC_PER_MSEC,
- client_timeout_expire, client);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(client->timeout_expire,
- client->event_priority);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_description(client->timeout_expire, "dhcp4-lifetime");
+ r = event_reset_time(client->event, &client->timeout_expire,
+ clock_boottime_or_monotonic(),
+ lifetime_timeout, 10 * USEC_PER_MSEC,
+ client_timeout_expire, client,
+ client->event_priority, "dhcp4-lifetime", true);
if (r < 0)
return r;
@@ -1500,21 +1507,11 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return 0;
/* arm T2 timeout */
- r = sd_event_add_time(client->event,
- &client->timeout_t2,
- clock_boottime_or_monotonic(),
- t2_timeout,
- 10 * USEC_PER_MSEC,
- client_timeout_t2, client);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(client->timeout_t2,
- client->event_priority);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_description(client->timeout_t2, "dhcp4-t2-timeout");
+ r = event_reset_time(client->event, &client->timeout_t2,
+ clock_boottime_or_monotonic(),
+ t2_timeout, 10 * USEC_PER_MSEC,
+ client_timeout_t2, client,
+ client->event_priority, "dhcp4-t2-timeout", true);
if (r < 0)
return r;
@@ -1526,20 +1523,11 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return 0;
/* arm T1 timeout */
- r = sd_event_add_time(client->event,
- &client->timeout_t1,
- clock_boottime_or_monotonic(),
- t1_timeout, 10 * USEC_PER_MSEC,
- client_timeout_t1, client);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(client->timeout_t1,
- client->event_priority);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_description(client->timeout_t1, "dhcp4-t1-timer");
+ r = event_reset_time(client->event, &client->timeout_t1,
+ clock_boottime_or_monotonic(),
+ t1_timeout, 10 * USEC_PER_MSEC,
+ client_timeout_t1, client,
+ client->event_priority, "dhcp4-t1-timer", true);
if (r < 0)
return r;
@@ -1564,26 +1552,14 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
r = client_handle_offer(client, message, len);
if (r >= 0) {
- client->timeout_resend =
- sd_event_source_unref(client->timeout_resend);
-
client->state = DHCP_STATE_REQUESTING;
client->attempt = 1;
- r = sd_event_add_time(client->event,
- &client->timeout_resend,
- clock_boottime_or_monotonic(),
- 0, 0,
- client_timeout_resend, client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend,
- client->event_priority);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_description(client->timeout_resend, "dhcp4-resend-timer");
+ r = event_reset_time(client->event, &client->timeout_resend,
+ clock_boottime_or_monotonic(),
+ 0, 0,
+ client_timeout_resend, client,
+ client->event_priority, "dhcp4-resend-timer", true);
if (r < 0)
goto error;
} else if (r == -ENOMSG)
@@ -1600,8 +1576,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
r = client_handle_ack(client, message, len);
if (r >= 0) {
client->start_delay = 0;
- client->timeout_resend =
- sd_event_source_unref(client->timeout_resend);
+ (void) event_source_disable(client->timeout_resend);
client->receive_message =
sd_event_source_unref(client->receive_message);
client->fd = asynchronous_close(client->fd);
@@ -1641,8 +1616,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
} else if (r == -EADDRNOTAVAIL) {
/* got a NAK, let's restart the client */
- client->timeout_resend =
- sd_event_source_unref(client->timeout_resend);
+ client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED);
r = client_initialize(client);
if (r < 0)
@@ -1809,8 +1783,7 @@ static int client_receive_message_raw(
if (!packet)
return -ENOMEM;
- iov.iov_base = packet;
- iov.iov_len = buflen;
+ iov = IOVEC_MAKE(packet, buflen);
len = recvmsg(fd, &msg, 0);
if (len < 0) {
@@ -1912,33 +1885,17 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
return client->event;
}
-sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) {
-
- if (!client)
- return NULL;
-
- assert(client->n_ref >= 1);
- client->n_ref++;
-
- return client;
-}
-
-sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
-
- if (!client)
- return NULL;
-
- assert(client->n_ref >= 1);
- client->n_ref--;
-
- if (client->n_ref > 0)
- return NULL;
+static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
+ assert(client);
log_dhcp_client(client, "FREE");
- client_initialize(client);
+ client->timeout_resend = sd_event_source_unref(client->timeout_resend);
+ client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
+ client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
+ client->timeout_expire = sd_event_source_unref(client->timeout_expire);
- client->receive_message = sd_event_source_unref(client->receive_message);
+ client_initialize(client);
sd_dhcp_client_detach_event(client);
@@ -1951,24 +1908,27 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
return mfree(client);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free);
+
int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
_cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL;
assert_return(ret, -EINVAL);
- client = new0(sd_dhcp_client, 1);
+ client = new(sd_dhcp_client, 1);
if (!client)
return -ENOMEM;
- client->n_ref = 1;
- client->state = DHCP_STATE_INIT;
- client->ifindex = -1;
- client->fd = -1;
- client->attempt = 1;
- client->mtu = DHCP_DEFAULT_MIN_SIZE;
- client->port = DHCP_PORT_CLIENT;
-
- client->anonymize = !!anonymize;
+ *client = (sd_dhcp_client) {
+ .n_ref = 1,
+ .state = DHCP_STATE_INIT,
+ .ifindex = -1,
+ .fd = -1,
+ .attempt = 1,
+ .mtu = DHCP_DEFAULT_MIN_SIZE,
+ .port = DHCP_PORT_CLIENT,
+ .anonymize = !!anonymize,
+ };
/* NOTE: this could be moved to a function. */
if (anonymize) {
client->req_opts_size = ELEMENTSOF(default_req_opts_anonymize);
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index dbd80442e6..13badbf0bf 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -16,6 +16,7 @@
#include "dhcp-lease-internal.h"
#include "dhcp-protocol.h"
#include "dns-domain.h"
+#include "env-file.h"
#include "fd-util.h"
#include "fileio.h"
#include "hexdecoct.h"
@@ -25,6 +26,8 @@
#include "parse-util.h"
#include "stdio-util.h"
#include "string-util.h"
+#include "strv.h"
+#include "tmpfile-util.h"
#include "unaligned.h"
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
@@ -245,27 +248,8 @@ int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, s
return 0;
}
-sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) {
-
- if (!lease)
- return NULL;
-
- assert(lease->n_ref >= 1);
- lease->n_ref++;
-
- return lease;
-}
-
-sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
-
- if (!lease)
- return NULL;
-
- assert(lease->n_ref >= 1);
- lease->n_ref--;
-
- if (lease->n_ref > 0)
- return NULL;
+static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) {
+ assert(lease);
while (lease->private_options) {
struct sd_dhcp_raw_option *option = lease->private_options;
@@ -276,6 +260,8 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
free(option);
}
+ free(lease->root_path);
+ free(lease->timezone);
free(lease->hostname);
free(lease->domainname);
free(lease->dns);
@@ -287,6 +273,8 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) {
return mfree(lease);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_lease, sd_dhcp_lease, dhcp_lease_free);
+
static int lease_parse_u32(const uint8_t *option, size_t len, uint32_t *ret, uint32_t min) {
assert(option);
assert(ret);
@@ -346,8 +334,7 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
if (!string)
return -ENOMEM;
- free(*ret);
- *ret = string;
+ free_and_replace(*ret, string);
}
return 0;
@@ -368,7 +355,7 @@ static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
return 0;
}
- r = dns_name_normalize(name, &normalized);
+ r = dns_name_normalize(name, 0, &normalized);
if (r < 0)
return r;
@@ -1031,7 +1018,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
if (r < 0)
return r;
- r = parse_env_file(NULL, lease_file, NEWLINE,
+ r = parse_env_file(NULL, lease_file,
"ADDRESS", &address,
"ROUTER", &router,
"NETMASK", &netmask,
@@ -1082,8 +1069,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
"OPTION_251", &options[27],
"OPTION_252", &options[28],
"OPTION_253", &options[29],
- "OPTION_254", &options[30],
- NULL);
+ "OPTION_254", &options[30]);
if (r < 0)
return r;
@@ -1315,3 +1301,9 @@ int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
*gateway = route->gw_addr;
return 0;
}
+
+int sd_dhcp_route_get_option(sd_dhcp_route *route) {
+ assert_return(route, -EINVAL);
+
+ return route->option;
+}
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 5ca46b3502..7cb44d1fdf 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -12,6 +12,7 @@
#include "dhcp-server-internal.h"
#include "fd-util.h"
#include "in-addr-util.h"
+#include "io-util.h"
#include "sd-id128.h"
#include "siphash24.h"
#include "string-util.h"
@@ -20,12 +21,12 @@
#define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
#define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
-static void dhcp_lease_free(DHCPLease *lease) {
+static DHCPLease *dhcp_lease_free(DHCPLease *lease) {
if (!lease)
- return;
+ return NULL;
free(lease->client_id.data);
- free(lease);
+ return mfree(lease);
}
/* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
@@ -89,7 +90,7 @@ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *addres
server->bound_leases[server_off - offset] = &server->invalid_lease;
/* Drop any leases associated with the old address range */
- hashmap_clear_with_destructor(server->leases_by_client_id, dhcp_lease_free);
+ hashmap_clear(server->leases_by_client_id);
}
return 0;
@@ -101,20 +102,7 @@ int sd_dhcp_server_is_running(sd_dhcp_server *server) {
return !!server->receive_message;
}
-sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server) {
-
- if (!server)
- return NULL;
-
- assert(server->n_ref >= 1);
- server->n_ref++;
-
- return server;
-}
-
-void client_id_hash_func(const void *p, struct siphash *state) {
- const DHCPClientId *id = p;
-
+void client_id_hash_func(const DHCPClientId *id, struct siphash *state) {
assert(id);
assert(id->length);
assert(id->data);
@@ -123,37 +111,24 @@ void client_id_hash_func(const void *p, struct siphash *state) {
siphash24_compress(id->data, id->length, state);
}
-int client_id_compare_func(const void *_a, const void *_b) {
- const DHCPClientId *a, *b;
-
- a = _a;
- b = _b;
+int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b) {
+ int r;
assert(!a->length || a->data);
assert(!b->length || b->data);
- if (a->length != b->length)
- return a->length < b->length ? -1 : 1;
+ r = CMP(a->length, b->length);
+ if (r != 0)
+ return r;
return memcmp(a->data, b->data, a->length);
}
-static const struct hash_ops client_id_hash_ops = {
- .hash = client_id_hash_func,
- .compare = client_id_compare_func
-};
-
-sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
- DHCPLease *lease;
-
- if (!server)
- return NULL;
-
- assert(server->n_ref >= 1);
- server->n_ref--;
+DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(dhcp_lease_hash_ops, DHCPClientId, client_id_hash_func, client_id_compare_func,
+ DHCPLease, dhcp_lease_free);
- if (server->n_ref > 0)
- return NULL;
+static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
+ assert(server);
log_dhcp_server(server, "UNREF");
@@ -165,14 +140,14 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
free(server->dns);
free(server->ntp);
- while ((lease = hashmap_steal_first(server->leases_by_client_id)))
- dhcp_lease_free(lease);
hashmap_free(server->leases_by_client_id);
free(server->bound_leases);
return mfree(server);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_server, sd_dhcp_server, dhcp_server_free);
+
int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
_cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
@@ -190,7 +165,7 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
server->netmask = htobe32(INADDR_ANY);
server->ifindex = ifindex;
- server->leases_by_client_id = hashmap_new(&client_id_hash_ops);
+ server->leases_by_client_id = hashmap_new(&dhcp_lease_hash_ops);
if (!server->leases_by_client_id)
return -ENOMEM;
@@ -957,8 +932,7 @@ static int server_receive_message(sd_event_source *s, int fd,
if (!message)
return -ENOMEM;
- iov.iov_base = message;
- iov.iov_len = buflen;
+ iov = IOVEC_MAKE(message, buflen);
len = recvmsg(fd, &msg, 0);
if (len < 0) {
@@ -1002,7 +976,7 @@ int sd_dhcp_server_start(sd_dhcp_server *server) {
assert_return(server->fd < 0, -EBUSY);
assert_return(server->address != htobe32(INADDR_ANY), -EUNATCH);
- r = socket(AF_PACKET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
+ r = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (r < 0) {
r = -errno;
sd_dhcp_server_stop(server);
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index b3bc259280..593ffd1b64 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -16,6 +16,7 @@
#include "dhcp6-lease-internal.h"
#include "dhcp6-protocol.h"
#include "dns-domain.h"
+#include "event-util.h"
#include "fd-util.h"
#include "hostname-util.h"
#include "in-addr-util.h"
@@ -27,6 +28,13 @@
#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
+/* what to request from the server, addresses (IA_NA) and/or prefixes (IA_PD) */
+enum {
+ DHCP6_REQUEST_IA_NA = 1,
+ DHCP6_REQUEST_IA_TA = 2, /* currently not used */
+ DHCP6_REQUEST_IA_PD = 4,
+};
+
struct sd_dhcp6_client {
unsigned n_ref;
@@ -40,12 +48,15 @@ struct sd_dhcp6_client {
uint16_t arp_type;
DHCP6IA ia_na;
DHCP6IA ia_pd;
- bool prefix_delegation;
+ sd_event_source *timeout_t1;
+ sd_event_source *timeout_t2;
+ unsigned request;
be32_t transaction_id;
usec_t transaction_start;
struct sd_dhcp6_lease *lease;
int fd;
bool information_request;
+ bool iaid_set;
be16_t *req_opts;
size_t req_opts_allocated;
size_t req_opts_len;
@@ -182,43 +193,86 @@ static int client_ensure_duid(sd_dhcp6_client *client) {
* without further modification. Otherwise, if duid_type is supported, DUID
* is set based on that type. Otherwise, an error is returned.
*/
-int sd_dhcp6_client_set_duid(
+static int dhcp6_client_set_duid_internal(
sd_dhcp6_client *client,
uint16_t duid_type,
const void *duid,
- size_t duid_len) {
-
+ size_t duid_len,
+ usec_t llt_time) {
int r;
+
assert_return(client, -EINVAL);
assert_return(duid_len == 0 || duid != NULL, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
if (duid != NULL) {
- r = dhcp_validate_duid_len(duid_type, duid_len);
- if (r < 0)
- return r;
- }
+ r = dhcp_validate_duid_len(duid_type, duid_len, true);
+ if (r < 0) {
+ r = dhcp_validate_duid_len(duid_type, duid_len, false);
+ if (r < 0)
+ return r;
+ log_dhcp6_client(client, "Setting DUID of type %u with unexpected content", duid_type);
+ }
- if (duid != NULL) {
client->duid.type = htobe16(duid_type);
memcpy(&client->duid.raw.data, duid, duid_len);
client->duid_len = sizeof(client->duid.type) + duid_len;
- } else if (duid_type == DUID_TYPE_EN) {
- r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
- if (r < 0)
- return r;
} else
- return -EOPNOTSUPP;
+ switch (duid_type) {
+ case DUID_TYPE_LLT:
+ if (client->mac_addr_len == 0)
+ return -EOPNOTSUPP;
+
+ r = dhcp_identifier_set_duid_llt(&client->duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_EN:
+ r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_LL:
+ if (client->mac_addr_len == 0)
+ return -EOPNOTSUPP;
+
+ r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len);
+ if (r < 0)
+ return r;
+ break;
+ case DUID_TYPE_UUID:
+ r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len);
+ if (r < 0)
+ return r;
+ break;
+ default:
+ return -EINVAL;
+ }
return 0;
}
+int sd_dhcp6_client_set_duid(
+ sd_dhcp6_client *client,
+ uint16_t duid_type,
+ const void *duid,
+ size_t duid_len) {
+ return dhcp6_client_set_duid_internal(client, duid_type, duid, duid_len, 0);
+}
+
+int sd_dhcp6_client_set_duid_llt(
+ sd_dhcp6_client *client,
+ usec_t llt_time) {
+ return dhcp6_client_set_duid_internal(client, DUID_TYPE_LLT, NULL, 0, llt_time);
+}
+
int sd_dhcp6_client_set_iaid(sd_dhcp6_client *client, uint32_t iaid) {
assert_return(client, -EINVAL);
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
client->ia_na.ia_na.id = htobe32(iaid);
client->ia_pd.ia_pd.id = htobe32(iaid);
+ client->iaid_set = true;
return 0;
}
@@ -287,10 +341,44 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
return 0;
}
-int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, bool delegation) {
+int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
assert_return(client, -EINVAL);
+ assert_return(delegation, -EINVAL);
- client->prefix_delegation = delegation;
+ *delegation = FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD);
+
+ return 0;
+}
+
+int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, int delegation) {
+ assert_return(client, -EINVAL);
+
+ SET_FLAG(client->request, DHCP6_REQUEST_IA_PD, delegation);
+
+ return 0;
+}
+
+int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, int *request) {
+ assert_return(client, -EINVAL);
+ assert_return(request, -EINVAL);
+
+ *request = FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA);
+
+ return 0;
+}
+
+int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client, int request) {
+ assert_return(client, -EINVAL);
+
+ SET_FLAG(client->request, DHCP6_REQUEST_IA_NA, request);
+
+ return 0;
+}
+
+int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id) {
+ assert_return(client, -EINVAL);
+
+ client->transaction_id = transaction_id;
return 0;
}
@@ -314,21 +402,10 @@ static void client_notify(sd_dhcp6_client *client, int event) {
client->callback(client, event, client->userdata);
}
-static void client_set_lease(sd_dhcp6_client *client, sd_dhcp6_lease *lease) {
- assert(client);
-
- if (client->lease) {
- dhcp6_lease_clear_timers(&client->lease->ia);
- sd_dhcp6_lease_unref(client->lease);
- }
-
- client->lease = lease;
-}
-
static int client_reset(sd_dhcp6_client *client) {
assert(client);
- client_set_lease(client, NULL);
+ client->lease = sd_dhcp6_lease_unref(client->lease);
client->receive_message =
sd_event_source_unref(client->receive_message);
@@ -336,16 +413,13 @@ static int client_reset(sd_dhcp6_client *client) {
client->transaction_id = 0;
client->transaction_start = 0;
- client->ia_na.timeout_t1 =
- sd_event_source_unref(client->ia_na.timeout_t1);
- client->ia_na.timeout_t2 =
- sd_event_source_unref(client->ia_na.timeout_t2);
-
client->retransmit_time = 0;
client->retransmit_count = 0;
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
- client->timeout_resend_expire =
- sd_event_source_unref(client->timeout_resend_expire);
+
+ (void) event_source_disable(client->timeout_resend);
+ (void) event_source_disable(client->timeout_resend_expire);
+ (void) event_source_disable(client->timeout_t1);
+ (void) event_source_disable(client->timeout_t2);
client->state = DHCP6_STATE_STOPPED;
@@ -398,9 +472,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
if (r < 0)
return r;
- r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
- if (r < 0)
- return r;
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
+ r = dhcp6_option_append_ia(&opt, &optlen,
+ &client->ia_na);
+ if (r < 0)
+ return r;
+ }
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -408,7 +485,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
- if (client->prefix_delegation) {
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd);
if (r < 0)
return r;
@@ -433,9 +510,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
if (r < 0)
return r;
- r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
- if (r < 0)
- return r;
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
+ r = dhcp6_option_append_ia(&opt, &optlen,
+ &client->lease->ia);
+ if (r < 0)
+ return r;
+ }
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -443,7 +523,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
- if (client->prefix_delegation) {
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
if (r < 0)
return r;
@@ -457,9 +537,11 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
case DHCP6_STATE_REBIND:
message->type = DHCP6_REBIND;
- r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
- if (r < 0)
- return r;
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) {
+ r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia);
+ if (r < 0)
+ return r;
+ }
if (client->fqdn) {
r = dhcp6_option_append_fqdn(&opt, &optlen, client->fqdn);
@@ -467,7 +549,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
- if (client->prefix_delegation) {
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd);
if (r < 0)
return r;
@@ -524,8 +606,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
assert(client);
assert(client->lease);
- client->lease->ia.timeout_t2 =
- sd_event_source_unref(client->lease->ia.timeout_t2);
+ (void) event_source_disable(client->timeout_t2);
log_dhcp6_client(client, "Timeout T2");
@@ -541,8 +622,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
assert(client);
assert(client->lease);
- client->lease->ia.timeout_t1 =
- sd_event_source_unref(client->lease->ia.timeout_t1);
+ (void) event_source_disable(client->timeout_t1);
log_dhcp6_client(client, "Timeout T1");
@@ -590,7 +670,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda
assert(client);
assert(client->event);
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
+ (void) event_source_disable(client->timeout_resend);
switch (client->state) {
case DHCP6_STATE_INFORMATION_REQUEST:
@@ -632,7 +712,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda
init_retransmit_time = DHCP6_REB_TIMEOUT;
max_retransmit_time = DHCP6_REB_MAX_RT;
- if (!client->timeout_resend_expire) {
+ if (event_source_is_enabled(client->timeout_resend_expire) <= 0) {
r = dhcp6_lease_ia_rebind_expire(&client->lease->ia,
&expire);
if (r < 0) {
@@ -681,43 +761,24 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda
log_dhcp6_client(client, "Next retransmission in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC));
- r = sd_event_add_time(client->event, &client->timeout_resend,
- clock_boottime_or_monotonic(),
- time_now + client->retransmit_time,
- 10 * USEC_PER_MSEC, client_timeout_resend,
- client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend,
- client->event_priority);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timer");
+ r = event_reset_time(client->event, &client->timeout_resend,
+ clock_boottime_or_monotonic(),
+ time_now + client->retransmit_time, 10 * USEC_PER_MSEC,
+ client_timeout_resend, client,
+ client->event_priority, "dhcp6-resend-timer", true);
if (r < 0)
goto error;
- if (max_retransmit_duration && !client->timeout_resend_expire) {
+ if (max_retransmit_duration && event_source_is_enabled(client->timeout_resend_expire) <= 0) {
log_dhcp6_client(client, "Max retransmission duration %"PRIu64" secs",
max_retransmit_duration / USEC_PER_SEC);
- r = sd_event_add_time(client->event,
- &client->timeout_resend_expire,
- clock_boottime_or_monotonic(),
- time_now + max_retransmit_duration,
- USEC_PER_SEC,
- client_timeout_resend_expire, client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend_expire,
- client->event_priority);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_description(client->timeout_resend_expire, "dhcp6-resend-expire-timer");
+ r = event_reset_time(client->event, &client->timeout_resend_expire,
+ clock_boottime_or_monotonic(),
+ time_now + max_retransmit_duration, USEC_PER_SEC,
+ client_timeout_resend_expire, client,
+ client->event_priority, "dhcp6-resend-expire-timer", true);
if (r < 0)
goto error;
}
@@ -731,19 +792,20 @@ error:
static int client_ensure_iaid(sd_dhcp6_client *client) {
int r;
- be32_t iaid;
+ uint32_t iaid;
assert(client);
- if (client->ia_na.ia_na.id)
+ if (client->iaid_set)
return 0;
- r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, &iaid);
+ r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, true, &iaid);
if (r < 0)
return r;
client->ia_na.ia_na.id = iaid;
client->ia_pd.ia_pd.id = iaid;
+ client->iaid_set = true;
return 0;
}
@@ -753,10 +815,11 @@ static int client_parse_message(
DHCP6Message *message,
size_t len,
sd_dhcp6_lease *lease) {
+
+ uint32_t lt_t1 = ~0, lt_t2 = ~0;
+ bool clientid = false;
size_t pos = 0;
int r;
- bool clientid = false;
- uint32_t lt_t1 = ~0, lt_t2 = ~0;
assert(client);
assert(message);
@@ -766,20 +829,22 @@ static int client_parse_message(
len -= sizeof(DHCP6Message);
while (pos < len) {
- DHCP6Option *option = (DHCP6Option *)&message->options[pos];
+ DHCP6Option *option = (DHCP6Option *) &message->options[pos];
uint16_t optcode, optlen;
- int status;
- uint8_t *optval;
be32_t iaid_lease;
+ uint8_t *optval;
+ int status;
- if (len < offsetof(DHCP6Option, data) ||
- len < offsetof(DHCP6Option, data) + be16toh(option->len))
+ if (len < pos + offsetof(DHCP6Option, data))
return -ENOBUFS;
optcode = be16toh(option->code);
optlen = be16toh(option->len);
optval = option->data;
+ if (len < pos + offsetof(DHCP6Option, data) + optlen)
+ return -ENOBUFS;
+
switch (optcode) {
case SD_DHCP6_OPTION_CLIENTID:
if (clientid) {
@@ -824,13 +889,14 @@ static int client_parse_message(
break;
case SD_DHCP6_OPTION_STATUS_CODE:
- status = dhcp6_option_parse_status(option);
- if (status) {
+ status = dhcp6_option_parse_status(option, optlen + sizeof(DHCP6Option));
+ if (status < 0)
+ return status;
+
+ if (status > 0) {
log_dhcp6_client(client, "%s Status %s",
dhcp6_message_type_to_string(message->type),
dhcp6_message_status_to_string(status));
- dhcp6_lease_free_ia(&lease->ia);
- dhcp6_lease_free_ia(&lease->pd);
return -EINVAL;
}
@@ -876,7 +942,7 @@ static int client_parse_message(
if (r < 0 && r != -ENOMSG)
return r;
- r = dhcp6_lease_get_iaid(lease, &iaid_lease);
+ r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease);
if (r < 0)
return r;
@@ -929,7 +995,7 @@ static int client_parse_message(
break;
}
- pos += sizeof(*option) + optlen;
+ pos += offsetof(DHCP6Option, data) + optlen;
}
if (!clientid) {
@@ -989,8 +1055,8 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
return 0;
}
- client_set_lease(client, lease);
- lease = NULL;
+ sd_dhcp6_lease_unref(client->lease);
+ client->lease = TAKE_PTR(lease);
return DHCP6_STATE_BOUND;
}
@@ -1018,8 +1084,8 @@ static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *adver
r = dhcp6_lease_get_preference(client->lease, &pref_lease);
if (r < 0 || pref_advertise > pref_lease) {
- client_set_lease(client, lease);
- lease = NULL;
+ sd_dhcp6_lease_unref(client->lease);
+ client->lease = TAKE_PTR(lease);
r = 0;
}
@@ -1144,26 +1210,47 @@ static int client_receive_message(
return 0;
}
- if (r >= 0)
- log_dhcp6_client(client, "Recv %s",
- dhcp6_message_type_to_string(message->type));
+ log_dhcp6_client(client, "Recv %s",
+ dhcp6_message_type_to_string(message->type));
return 0;
}
+static int client_get_lifetime(sd_dhcp6_client *client, uint32_t *lifetime_t1,
+ uint32_t *lifetime_t2) {
+ assert_return(client, -EINVAL);
+ assert_return(client->lease, -EINVAL);
+
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) {
+ *lifetime_t1 = be32toh(client->lease->ia.ia_na.lifetime_t1);
+ *lifetime_t2 = be32toh(client->lease->ia.ia_na.lifetime_t2);
+
+ return 0;
+ }
+
+ if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) {
+ *lifetime_t1 = be32toh(client->lease->pd.ia_pd.lifetime_t1);
+ *lifetime_t2 = be32toh(client->lease->pd.ia_pd.lifetime_t2);
+
+ return 0;
+ }
+
+ return -ENOMSG;
+}
+
static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
int r;
usec_t timeout, time_now;
char time_string[FORMAT_TIMESPAN_MAX];
+ uint32_t lifetime_t1, lifetime_t2;
assert_return(client, -EINVAL);
assert_return(client->event, -EINVAL);
assert_return(client->ifindex > 0, -EINVAL);
assert_return(client->state != state, -EINVAL);
- client->timeout_resend_expire =
- sd_event_source_unref(client->timeout_resend_expire);
- client->timeout_resend = sd_event_source_unref(client->timeout_resend);
+ (void) event_source_disable(client->timeout_resend_expire);
+ (void) event_source_disable(client->timeout_resend);
client->retransmit_time = 0;
client->retransmit_count = 0;
@@ -1214,57 +1301,40 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
case DHCP6_STATE_BOUND:
- if (client->lease->ia.ia_na.lifetime_t1 == 0xffffffff ||
- client->lease->ia.ia_na.lifetime_t2 == 0xffffffff) {
+ r = client_get_lifetime(client, &lifetime_t1, &lifetime_t2);
+ if (r < 0)
+ goto error;
+ if (lifetime_t1 == 0xffffffff || lifetime_t2 == 0xffffffff) {
log_dhcp6_client(client, "Infinite T1 0x%08x or T2 0x%08x",
- be32toh(client->lease->ia.ia_na.lifetime_t1),
- be32toh(client->lease->ia.ia_na.lifetime_t2));
+ lifetime_t1, lifetime_t2);
return 0;
}
- timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t1) * USEC_PER_SEC);
+ timeout = client_timeout_compute_random(lifetime_t1 * USEC_PER_SEC);
log_dhcp6_client(client, "T1 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
- r = sd_event_add_time(client->event,
- &client->lease->ia.timeout_t1,
- clock_boottime_or_monotonic(), time_now + timeout,
- 10 * USEC_PER_SEC, client_timeout_t1,
- client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->lease->ia.timeout_t1,
- client->event_priority);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
+ r = event_reset_time(client->event, &client->timeout_t1,
+ clock_boottime_or_monotonic(),
+ time_now + timeout, 10 * USEC_PER_SEC,
+ client_timeout_t1, client,
+ client->event_priority, "dhcp6-t1-timeout", true);
if (r < 0)
goto error;
- timeout = client_timeout_compute_random(be32toh(client->lease->ia.ia_na.lifetime_t2) * USEC_PER_SEC);
+ timeout = client_timeout_compute_random(lifetime_t2 * USEC_PER_SEC);
log_dhcp6_client(client, "T2 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
- r = sd_event_add_time(client->event,
- &client->lease->ia.timeout_t2,
- clock_boottime_or_monotonic(), time_now + timeout,
- 10 * USEC_PER_SEC, client_timeout_t2,
- client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->lease->ia.timeout_t2,
- client->event_priority);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
+ r = event_reset_time(client->event, &client->timeout_t2,
+ clock_boottime_or_monotonic(),
+ time_now + timeout, 10 * USEC_PER_SEC,
+ client_timeout_t2, client,
+ client->event_priority, "dhcp6-t2-timeout", true);
if (r < 0)
goto error;
@@ -1276,18 +1346,11 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
client->transaction_id = random_u32() & htobe32(0x00ffffff);
client->transaction_start = time_now;
- r = sd_event_add_time(client->event, &client->timeout_resend,
- clock_boottime_or_monotonic(), 0, 0, client_timeout_resend,
- client);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_priority(client->timeout_resend,
- client->event_priority);
- if (r < 0)
- goto error;
-
- r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout");
+ r = event_reset_time(client->event, &client->timeout_resend,
+ clock_boottime_or_monotonic(),
+ 0, 0,
+ client_timeout_resend, client,
+ client->event_priority, "dhcp6-resend-timeout", true);
if (r < 0)
goto error;
@@ -1326,6 +1389,9 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
if (!IN_SET(client->state, DHCP6_STATE_STOPPED))
return -EBUSY;
+ if (!client->information_request && !client->request)
+ return -EINVAL;
+
r = client_reset(client);
if (r < 0)
return r;
@@ -1394,27 +1460,13 @@ sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
return client->event;
}
-sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) {
-
- if (!client)
- return NULL;
-
- assert(client->n_ref >= 1);
- client->n_ref++;
-
- return client;
-}
-
-sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
-
- if (!client)
- return NULL;
-
- assert(client->n_ref >= 1);
- client->n_ref--;
+static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
+ assert(client);
- if (client->n_ref > 0)
- return NULL;
+ client->timeout_resend = sd_event_source_unref(client->timeout_resend);
+ client->timeout_resend_expire = sd_event_source_unref(client->timeout_resend_expire);
+ client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
+ client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
client_reset(client);
@@ -1427,29 +1479,36 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
return mfree(client);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_client, sd_dhcp6_client, dhcp6_client_free);
+
int sd_dhcp6_client_new(sd_dhcp6_client **ret) {
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
+ _cleanup_free_ be16_t *req_opts = NULL;
size_t t;
assert_return(ret, -EINVAL);
- client = new0(sd_dhcp6_client, 1);
- if (!client)
+ req_opts = new(be16_t, ELEMENTSOF(default_req_opts));
+ if (!req_opts)
return -ENOMEM;
- client->n_ref = 1;
- client->ia_na.type = SD_DHCP6_OPTION_IA_NA;
- client->ia_pd.type = SD_DHCP6_OPTION_IA_PD;
- client->ifindex = -1;
- client->fd = -1;
+ for (t = 0; t < ELEMENTSOF(default_req_opts); t++)
+ req_opts[t] = htobe16(default_req_opts[t]);
- client->req_opts_len = ELEMENTSOF(default_req_opts);
- client->req_opts = new0(be16_t, client->req_opts_len);
- if (!client->req_opts)
+ client = new(sd_dhcp6_client, 1);
+ if (!client)
return -ENOMEM;
- for (t = 0; t < client->req_opts_len; t++)
- client->req_opts[t] = htobe16(default_req_opts[t]);
+ *client = (sd_dhcp6_client) {
+ .n_ref = 1,
+ .ia_na.type = SD_DHCP6_OPTION_IA_NA,
+ .ia_pd.type = SD_DHCP6_OPTION_IA_PD,
+ .ifindex = -1,
+ .request = DHCP6_REQUEST_IA_NA,
+ .fd = -1,
+ .req_opts_len = ELEMENTSOF(default_req_opts),
+ .req_opts = TAKE_PTR(req_opts),
+ };
*ret = TAKE_PTR(client);
diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c
index 779ad54b4a..8b424811ad 100644
--- a/src/libsystemd-network/sd-dhcp6-lease.c
+++ b/src/libsystemd-network/sd-dhcp6-lease.c
@@ -11,15 +11,6 @@
#include "strv.h"
#include "util.h"
-int dhcp6_lease_clear_timers(DHCP6IA *ia) {
- assert_return(ia, -EINVAL);
-
- ia->timeout_t1 = sd_event_source_unref(ia->timeout_t1);
- ia->timeout_t2 = sd_event_source_unref(ia->timeout_t2);
-
- return 0;
-}
-
int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) {
DHCP6Address *addr;
uint32_t valid = 0, t;
@@ -48,8 +39,6 @@ DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
if (!ia)
return NULL;
- dhcp6_lease_clear_timers(ia);
-
while (ia->addresses) {
address = ia->addresses;
@@ -63,15 +52,16 @@ DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) {
int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
size_t len) {
+ uint8_t *serverid;
+
assert_return(lease, -EINVAL);
assert_return(id, -EINVAL);
- free(lease->serverid);
-
- lease->serverid = memdup(id, len);
- if (!lease->serverid)
- return -EINVAL;
+ serverid = memdup(id, len);
+ if (!serverid)
+ return -ENOMEM;
+ free_and_replace(lease->serverid, serverid);
lease->serverid_len = len;
return 0;
@@ -136,6 +126,15 @@ int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
return 0;
}
+int dhcp6_lease_get_pd_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
+ assert_return(lease, -EINVAL);
+ assert_return(iaid, -EINVAL);
+
+ *iaid = lease->pd.ia_pd.id;
+
+ return 0;
+}
+
int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr,
uint32_t *lifetime_preferred,
uint32_t *lifetime_valid) {
@@ -374,27 +373,8 @@ int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) {
return -ENOENT;
}
-sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) {
-
- if (!lease)
- return NULL;
-
- assert(lease->n_ref >= 1);
- lease->n_ref++;
-
- return lease;
-}
-
-sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
-
- if (!lease)
- return NULL;
-
- assert(lease->n_ref >= 1);
- lease->n_ref--;
-
- if (lease->n_ref > 0)
- return NULL;
+static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) {
+ assert(lease);
free(lease->serverid);
dhcp6_lease_free_ia(&lease->ia);
@@ -410,6 +390,8 @@ sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) {
return mfree(lease);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_lease, sd_dhcp6_lease, dhcp6_lease_free);
+
int dhcp6_lease_new(sd_dhcp6_lease **ret) {
sd_dhcp6_lease *lease;
diff --git a/src/libsystemd-network/sd-ipv4acd.c b/src/libsystemd-network/sd-ipv4acd.c
index a40d40db90..59359aec79 100644
--- a/src/libsystemd-network/sd-ipv4acd.c
+++ b/src/libsystemd-network/sd-ipv4acd.c
@@ -14,6 +14,7 @@
#include "alloc-util.h"
#include "arp-util.h"
#include "ether-addr-util.h"
+#include "event-util.h"
#include "fd-util.h"
#include "in-addr-util.h"
#include "list.h"
@@ -89,7 +90,7 @@ static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_count
static void ipv4acd_reset(sd_ipv4acd *acd) {
assert(acd);
- acd->timer_event_source = sd_event_source_unref(acd->timer_event_source);
+ (void) event_source_disable(acd->timer_event_source);
acd->receive_message_event_source = sd_event_source_unref(acd->receive_message_event_source);
acd->fd = safe_close(acd->fd);
@@ -97,25 +98,10 @@ static void ipv4acd_reset(sd_ipv4acd *acd) {
ipv4acd_set_state(acd, IPV4ACD_STATE_INIT, true);
}
-sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd) {
- if (!acd)
- return NULL;
-
- assert_se(acd->n_ref >= 1);
- acd->n_ref++;
-
- return acd;
-}
-
-sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) {
- if (!acd)
- return NULL;
-
- assert_se(acd->n_ref >= 1);
- acd->n_ref--;
+static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) {
+ assert(acd);
- if (acd->n_ref > 0)
- return NULL;
+ acd->timer_event_source = sd_event_source_unref(acd->timer_event_source);
ipv4acd_reset(acd);
sd_ipv4acd_detach_event(acd);
@@ -123,19 +109,23 @@ sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd) {
return mfree(acd);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4acd, sd_ipv4acd, ipv4acd_free);
+
int sd_ipv4acd_new(sd_ipv4acd **ret) {
_cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL;
assert_return(ret, -EINVAL);
- acd = new0(sd_ipv4acd, 1);
+ acd = new(sd_ipv4acd, 1);
if (!acd)
return -ENOMEM;
- acd->n_ref = 1;
- acd->state = IPV4ACD_STATE_INIT;
- acd->ifindex = -1;
- acd->fd = -1;
+ *acd = (sd_ipv4acd) {
+ .n_ref = 1,
+ .state = IPV4ACD_STATE_INIT,
+ .ifindex = -1,
+ .fd = -1,
+ };
*ret = TAKE_PTR(acd);
@@ -166,9 +156,7 @@ int sd_ipv4acd_stop(sd_ipv4acd *acd) {
static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata);
static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) {
- _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL;
usec_t next_timeout, time_now;
- int r;
assert(acd);
@@ -179,20 +167,11 @@ static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_u
assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 0);
- r = sd_event_add_time(acd->event, &timer, clock_boottime_or_monotonic(), time_now + next_timeout, 0, ipv4acd_on_timeout, acd);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(timer, acd->event_priority);
- if (r < 0)
- return r;
-
- (void) sd_event_source_set_description(timer, "ipv4acd-timer");
-
- sd_event_source_unref(acd->timer_event_source);
- acd->timer_event_source = TAKE_PTR(timer);
-
- return 0;
+ return event_reset_time(acd->event, &acd->timer_event_source,
+ clock_boottime_or_monotonic(),
+ time_now + next_timeout, 0,
+ ipv4acd_on_timeout, acd,
+ acd->event_priority, "ipv4acd-timer", true);
}
static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, struct ether_arp *arp) {
diff --git a/src/libsystemd-network/sd-ipv4ll.c b/src/libsystemd-network/sd-ipv4ll.c
index 7307e1668f..e451dff744 100644
--- a/src/libsystemd-network/sd-ipv4ll.c
+++ b/src/libsystemd-network/sd-ipv4ll.c
@@ -55,30 +55,15 @@ struct sd_ipv4ll {
static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
-sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll) {
- if (!ll)
- return NULL;
-
- assert(ll->n_ref >= 1);
- ll->n_ref++;
-
- return ll;
-}
-
-sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll) {
- if (!ll)
- return NULL;
-
- assert(ll->n_ref >= 1);
- ll->n_ref--;
-
- if (ll->n_ref > 0)
- return NULL;
+static sd_ipv4ll *ipv4ll_free(sd_ipv4ll *ll) {
+ assert(ll);
sd_ipv4acd_unref(ll->acd);
return mfree(ll);
}
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4ll, sd_ipv4ll, ipv4ll_free);
+
int sd_ipv4ll_new(sd_ipv4ll **ret) {
_cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL;
int r;
diff --git a/src/libsystemd-network/sd-lldp.c b/src/libsystemd-network/sd-lldp.c
index c75d6079e1..969fc71051 100644
--- a/src/libsystemd-network/sd-lldp.c
+++ b/src/libsystemd-network/sd-lldp.c
@@ -2,36 +2,47 @@
#include <arpa/inet.h>
#include <linux/sockios.h>
+#include <sys/ioctl.h>
#include "sd-lldp.h"
#include "alloc-util.h"
+#include "ether-addr-util.h"
+#include "event-util.h"
#include "fd-util.h"
#include "lldp-internal.h"
#include "lldp-neighbor.h"
#include "lldp-network.h"
#include "socket-util.h"
-#include "ether-addr-util.h"
+#include "string-table.h"
#define LLDP_DEFAULT_NEIGHBORS_MAX 128U
-static void lldp_flush_neighbors(sd_lldp *lldp) {
- sd_lldp_neighbor *n;
+static const char * const lldp_event_table[_SD_LLDP_EVENT_MAX] = {
+ [SD_LLDP_EVENT_ADDED] = "added",
+ [SD_LLDP_EVENT_REMOVED] = "removed",
+ [SD_LLDP_EVENT_UPDATED] = "updated",
+ [SD_LLDP_EVENT_REFRESHED] = "refreshed",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(lldp_event, sd_lldp_event);
+static void lldp_flush_neighbors(sd_lldp *lldp) {
assert(lldp);
- while ((n = hashmap_first(lldp->neighbor_by_id)))
- lldp_neighbor_unlink(n);
+ hashmap_clear(lldp->neighbor_by_id);
}
static void lldp_callback(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n) {
assert(lldp);
+ assert(event >= 0 && event < _SD_LLDP_EVENT_MAX);
- log_lldp("Invoking callback for '%c'.", event);
-
- if (!lldp->callback)
+ if (!lldp->callback) {
+ log_lldp("Received '%s' event.", lldp_event_to_string(event));
return;
+ }
+ log_lldp("Invoking callback for '%s' event.", lldp_event_to_string(event));
lldp->callback(lldp, event, n, lldp->userdata);
}
@@ -119,7 +130,7 @@ static int lldp_add_neighbor(sd_lldp *lldp, sd_lldp_neighbor *n) {
}
if (lldp_neighbor_equal(n, old)) {
- /* Is this equal, then restart the TTL counter, but don't do anyting else. */
+ /* Is this equal, then restart the TTL counter, but don't do anything else. */
old->timestamp = n->timestamp;
lldp_start_timer(lldp, old);
lldp_callback(lldp, SD_LLDP_EVENT_REFRESHED, old);
@@ -223,7 +234,7 @@ static int lldp_receive_datagram(sd_event_source *s, int fd, uint32_t revents, v
static void lldp_reset(sd_lldp *lldp) {
assert(lldp);
- lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
+ (void) event_source_disable(lldp->timer_event_source);
lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
lldp->fd = safe_close(lldp->fd);
}
@@ -329,27 +340,10 @@ _public_ int sd_lldp_set_ifindex(sd_lldp *lldp, int ifindex) {
return 0;
}
-_public_ sd_lldp* sd_lldp_ref(sd_lldp *lldp) {
-
- if (!lldp)
- return NULL;
-
- assert(lldp->n_ref > 0);
- lldp->n_ref++;
-
- return lldp;
-}
-
-_public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
-
- if (!lldp)
- return NULL;
-
- assert(lldp->n_ref > 0);
- lldp->n_ref --;
+static sd_lldp* lldp_free(sd_lldp *lldp) {
+ assert(lldp);
- if (lldp->n_ref > 0)
- return NULL;
+ lldp->timer_event_source = sd_event_source_unref(lldp->timer_event_source);
lldp_reset(lldp);
sd_lldp_detach_event(lldp);
@@ -360,22 +354,26 @@ _public_ sd_lldp* sd_lldp_unref(sd_lldp *lldp) {
return mfree(lldp);
}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp, sd_lldp, lldp_free);
+
_public_ int sd_lldp_new(sd_lldp **ret) {
_cleanup_(sd_lldp_unrefp) sd_lldp *lldp = NULL;
int r;
assert_return(ret, -EINVAL);
- lldp = new0(sd_lldp, 1);
+ lldp = new(sd_lldp, 1);
if (!lldp)
return -ENOMEM;
- lldp->n_ref = 1;
- lldp->fd = -1;
- lldp->neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX;
- lldp->capability_mask = (uint16_t) -1;
+ *lldp = (sd_lldp) {
+ .n_ref = 1,
+ .fd = -1,
+ .neighbors_max = LLDP_DEFAULT_NEIGHBORS_MAX,
+ .capability_mask = (uint16_t) -1,
+ };
- lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_id_hash_ops);
+ lldp->neighbor_by_id = hashmap_new(&lldp_neighbor_hash_ops);
if (!lldp->neighbor_by_id)
return -ENOMEM;
@@ -388,10 +386,8 @@ _public_ int sd_lldp_new(sd_lldp **ret) {
return 0;
}
-static int neighbor_compare_func(const void *a, const void *b) {
- const sd_lldp_neighbor * const*x = a, * const *y = b;
-
- return lldp_neighbor_id_hash_ops.compare(&(*x)->id, &(*y)->id);
+static int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_neighbor * const *b) {
+ return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id);
}
static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
@@ -411,7 +407,6 @@ static int on_timer_event(sd_event_source *s, uint64_t usec, void *userdata) {
static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
sd_lldp_neighbor *n;
- int r;
assert(lldp);
@@ -419,35 +414,17 @@ static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
lldp_neighbor_start_ttl(neighbor);
n = prioq_peek(lldp->neighbor_by_expiry);
- if (!n) {
-
- if (lldp->timer_event_source)
- return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_OFF);
-
- return 0;
- }
-
- if (lldp->timer_event_source) {
- r = sd_event_source_set_time(lldp->timer_event_source, n->until);
- if (r < 0)
- return r;
-
- return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_ONESHOT);
- }
+ if (!n)
+ return event_source_disable(lldp->timer_event_source);
if (!lldp->event)
return 0;
- r = sd_event_add_time(lldp->event, &lldp->timer_event_source, clock_boottime_or_monotonic(), n->until, 0, on_timer_event, lldp);
- if (r < 0)
- return r;
-
- r = sd_event_source_set_priority(lldp->timer_event_source, lldp->event_priority);
- if (r < 0)
- return r;
-
- (void) sd_event_source_set_description(lldp->timer_event_source, "lldp-timer");
- return 0;
+ return event_reset_time(lldp->event, &lldp->timer_event_source,
+ clock_boottime_or_monotonic(),
+ n->until, 0,
+ on_timer_event, lldp,
+ lldp->event_priority, "lldp-timer", true);
}
_public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
@@ -479,7 +456,7 @@ _public_ int sd_lldp_get_neighbors(sd_lldp *lldp, sd_lldp_neighbor ***ret) {
assert((size_t) k == hashmap_size(lldp->neighbor_by_id));
/* Return things in a stable order */
- qsort(l, k, sizeof(sd_lldp_neighbor*), neighbor_compare_func);
+ typesafe_qsort(l, k, neighbor_compare_func);
*ret = l;
return k;
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index 2d81160b02..79b2ea8bf2 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -9,6 +9,7 @@
#include "sd-ndisc.h"
#include "alloc-util.h"
+#include "event-util.h"
#include "fd-util.h"
#include "icmp6-util.h"
#include "in-addr-util.h"
@@ -16,19 +17,30 @@
#include "ndisc-router.h"
#include "random-util.h"
#include "socket-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "util.h"
#define NDISC_TIMEOUT_NO_RA_USEC (NDISC_ROUTER_SOLICITATION_INTERVAL * NDISC_MAX_ROUTER_SOLICITATIONS)
+static const char * const ndisc_event_table[_SD_NDISC_EVENT_MAX] = {
+ [SD_NDISC_EVENT_TIMEOUT] = "timeout",
+ [SD_NDISC_EVENT_ROUTER] = "router",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ndisc_event, sd_ndisc_event);
+
static void ndisc_callback(sd_ndisc *ndisc, sd_ndisc_event event, sd_ndisc_router *rt) {
assert(ndisc);
+ assert(event >= 0 && event < _SD_NDISC_EVENT_MAX);
- log_ndisc("Invoking callback for '%c'.", event);
- if (!ndisc->callback)
+ if (!ndisc->callback) {
+ log_ndisc("Received '%s' event.", ndisc_event_to_string(event));
return;
+ }
+ log_ndisc("Invoking callback for '%s' event.", ndisc_event_to_string(event));
ndisc->callback(ndisc, event, rt, ndisc->userdata);
}
@@ -100,56 +112,42 @@ _public_ sd_event *sd_ndisc_get_event(sd_ndisc *nd) {
return nd->event;
}
-_public_ sd_ndisc *sd_ndisc_ref(sd_ndisc *nd) {
-
- if (!nd)
- return NULL;
-
- assert(nd->n_ref > 0);
- nd->n_ref++;
-
- return nd;
-}
-
-static int ndisc_reset(sd_ndisc *nd) {
+static void ndisc_reset(sd_ndisc *nd) {
assert(nd);
- nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
- nd->timeout_no_ra = sd_event_source_unref(nd->timeout_no_ra);
+ (void) event_source_disable(nd->timeout_event_source);
+ (void) event_source_disable(nd->timeout_no_ra);
nd->retransmit_time = 0;
nd->recv_event_source = sd_event_source_unref(nd->recv_event_source);
nd->fd = safe_close(nd->fd);
-
- return 0;
}
-_public_ sd_ndisc *sd_ndisc_unref(sd_ndisc *nd) {
-
- if (!nd)
- return NULL;
-
- assert(nd->n_ref > 0);
- nd->n_ref--;
+static sd_ndisc *ndisc_free(sd_ndisc *nd) {
+ assert(nd);
- if (nd->n_ref > 0)
- return NULL;
+ nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
+ nd->timeout_no_ra = sd_event_source_unref(nd->timeout_no_ra);
ndisc_reset(nd);
sd_ndisc_detach_event(nd);
return mfree(nd);
}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc, sd_ndisc, ndisc_free);
+
_public_ int sd_ndisc_new(sd_ndisc **ret) {
_cleanup_(sd_ndisc_unrefp) sd_ndisc *nd = NULL;
assert_return(ret, -EINVAL);
- nd = new0(sd_ndisc, 1);
+ nd = new(sd_ndisc, 1);
if (!nd)
return -ENOMEM;
- nd->n_ref = 1;
- nd->fd = -1;
+ *nd = (sd_ndisc) {
+ .n_ref = 1,
+ .fd = -1,
+ };
*ret = TAKE_PTR(nd);
@@ -238,14 +236,21 @@ static int ndisc_recv(sd_event_source *s, int fd, uint32_t revents, void *userda
break;
case -EPFNOSUPPORT:
- log_ndisc("Received invalid source address from ICMPv6 socket.");
+ log_ndisc("Received invalid source address from ICMPv6 socket. Ignoring.");
+ break;
+
+ case -EAGAIN: /* ignore spurious wakeups */
+ break;
+
+ default:
+ log_ndisc_errno(r, "Unexpected error while reading from ICMPv6, ignoring: %m");
break;
}
return 0;
}
- nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
+ (void) event_source_disable(nd->timeout_event_source);
return ndisc_handle_datagram(nd, rt);
}
@@ -257,10 +262,10 @@ static usec_t ndisc_timeout_compute_random(usec_t val) {
}
static int ndisc_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
+ char time_string[FORMAT_TIMESPAN_MAX];
sd_ndisc *nd = userdata;
usec_t time_now;
int r;
- char time_string[FORMAT_TIMESPAN_MAX];
assert(s);
assert(nd);
@@ -268,8 +273,6 @@ static int ndisc_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
assert_se(sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now) >= 0);
- nd->timeout_event_source = sd_event_source_unref(nd->timeout_event_source);
-
if (!nd->retransmit_time)
nd->retransmit_time = ndisc_timeout_compute_random(NDISC_ROUTER_SOLICITATION_INTERVAL);
else {
@@ -279,25 +282,14 @@ static int ndisc_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
nd->retransmit_time += ndisc_timeout_compute_random(nd->retransmit_time);
}
- r = sd_event_add_time(nd->event, &nd->timeout_event_source,
- clock_boottime_or_monotonic(),
- time_now + nd->retransmit_time,
- 10 * USEC_PER_MSEC, ndisc_timeout, nd);
+ r = event_reset_time(nd->event, &nd->timeout_event_source,
+ clock_boottime_or_monotonic(),
+ time_now + nd->retransmit_time, 10 * USEC_PER_MSEC,
+ ndisc_timeout, nd,
+ nd->event_priority, "ndisc-timeout-no-ra", true);
if (r < 0)
goto fail;
- r = sd_event_source_set_priority(nd->timeout_event_source, nd->event_priority);
- if (r < 0)
- goto fail;
-
- (void) sd_event_source_set_description(nd->timeout_event_source, "ndisc-timeout-no-ra");
-
- r = sd_event_source_set_enabled(nd->timeout_event_source, SD_EVENT_ONESHOT);
- if (r < 0) {
- log_ndisc_errno(r, "Error reenabling timer: %m");
- goto fail;
- }
-
r = icmp6_send_router_solicitation(nd->fd, &nd->mac_addr);
if (r < 0) {
log_ndisc_errno(r, "Error sending Router Solicitation: %m");
@@ -311,7 +303,7 @@ static int ndisc_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
return 0;
fail:
- sd_ndisc_stop(nd);
+ (void) sd_ndisc_stop(nd);
return 0;
}
@@ -323,7 +315,7 @@ static int ndisc_timeout_no_ra(sd_event_source *s, uint64_t usec, void *userdata
log_ndisc("No RA received before link confirmation timeout");
- nd->timeout_no_ra = sd_event_source_unref(nd->timeout_no_ra);
+ (void) event_source_disable(nd->timeout_no_ra);
ndisc_callback(nd, SD_NDISC_EVENT_TIMEOUT, NULL);
return 0;
@@ -353,7 +345,6 @@ _public_ int sd_ndisc_start(sd_ndisc *nd) {
return 0;
assert(!nd->recv_event_source);
- assert(!nd->timeout_event_source);
r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
@@ -373,29 +364,22 @@ _public_ int sd_ndisc_start(sd_ndisc *nd) {
(void) sd_event_source_set_description(nd->recv_event_source, "ndisc-receive-message");
- r = sd_event_add_time(nd->event, &nd->timeout_event_source, clock_boottime_or_monotonic(), 0, 0, ndisc_timeout, nd);
+ r = event_reset_time(nd->event, &nd->timeout_event_source,
+ clock_boottime_or_monotonic(),
+ 0, 0,
+ ndisc_timeout, nd,
+ nd->event_priority, "ndisc-timeout", true);
if (r < 0)
goto fail;
- r = sd_event_source_set_priority(nd->timeout_event_source, nd->event_priority);
+ r = event_reset_time(nd->event, &nd->timeout_no_ra,
+ clock_boottime_or_monotonic(),
+ time_now + NDISC_TIMEOUT_NO_RA_USEC, 10 * USEC_PER_MSEC,
+ ndisc_timeout_no_ra, nd,
+ nd->event_priority, "ndisc-timeout-no-ra", true);
if (r < 0)
goto fail;
- (void) sd_event_source_set_description(nd->timeout_event_source, "ndisc-timeout");
-
- r = sd_event_add_time(nd->event, &nd->timeout_no_ra,
- clock_boottime_or_monotonic(),
- time_now + NDISC_TIMEOUT_NO_RA_USEC,
- 10 * USEC_PER_MSEC, ndisc_timeout_no_ra, nd);
- if (r < 0)
- goto fail;
-
- r = sd_event_source_set_priority(nd->timeout_no_ra, nd->event_priority);
- if (r < 0)
- goto fail;
-
- (void) sd_event_source_set_description(nd->timeout_no_ra, "ndisc-timeout-no-ra");
-
log_ndisc("Started IPv6 Router Solicitation client");
return 1;
diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c
index 86750b876c..098e01fb82 100644
--- a/src/libsystemd-network/sd-radv.c
+++ b/src/libsystemd-network/sd-radv.c
@@ -9,32 +9,35 @@
#include "sd-radv.h"
-#include "macro.h"
#include "alloc-util.h"
#include "dns-domain.h"
+#include "ether-addr-util.h"
+#include "event-util.h"
#include "fd-util.h"
#include "icmp6-util.h"
#include "in-addr-util.h"
+#include "io-util.h"
+#include "macro.h"
#include "radv-internal.h"
+#include "random-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "random-util.h"
_public_ int sd_radv_new(sd_radv **ret) {
_cleanup_(sd_radv_unrefp) sd_radv *ra = NULL;
assert_return(ret, -EINVAL);
- ra = new0(sd_radv, 1);
+ ra = new(sd_radv, 1);
if (!ra)
return -ENOMEM;
- ra->n_ref = 1;
- ra->fd = -1;
-
- LIST_HEAD_INIT(ra->prefixes);
+ *ra = (sd_radv) {
+ .n_ref = 1,
+ .fd = -1,
+ };
*ret = TAKE_PTR(ra);
@@ -77,8 +80,7 @@ _public_ sd_event *sd_radv_get_event(sd_radv *ra) {
static void radv_reset(sd_radv *ra) {
assert(ra);
- ra->timeout_event_source =
- sd_event_source_unref(ra->timeout_event_source);
+ (void) event_source_disable(ra->timeout_event_source);
ra->recv_event_source =
sd_event_source_unref(ra->recv_event_source);
@@ -86,26 +88,10 @@ static void radv_reset(sd_radv *ra) {
ra->ra_sent = 0;
}
-_public_ sd_radv *sd_radv_ref(sd_radv *ra) {
+static sd_radv *radv_free(sd_radv *ra) {
if (!ra)
return NULL;
- assert(ra->n_ref > 0);
- ra->n_ref++;
-
- return ra;
-}
-
-_public_ sd_radv *sd_radv_unref(sd_radv *ra) {
- if (!ra)
- return NULL;
-
- assert(ra->n_ref > 0);
- ra->n_ref--;
-
- if (ra->n_ref > 0)
- return NULL;
-
while (ra->prefixes) {
sd_radv_prefix *p = ra->prefixes;
@@ -116,6 +102,8 @@ _public_ sd_radv *sd_radv_unref(sd_radv *ra) {
free(ra->rdnss);
free(ra->dnssl);
+ ra->timeout_event_source = sd_event_source_unref(ra->timeout_event_source);
+
radv_reset(ra);
sd_radv_detach_event(ra);
@@ -125,9 +113,9 @@ _public_ sd_radv *sd_radv_unref(sd_radv *ra) {
return mfree(ra);
}
-static int radv_send(sd_radv *ra, const struct in6_addr *dst,
- const uint32_t router_lifetime) {
- static const struct ether_addr mac_zero = {};
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free);
+
+static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_lifetime) {
sd_radv_prefix *p;
struct sockaddr_in6 dst_addr = {
.sin6_family = AF_INET6,
@@ -159,35 +147,31 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst,
usec_t time_now;
int r;
+ assert(ra);
+
r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
return r;
- if (dst && !in_addr_is_null(AF_INET6, (union in_addr_union*) dst))
+ if (dst && !IN6_IS_ADDR_UNSPECIFIED(dst))
dst_addr.sin6_addr = *dst;
adv.nd_ra_type = ND_ROUTER_ADVERT;
adv.nd_ra_curhoplimit = ra->hop_limit;
adv.nd_ra_flags_reserved = ra->flags;
adv.nd_ra_router_lifetime = htobe16(router_lifetime);
- iov[msg.msg_iovlen].iov_base = &adv;
- iov[msg.msg_iovlen].iov_len = sizeof(adv);
- msg.msg_iovlen++;
+ iov[msg.msg_iovlen++] = IOVEC_MAKE(&adv, sizeof(adv));
/* MAC address is optional, either because the link does not use L2
addresses or load sharing is desired. See RFC 4861, Section 4.2 */
- if (memcmp(&mac_zero, &ra->mac_addr, sizeof(mac_zero))) {
+ if (!ether_addr_is_null(&ra->mac_addr)) {
opt_mac.slladdr = ra->mac_addr;
- iov[msg.msg_iovlen].iov_base = &opt_mac;
- iov[msg.msg_iovlen].iov_len = sizeof(opt_mac);
- msg.msg_iovlen++;
+ iov[msg.msg_iovlen++] = IOVEC_MAKE(&opt_mac, sizeof(opt_mac));
}
if (ra->mtu) {
opt_mtu.nd_opt_mtu_mtu = htobe32(ra->mtu);
- iov[msg.msg_iovlen].iov_base = &opt_mtu;
- iov[msg.msg_iovlen].iov_len = sizeof(opt_mtu);
- msg.msg_iovlen++;
+ iov[msg.msg_iovlen++] = IOVEC_MAKE(&opt_mtu, sizeof(opt_mtu));
}
LIST_FOREACH(prefix, p, ra->prefixes) {
@@ -203,22 +187,14 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst,
else
p->opt.preferred_lifetime = htobe32((p->preferred_until - time_now) / USEC_PER_SEC);
}
- iov[msg.msg_iovlen].iov_base = &p->opt;
- iov[msg.msg_iovlen].iov_len = sizeof(p->opt);
- msg.msg_iovlen++;
+ iov[msg.msg_iovlen++] = IOVEC_MAKE(&p->opt, sizeof(p->opt));
}
- if (ra->rdnss) {
- iov[msg.msg_iovlen].iov_base = ra->rdnss;
- iov[msg.msg_iovlen].iov_len = ra->rdnss->length * 8;
- msg.msg_iovlen++;
- }
+ if (ra->rdnss)
+ iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->rdnss, ra->rdnss->length * 8);
- if (ra->dnssl) {
- iov[msg.msg_iovlen].iov_base = ra->dnssl;
- iov[msg.msg_iovlen].iov_len = ra->dnssl->length * 8;
- msg.msg_iovlen++;
- }
+ if (ra->dnssl)
+ iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->dnssl, ra->dnssl->length * 8);
if (sendmsg(ra->fd, &msg, 0) < 0)
return -errno;
@@ -240,13 +216,12 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
assert(ra->event);
buflen = next_datagram_size_fd(fd);
-
- if ((unsigned) buflen < sizeof(struct nd_router_solicit))
- return log_radv("Too short packet received");
+ if (buflen < 0)
+ return (int) buflen;
buf = new0(char, buflen);
if (!buf)
- return 0;
+ return -ENOMEM;
r = icmp6_receive(fd, buf, buflen, &src, &timestamp);
if (r < 0) {
@@ -264,21 +239,29 @@ static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdat
log_radv("Received invalid source address from ICMPv6 socket. Ignoring.");
break;
+ case -EAGAIN: /* ignore spurious wakeups */
+ break;
+
default:
- log_radv_warning_errno(r, "Error receiving from ICMPv6 socket: %m");
+ log_radv_errno(r, "Unexpected error receiving from ICMPv6 socket: %m");
break;
}
return 0;
}
+ if ((size_t) buflen < sizeof(struct nd_router_solicit)) {
+ log_radv("Too short packet received");
+ return 0;
+ }
+
(void) in_addr_to_string(AF_INET6, (union in_addr_union*) &src, &addr);
r = radv_send(ra, &src, ra->lifetime);
if (r < 0)
- log_radv_warning_errno(r, "Unable to send solicited Router Advertisement to %s: %m", addr);
+ log_radv_errno(r, "Unable to send solicited Router Advertisement to %s: %m", strnull(addr));
else
- log_radv("Sent solicited Router Advertisement to %s", addr);
+ log_radv("Sent solicited Router Advertisement to %s", strnull(addr));
return 0;
}
@@ -301,15 +284,13 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
assert(ra);
assert(ra->event);
- ra->timeout_event_source = sd_event_source_unref(ra->timeout_event_source);
-
r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now);
if (r < 0)
goto fail;
r = radv_send(ra, NULL, ra->lifetime);
if (r < 0)
- log_radv_warning_errno(r, "Unable to send Router Advertisement: %m");
+ log_radv_errno(r, "Unable to send Router Advertisement: %m");
/* RFC 4861, Section 6.2.4, sending initial Router Advertisements */
if (ra->ra_sent < SD_RADV_MAX_INITIAL_RTR_ADVERTISEMENTS) {
@@ -323,28 +304,20 @@ static int radv_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
format_timespan(time_string, FORMAT_TIMESPAN_MAX,
timeout, USEC_PER_SEC));
- r = sd_event_add_time(ra->event, &ra->timeout_event_source,
- clock_boottime_or_monotonic(),
- time_now + timeout, MSEC_PER_SEC,
- radv_timeout, ra);
- if (r < 0)
- goto fail;
-
- r = sd_event_source_set_priority(ra->timeout_event_source,
- ra->event_priority);
- if (r < 0)
- goto fail;
-
- r = sd_event_source_set_description(ra->timeout_event_source,
- "radv-timeout");
+ r = event_reset_time(ra->event, &ra->timeout_event_source,
+ clock_boottime_or_monotonic(),
+ time_now + timeout, MSEC_PER_SEC,
+ radv_timeout, ra,
+ ra->event_priority, "radv-timeout", true);
if (r < 0)
goto fail;
ra->ra_sent++;
+ return 0;
+
fail:
- if (r < 0)
- sd_radv_stop(ra);
+ sd_radv_stop(ra);
return 0;
}
@@ -363,7 +336,7 @@ _public_ int sd_radv_stop(sd_radv *ra) {
with zero lifetime */
r = radv_send(ra, NULL, 0);
if (r < 0)
- log_radv_warning_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
+ log_radv_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
radv_reset(ra);
ra->fd = safe_close(ra->fd);
@@ -373,7 +346,7 @@ _public_ int sd_radv_stop(sd_radv *ra) {
}
_public_ int sd_radv_start(sd_radv *ra) {
- int r = 0;
+ int r;
assert_return(ra, -EINVAL);
assert_return(ra->event, -EINVAL);
@@ -382,20 +355,14 @@ _public_ int sd_radv_start(sd_radv *ra) {
if (ra->state != SD_RADV_STATE_IDLE)
return 0;
- r = sd_event_add_time(ra->event, &ra->timeout_event_source,
- clock_boottime_or_monotonic(), 0, 0,
- radv_timeout, ra);
- if (r < 0)
- goto fail;
-
- r = sd_event_source_set_priority(ra->timeout_event_source,
- ra->event_priority);
+ r = event_reset_time(ra->event, &ra->timeout_event_source,
+ clock_boottime_or_monotonic(),
+ 0, 0,
+ radv_timeout, ra,
+ ra->event_priority, "radv-timeout", true);
if (r < 0)
goto fail;
- (void) sd_event_source_set_description(ra->timeout_event_source,
- "radv-timeout");
-
r = icmp6_bind_router_advertisement(ra->ifindex);
if (r < 0)
goto fail;
@@ -523,7 +490,7 @@ _public_ int sd_radv_set_preference(sd_radv *ra, unsigned preference) {
return r;
}
-_public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, bool dynamic) {
+_public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) {
sd_radv_prefix *cur;
int r;
_cleanup_free_ char *addr_p = NULL;
@@ -536,6 +503,10 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, bool dynamic) {
if (!p)
return -EINVAL;
+ /* Refuse prefixes that don't have a prefix set */
+ if (IN6_IS_ADDR_UNSPECIFIED(&p->opt.in6_addr))
+ return -ENOEXEC;
+
LIST_FOREACH(prefix, cur, ra->prefixes) {
r = in_addr_prefix_intersect(AF_INET6,
@@ -718,56 +689,33 @@ _public_ int sd_radv_set_dnssl(sd_radv *ra, uint32_t lifetime,
}
_public_ int sd_radv_prefix_new(sd_radv_prefix **ret) {
- _cleanup_(sd_radv_prefix_unrefp) sd_radv_prefix *p = NULL;
+ sd_radv_prefix *p;
assert_return(ret, -EINVAL);
- p = new0(sd_radv_prefix, 1);
+ p = new(sd_radv_prefix, 1);
if (!p)
return -ENOMEM;
- p->n_ref = 1;
+ *p = (sd_radv_prefix) {
+ .n_ref = 1,
- p->opt.type = ND_OPT_PREFIX_INFORMATION;
- p->opt.length = (sizeof(p->opt) - 1) /8 + 1;
+ .opt.type = ND_OPT_PREFIX_INFORMATION,
+ .opt.length = (sizeof(p->opt) - 1)/8 + 1,
+ .opt.prefixlen = 64,
- p->opt.prefixlen = 64;
+ /* RFC 4861, Section 6.2.1 */
+ .opt.flags = ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO,
- /* RFC 4861, Section 6.2.1 */
- SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_ONLINK, true);
- SET_FLAG(p->opt.flags, ND_OPT_PI_FLAG_AUTO, true);
- p->opt.preferred_lifetime = htobe32(604800);
- p->opt.valid_lifetime = htobe32(2592000);
-
- LIST_INIT(prefix, p);
-
- *ret = TAKE_PTR(p);
+ .opt.preferred_lifetime = htobe32(604800),
+ .opt.valid_lifetime = htobe32(2592000),
+ };
+ *ret = p;
return 0;
}
-_public_ sd_radv_prefix *sd_radv_prefix_ref(sd_radv_prefix *p) {
- if (!p)
- return NULL;
-
- assert(p->n_ref > 0);
- p->n_ref++;
-
- return p;
-}
-
-_public_ sd_radv_prefix *sd_radv_prefix_unref(sd_radv_prefix *p) {
- if (!p)
- return NULL;
-
- assert(p->n_ref > 0);
- p->n_ref--;
-
- if (p->n_ref > 0)
- return NULL;
-
- return mfree(p);
-}
+DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_prefix, sd_radv_prefix, mfree);
_public_ int sd_radv_prefix_set_prefix(sd_radv_prefix *p, const struct in6_addr *in6_addr,
unsigned char prefixlen) {
diff --git a/src/libsystemd-network/test-acd.c b/src/libsystemd-network/test-acd.c
index 079e760996..302eea2c30 100644
--- a/src/libsystemd-network/test-acd.c
+++ b/src/libsystemd-network/test-acd.c
@@ -13,6 +13,7 @@
#include "in-addr-util.h"
#include "netlink-util.h"
+#include "tests.h"
#include "util.h"
static void acd_handler(sd_ipv4acd *acd, int event, void *userdata) {
@@ -83,9 +84,7 @@ static int test_acd(const char *ifname, const char *address) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
if (argc == 3)
return test_acd(argv[1], argv[2]);
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 0e257633b8..fe6788d91b 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
+#include <net/if.h>
#include "sd-dhcp-client.h"
#include "sd-event.h"
@@ -16,6 +17,8 @@
#include "dhcp-internal.h"
#include "dhcp-protocol.h"
#include "fd-util.h"
+#include "random-util.h"
+#include "tests.h"
#include "util.h"
static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
@@ -152,6 +155,35 @@ static void test_checksum(void) {
assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae));
}
+static void test_dhcp_identifier_set_iaid(void) {
+ uint32_t iaid_legacy;
+ be32_t iaid;
+ int ifindex;
+
+ for (;;) {
+ char ifname[IFNAMSIZ];
+
+ /* try to find an ifindex which does not exist. I causes dhcp_identifier_set_iaid()
+ * to hash the MAC address. */
+ pseudo_random_bytes(&ifindex, sizeof(ifindex));
+ if (ifindex > 0 && !if_indextoname(ifindex, ifname))
+ break;
+ }
+
+ assert_se(dhcp_identifier_set_iaid(ifindex, mac_addr, sizeof(mac_addr), true, &iaid_legacy) >= 0);
+ assert_se(dhcp_identifier_set_iaid(ifindex, mac_addr, sizeof(mac_addr), false, &iaid) >= 0);
+
+ /* we expect, that the MAC address was hashed. The legacy value is in native
+ * endianness. */
+ assert_se(iaid_legacy == 0x8dde4ba8u);
+ assert_se(iaid == htole32(0x8dde4ba8u));
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ assert_se(iaid == iaid_legacy);
+#else
+ assert_se(iaid == __bswap_32(iaid_legacy));
+#endif
+}
+
static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
switch(code) {
case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
@@ -161,7 +193,7 @@ static int check_options(uint8_t code, uint8_t len, const void *option, void *us
size_t duid_len;
assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0);
- assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, &iaid) >= 0);
+ assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, true, &iaid) >= 0);
assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
assert_se(len == 19);
@@ -231,7 +263,7 @@ int dhcp_network_bind_raw_socket(
const uint8_t *addr, size_t addr_len,
uint16_t arp_type, uint16_t port) {
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
return -errno;
return test_fd[0];
@@ -240,7 +272,7 @@ int dhcp_network_bind_raw_socket(
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
int fd;
- fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+ fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
if (fd < 0)
return -errno;
@@ -524,15 +556,14 @@ static void test_addr_acq(sd_event *e) {
int main(int argc, char *argv[]) {
_cleanup_(sd_event_unrefp) sd_event *e;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
assert_se(sd_event_new(&e) >= 0);
test_request_basic(e);
test_request_anonymize(e);
test_checksum();
+ test_dhcp_identifier_set_iaid();
test_discover_message(e);
test_addr_acq(e);
diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c
index 815b11e997..ea998939bc 100644
--- a/src/libsystemd-network/test-dhcp-server.c
+++ b/src/libsystemd-network/test-dhcp-server.c
@@ -9,6 +9,7 @@
#include "sd-event.h"
#include "dhcp-server-internal.h"
+#include "tests.h"
static void test_pool(struct in_addr *address, unsigned size, int ret) {
_cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
@@ -54,9 +55,8 @@ static int test_basic(sd_event *event) {
test_pool(&address_lo, 1, 0);
r = sd_dhcp_server_start(server);
-
if (r == -EPERM)
- return EXIT_TEST_SKIP;
+ return log_info_errno(r, "sd_dhcp_server_start failed: %m");
assert_se(r >= 0);
assert_se(sd_dhcp_server_start(server) == -EBUSY);
@@ -229,15 +229,13 @@ int main(int argc, char *argv[]) {
_cleanup_(sd_event_unrefp) sd_event *e;
int r;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
assert_se(sd_event_new(&e) >= 0);
r = test_basic(e);
if (r != 0)
- return r;
+ return log_tests_skipped("cannot start dhcp server");
test_message_handler();
test_client_id_hash();
diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c
index 27c0002fe2..fa94b3cb75 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -19,14 +19,14 @@
#include "fd-util.h"
#include "macro.h"
#include "socket-util.h"
+#include "tests.h"
+#include "util.h"
#include "virt.h"
static struct ether_addr mac_addr = {
.ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
};
-static bool verbose = true;
-
static sd_event_source *hangcheck;
static int test_dhcp_fd[2];
static int test_index = 42;
@@ -36,9 +36,9 @@ static uint8_t test_duid[14] = { };
static int test_client_basic(sd_event *e) {
sd_dhcp6_client *client;
+ int v;
- if (verbose)
- printf("* %s\n", __FUNCTION__);
+ log_debug("/* %s */", __func__);
assert_se(sd_dhcp6_client_new(&client) >= 0);
assert_se(client);
@@ -67,6 +67,36 @@ static int test_client_basic(sd_event *e) {
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
+ assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0);
+ v = 0;
+ assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
+ assert_se(v);
+ assert_se(sd_dhcp6_client_set_information_request(client, 0) >= 0);
+ v = 42;
+ assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
+ assert_se(v == 0);
+
+ v = 0;
+ assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
+ assert_se(v);
+ v = 0;
+ assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
+ assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
+ assert_se(v);
+ v = 42;
+ assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
+ assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
+ assert_se(v);
+
+ assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
+ assert_se(sd_dhcp6_client_set_prefix_delegation(client, 1) >= 0);
+ v = 0;
+ assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
+ assert_se(v);
+ v = 0;
+ assert_se(sd_dhcp6_client_get_prefix_delegation(client, &v) >= 0);
+ assert_se(v);
+
assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
assert_se(sd_dhcp6_client_detach_event(client) >= 0);
@@ -97,8 +127,7 @@ static int test_option(sd_event *e) {
size_t zero = 0, pos = 3;
size_t buflen = sizeof(packet), outlen = sizeof(result);
- if (verbose)
- printf("* %s\n", __FUNCTION__);
+ log_debug("/* %s */", __func__);
assert_se(buflen == outlen);
@@ -211,8 +240,7 @@ static int test_option_status(sd_event *e) {
DHCP6IA ia, pd;
int r = 0;
- if (verbose)
- printf("* %s\n", __FUNCTION__);
+ log_debug("/* %s */", __func__);
zero(ia);
option = (DHCP6Option *)option1;
@@ -345,8 +373,7 @@ static int test_advertise_option(sd_event *e) {
struct in6_addr *addrs;
char **domains;
- if (verbose)
- printf("* %s\n", __FUNCTION__);
+ log_debug("/* %s */", __func__);
assert_se(len >= sizeof(DHCP6Message));
@@ -493,6 +520,8 @@ static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
struct in6_addr *addrs;
char **domains;
+ log_debug("/* %s */", __func__);
+
assert_se(e);
assert_se(event == SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE);
@@ -510,9 +539,6 @@ static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
- if (verbose)
- printf(" got DHCPv6 event %d\n", event);
-
sd_event_exit(e, 0);
}
@@ -543,8 +569,9 @@ static int test_client_verify_request(DHCP6Message *request, size_t len) {
be32_t val;
uint32_t lt_pref, lt_valid;
- assert_se(request->type == DHCP6_REQUEST);
+ log_debug("/* %s */", __func__);
+ assert_se(request->type == DHCP6_REQUEST);
assert_se(dhcp6_lease_new(&lease) >= 0);
len -= sizeof(DHCP6Message);
@@ -651,6 +678,8 @@ static int test_client_verify_solicit(DHCP6Message *solicit, size_t len) {
found_elapsed_time = false, found_fqdn = false;
size_t pos = 0;
+ log_debug("/* %s */", __func__);
+
assert_se(solicit->type == DHCP6_SOLICIT);
len -= sizeof(DHCP6Message);
@@ -718,6 +747,8 @@ static void test_client_information_cb(sd_dhcp6_client *client, int event,
struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
char **domains;
+ log_debug("/* %s */", __func__);
+
assert_se(e);
assert_se(event == SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST);
@@ -733,9 +764,6 @@ static void test_client_information_cb(sd_dhcp6_client *client, int event,
assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1);
assert_se(!memcmp(addrs, &msg_advertise[159], 16));
- if (verbose)
- printf(" got DHCPv6 event %d\n", event);
-
assert_se(sd_dhcp6_client_set_information_request(client, false) == -EBUSY);
assert_se(sd_dhcp6_client_set_callback(client, NULL, e) >= 0);
assert_se(sd_dhcp6_client_stop(client) >= 0);
@@ -759,8 +787,9 @@ static int test_client_verify_information_request(DHCP6Message *information_requ
struct in6_addr addr;
uint32_t lt_pref, lt_valid;
- assert_se(information_request->type == DHCP6_INFORMATION_REQUEST);
+ log_debug("/* %s */", __func__);
+ assert_se(information_request->type == DHCP6_INFORMATION_REQUEST);
assert_se(dhcp6_lease_new(&lease) >= 0);
len -= sizeof(DHCP6Message);
@@ -824,7 +853,6 @@ int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
assert_se(server_address);
assert_se(packet);
assert_se(len > sizeof(DHCP6Message) + 4);
-
assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast));
message = (DHCP6Message *)packet;
@@ -851,7 +879,7 @@ int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
assert_se(index == test_index);
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd) < 0)
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_dhcp_fd) < 0)
return -errno;
return test_dhcp_fd[0];
@@ -861,10 +889,9 @@ static int test_client_solicit(sd_event *e) {
sd_dhcp6_client *client;
usec_t time_now = now(clock_boottime_or_monotonic());
struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
- int val = true;
+ int val;
- if (verbose)
- printf("* %s\n", __FUNCTION__);
+ log_debug("/* %s */", __func__);
assert_se(sd_dhcp6_client_new(&client) >= 0);
assert_se(client);
@@ -878,10 +905,10 @@ static int test_client_solicit(sd_event *e) {
assert_se(sd_dhcp6_client_set_fqdn(client, "host.lab.intra") == 1);
assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
- assert_se(val == false);
- assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
+ assert_se(val == 0);
+ assert_se(sd_dhcp6_client_set_information_request(client, 42) >= 0);
assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
- assert_se(val == true);
+ assert_se(val);
assert_se(sd_dhcp6_client_set_callback(client,
test_client_information_cb, e) >= 0);
@@ -910,9 +937,7 @@ int main(int argc, char *argv[]) {
assert_se(sd_event_new(&e) >= 0);
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_client_basic(e);
test_option(e);
diff --git a/src/libsystemd-network/test-ipv4ll-manual.c b/src/libsystemd-network/test-ipv4ll-manual.c
index 125133f039..fd827ff401 100644
--- a/src/libsystemd-network/test-ipv4ll-manual.c
+++ b/src/libsystemd-network/test-ipv4ll-manual.c
@@ -15,6 +15,7 @@
#include "netlink-util.h"
#include "parse-util.h"
#include "string-util.h"
+#include "tests.h"
#include "util.h"
static void ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
@@ -95,9 +96,7 @@ static int test_ll(const char *ifname, const char *seed) {
}
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
if (argc == 2)
return test_ll(argv[1], NULL);
diff --git a/src/libsystemd-network/test-ipv4ll.c b/src/libsystemd-network/test-ipv4ll.c
index ee9cce02a8..2e1488cb0a 100644
--- a/src/libsystemd-network/test-ipv4ll.c
+++ b/src/libsystemd-network/test-ipv4ll.c
@@ -15,6 +15,7 @@
#include "arp-util.h"
#include "fd-util.h"
#include "socket-util.h"
+#include "tests.h"
#include "util.h"
static bool verbose = false;
@@ -78,7 +79,7 @@ int arp_send_announcement(int fd, int ifindex,
}
int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac) {
- if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0)
+ if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
return -errno;
return test_fd[0];
@@ -193,9 +194,7 @@ static void test_basic_request(sd_event *e) {
int main(int argc, char *argv[]) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
assert_se(sd_event_new(&e) >= 0);
diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c
index ac8ba2b707..cb4545d901 100644
--- a/src/libsystemd-network/test-lldp.c
+++ b/src/libsystemd-network/test-lldp.c
@@ -24,7 +24,7 @@ static int test_fd[2] = { -1, -1 };
static int lldp_handler_calls;
int lldp_network_bind_raw_socket(int ifindex) {
- if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0)
+ if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
return -errno;
return test_fd[0];
@@ -229,6 +229,135 @@ static void test_receive_oui_packet(sd_event *e) {
assert_se(stop_lldp(lldp) == 0);
}
+static void test_multiple_neighbors_sorted(sd_event *e) {
+
+ static const uint8_t frame1[] = {
+ /* Ethernet header */
+ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
+ 0x88, 0xcc, /* Ethertype */
+ /* LLDP mandatory TLVs */
+ 0x02, 0x04, 0x01, '1', '/', '2', /* Chassis component: "1/2" */
+ 0x04, 0x04, 0x02, '2', '/', '3', /* Port component: "2/3" */
+ 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */
+ 0x00, 0x00 /* End Of LLDPDU */
+ };
+ static const uint8_t frame2[] = {
+ /* Ethernet header */
+ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
+ 0x88, 0xcc, /* Ethertype */
+ /* LLDP mandatory TLVs */
+ 0x02, 0x04, 0x01, '2', '/', '1', /* Chassis component: "2/1" */
+ 0x04, 0x04, 0x02, '1', '/', '3', /* Port component: "1/3" */
+ 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */
+ 0x00, 0x00 /* End Of LLDPDU */
+ };
+ static const uint8_t frame3[] = {
+ /* Ethernet header */
+ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
+ 0x88, 0xcc, /* Ethertype */
+ /* LLDP mandatory TLVs */
+ 0x02, 0x05, 0x01, '2', '/', '1', '0', /* Chassis component: "2/10" */
+ 0x04, 0x04, 0x02, '1', '/', '0', /* Port component: "1/0" */
+ 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */
+ 0x00, 0x00 /* End Of LLDPDU */
+ };
+ static const uint8_t frame4[] = {
+ /* Ethernet header */
+ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
+ 0x88, 0xcc, /* Ethertype */
+ /* LLDP mandatory TLVs */
+ 0x02, 0x05, 0x01, '2', '/', '1', '9', /* Chassis component: "2/19" */
+ 0x04, 0x04, 0x02, '1', '/', '0', /* Port component: "1/0" */
+ 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */
+ 0x00, 0x00 /* End Of LLDPDU */
+ };
+ static const uint8_t frame5[] = {
+ /* Ethernet header */
+ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
+ 0x88, 0xcc, /* Ethertype */
+ /* LLDP mandatory TLVs */
+ 0x02, 0x04, 0x01, '1', '/', '2', /* Chassis component: "1/2" */
+ 0x04, 0x05, 0x02, '2', '/', '1', '0', /* Port component: "2/10" */
+ 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */
+ 0x00, 0x00 /* End Of LLDPDU */
+ };
+ static const uint8_t frame6[] = {
+ /* Ethernet header */
+ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */
+ 0x88, 0xcc, /* Ethertype */
+ /* LLDP mandatory TLVs */
+ 0x02, 0x04, 0x01, '1', '/', '2', /* Chassis component: "1/2" */
+ 0x04, 0x05, 0x02, '2', '/', '3', '9', /* Port component: "2/10" */
+ 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */
+ 0x00, 0x00 /* End Of LLDPDU */
+ };
+ static const char* expected[] = {
+ /* ordered pairs of Chassis+Port */
+ "1/2", "2/10",
+ "1/2", "2/3",
+ "1/2", "2/39",
+ "2/1", "1/3",
+ "2/10", "1/0",
+ "2/19", "1/0",
+ };
+
+ sd_lldp *lldp;
+ sd_lldp_neighbor **neighbors;
+ int i;
+ uint8_t type;
+ const void *data;
+ size_t length, expected_length;
+ uint16_t ttl;
+
+ lldp_handler_calls = 0;
+ assert_se(start_lldp(&lldp, e, lldp_handler, NULL) == 0);
+
+ assert_se(write(test_fd[1], frame1, sizeof(frame1)) == sizeof(frame1));
+ sd_event_run(e, 0);
+ assert_se(write(test_fd[1], frame2, sizeof(frame2)) == sizeof(frame2));
+ sd_event_run(e, 0);
+ assert_se(write(test_fd[1], frame3, sizeof(frame3)) == sizeof(frame3));
+ sd_event_run(e, 0);
+ assert_se(write(test_fd[1], frame4, sizeof(frame4)) == sizeof(frame4));
+ sd_event_run(e, 0);
+ assert_se(write(test_fd[1], frame5, sizeof(frame5)) == sizeof(frame5));
+ sd_event_run(e, 0);
+ assert_se(write(test_fd[1], frame6, sizeof(frame6)) == sizeof(frame6));
+ sd_event_run(e, 0);
+ assert_se(lldp_handler_calls == 6);
+
+ assert_se(sd_lldp_get_neighbors(lldp, &neighbors) == 6);
+
+ for (i = 0; i < 6; i++) {
+ assert_se(sd_lldp_neighbor_get_chassis_id(neighbors[i], &type, &data, &length) == 0);
+ assert_se(type == SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT);
+ expected_length = strlen(expected[2 * i]);
+ assert_se(length == expected_length);
+ assert_se(memcmp(data, expected[2 * i], expected_length) == 0);
+
+ assert_se(sd_lldp_neighbor_get_port_id(neighbors[i], &type, &data, &length) == 0);
+ assert_se(type == SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT);
+ expected_length = strlen(expected[2 * i + 1]);
+ assert_se(length == expected_length);
+ assert_se(memcmp(data, expected[2 * i + 1], expected_length) == 0);
+
+ assert_se(sd_lldp_neighbor_get_ttl(neighbors[i], &ttl) == 0);
+ assert_se(ttl == 120);
+ }
+
+ for (i = 0; i < 6; i++)
+ sd_lldp_neighbor_unref(neighbors[i]);
+ free(neighbors);
+
+ assert_se(stop_lldp(lldp) == 0);
+}
+
int main(int argc, char *argv[]) {
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
@@ -239,6 +368,7 @@ int main(int argc, char *argv[]) {
test_receive_basic_packet(e);
test_receive_incomplete_packet(e);
test_receive_oui_packet(e);
+ test_multiple_neighbors_sorted(e);
return 0;
}
diff --git a/src/libsystemd-network/test-ndisc-ra.c b/src/libsystemd-network/test-ndisc-ra.c
index d5a0237663..c4c1c81140 100644
--- a/src/libsystemd-network/test-ndisc-ra.c
+++ b/src/libsystemd-network/test-ndisc-ra.c
@@ -13,6 +13,7 @@
#include "icmp6-util.h"
#include "socket-util.h"
#include "strv.h"
+#include "tests.h"
static struct ether_addr mac_addr = {
.ether_addr_octet = { 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53 }
@@ -292,11 +293,11 @@ static void test_ra(void) {
sd_event *e;
sd_radv *ra;
usec_t time_now = now(clock_boottime_or_monotonic());
- unsigned int i;
+ unsigned i;
printf("* %s\n", __FUNCTION__);
- assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, test_fd) >= 0);
+ assert_se(socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
assert_se(sd_event_new(&e) >= 0);
@@ -357,9 +358,7 @@ static void test_ra(void) {
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_radv_prefix();
test_radv();
diff --git a/src/libsystemd-network/test-ndisc-rs.c b/src/libsystemd-network/test-ndisc-rs.c
index b9d0e7dc90..caf94d10f8 100644
--- a/src/libsystemd-network/test-ndisc-rs.c
+++ b/src/libsystemd-network/test-ndisc-rs.c
@@ -14,6 +14,7 @@
#include "socket-util.h"
#include "strv.h"
#include "ndisc-internal.h"
+#include "tests.h"
static struct ether_addr mac_addr = {
.ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
@@ -175,7 +176,7 @@ static int test_rs_hangcheck(sd_event_source *s, uint64_t usec,
int icmp6_bind_router_solicitation(int index) {
assert_se(index == 42);
- if (socketpair(AF_UNIX, SOCK_DGRAM, 0, test_fd) < 0)
+ if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
return -errno;
return test_fd[0];
@@ -407,9 +408,7 @@ static void test_timeout(void) {
int main(int argc, char *argv[]) {
- log_set_max_level(LOG_DEBUG);
- log_parse_environment();
- log_open();
+ test_setup_logging(LOG_DEBUG);
test_rs();
test_timeout();