diff options
Diffstat (limited to 'src/libnm-systemd-core')
39 files changed, 1237 insertions, 1672 deletions
diff --git a/src/libnm-systemd-core/meson.build b/src/libnm-systemd-core/meson.build index fb472a76..1fa94486 100644 --- a/src/libnm-systemd-core/meson.build +++ b/src/libnm-systemd-core/meson.build @@ -18,8 +18,6 @@ libnm_systemd_core = static_library( 'src/libsystemd-network/sd-dhcp-lease.c', 'src/libsystemd-network/sd-dhcp6-client.c', 'src/libsystemd-network/sd-dhcp6-lease.c', - 'src/libsystemd-network/sd-ipv4acd.c', - 'src/libsystemd-network/sd-ipv4ll.c', 'src/libsystemd-network/sd-lldp-rx.c', 'src/libsystemd/sd-event/event-util.c', 'src/libsystemd/sd-event/sd-event.c', diff --git a/src/libnm-systemd-core/nm-sd-utils-dhcp.h b/src/libnm-systemd-core/nm-sd-utils-dhcp.h index 5d126d5b..6487a90d 100644 --- a/src/libnm-systemd-core/nm-sd-utils-dhcp.h +++ b/src/libnm-systemd-core/nm-sd-utils-dhcp.h @@ -11,7 +11,7 @@ typedef struct { uint8_t code; uint8_t data_len; - void * data; + void *data; } nm_sd_dhcp_option; int nm_sd_dhcp_lease_get_private_options(sd_dhcp_lease *lease, nm_sd_dhcp_option **out_options); diff --git a/src/libnm-systemd-core/nm-sd.h b/src/libnm-systemd-core/nm-sd.h index 0ec2f16e..421f5372 100644 --- a/src/libnm-systemd-core/nm-sd.h +++ b/src/libnm-systemd-core/nm-sd.h @@ -8,9 +8,7 @@ #include "src/systemd/sd-dhcp-client.h" #include "src/systemd/sd-dhcp6-client.h" -#include "src/systemd/sd-ipv4ll.h" #include "src/systemd/sd-lldp-rx.h" -#include "src/systemd/sd-lldp.h" /*****************************************************************************/ diff --git a/src/libnm-systemd-core/src/libsystemd-network/arp-util.c b/src/libnm-systemd-core/src/libsystemd-network/arp-util.c index 46c4a8cb..c8a73111 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/arp-util.c +++ b/src/libnm-systemd-core/src/libsystemd-network/arp-util.c @@ -16,7 +16,7 @@ #include "unaligned.h" #include "util.h" -int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *eth_mac) { +int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *mac) { struct sock_filter filter[] = { BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0), /* packet >= arp packet ? */ @@ -38,30 +38,21 @@ int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr * BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0), /* protocol == reply ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ /* Sender Hardware Address must be different from our own */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])),/* A <- 4 bytes of client's MAC */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(&mac->ether_addr_octet[0])), /* X <- 4 bytes of client's MAC */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_sha)), /* A <- 4 bytes of SHA */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 6), /* A == 0 ? */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])),/* A <- remainder of client's MAC */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 4), /* A == X ? */ + BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(&mac->ether_addr_octet[4])), /* X <- remainder of client's MAC */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, arp_sha) + 4), /* A <- remainder of SHA */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1), /* A == X ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ /* Sender Protocol Address or Target Protocol Address must be equal to the one we care about */ - BPF_STMT(BPF_LD + BPF_IMM, htobe32(a->s_addr)), /* A <- clients IP */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LDX + BPF_IMM, htobe32(a->s_addr)), /* X <- clients IP */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_spa)), /* A <- SPA */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ - BPF_STMT(BPF_LD + BPF_IMM, htobe32(a->s_addr)), /* A <- clients IP */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1), /* A == X ? */ + BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_tpa)), /* A <- TPA */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ - BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1), /* A == 0 ? */ + BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ }; struct sock_fprog fprog = { @@ -77,7 +68,7 @@ int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr * return 0; } -int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *eth_mac) { +int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *mac) { union sockaddr_union link = { .ll.sll_family = AF_PACKET, .ll.sll_protocol = htobe16(ETH_P_ARP), @@ -89,12 +80,13 @@ int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const stru int r; assert(ifindex > 0); + assert(mac); s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (s < 0) return -errno; - r = arp_update_filter(s, a, eth_mac); + r = arp_update_filter(s, a, mac); if (r < 0) return r; diff --git a/src/libnm-systemd-core/src/libsystemd-network/arp-util.h b/src/libnm-systemd-core/src/libsystemd-network/arp-util.h index e8615a15..b66a81bf 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/arp-util.h +++ b/src/libnm-systemd-core/src/libsystemd-network/arp-util.h @@ -11,8 +11,8 @@ #include "socket-util.h" #include "sparse-endian.h" -int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *eth_mac); -int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *eth_mac); +int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *mac); +int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *mac); int arp_send_packet( int fd, diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c index bd47ff41..74aa19de 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-identifier.c @@ -11,7 +11,7 @@ #include "dhcp-identifier.h" #include "dhcp6-protocol.h" -#include "network-util.h" +#include "netif-util.h" #include "siphash24.h" #include "sparse-endian.h" #include "stat-util.h" @@ -200,7 +200,7 @@ int dhcp_identifier_set_iaid( /* device is under renaming */ return -EBUSY; - name = net_get_name_persistent(device); + name = net_get_persistent_name(device); } if (name) @@ -214,7 +214,7 @@ int dhcp_identifier_set_iaid( if (legacy_unstable_byteorder) /* for historical reasons (a bug), the bits were swapped and thus * the result was endianness dependent. Preserve that behavior. */ - id32 = __bswap_32(id32); + 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 diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h index 6538f05b..466d8e4b 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-internal.h @@ -53,8 +53,8 @@ typedef int (*dhcp_option_callback_t)(uint8_t code, uint8_t len, int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t cb, void *userdata, char **error_message); int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, - uint8_t type, uint16_t arp_type, size_t optlen, - size_t *optoffset); + uint8_t type, uint16_t arp_type, uint8_t hlen, const uint8_t *chaddr, + size_t optlen, size_t *optoffset); uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len); diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h index 35a74dd7..992ac9f3 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-lease-internal.h @@ -70,6 +70,12 @@ struct sd_dhcp_lease { char *timezone; + uint8_t sixrd_ipv4masklen; + uint8_t sixrd_prefixlen; + struct in6_addr sixrd_prefix; + struct in_addr *sixrd_br_addresses; + size_t sixrd_n_br_addresses; + LIST_HEAD(struct sd_dhcp_raw_option, private_options); }; diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c index bbfdeb0f..1c5f3427 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-network.c @@ -60,24 +60,20 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link, /* We only support MAC address length to be either 0 or 6 (ETH_ALEN). Optionally * compare chaddr for ETH_ALEN bytes. */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 12), /* A (the MAC address length) == ETH_ALEN ? */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])), /* A <- 4 bytes of client's MAC */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 8), /* A (the MAC address length) == ETH_ALEN ? */ + BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])), /* X <- 4 bytes of client's MAC */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])), /* A <- remainder of client's MAC */ - BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ + BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])), /* X <- remainder of client's MAC */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */ - BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */ + BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)), /* A <- DHCP magic cookie */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0), /* cookie == DHCP magic cookie ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ - BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ + BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */ }; struct sock_fprog fprog = { .len = ELEMENTSOF(filter), @@ -117,10 +113,17 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link, return TAKE_FD(s); } -int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, - const uint8_t *mac_addr, size_t mac_addr_len, - const uint8_t *bcast_addr, size_t bcast_addr_len, - uint16_t arp_type, uint16_t port) { +int dhcp_network_bind_raw_socket( + int ifindex, + union sockaddr_union *link, + uint32_t xid, + const uint8_t *mac_addr, + size_t mac_addr_len, + const uint8_t *bcast_addr, + size_t bcast_addr_len, + uint16_t arp_type, + uint16_t port) { + static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* Default broadcast address for IPoIB */ static const uint8_t ib_bcast[] = { @@ -174,7 +177,6 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int r = setsockopt_int(s, IPPROTO_IP, IP_TOS, ip_service_type); else r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6); - if (r < 0) return r; @@ -206,43 +208,49 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int return r; } - r = bind(s, &src.sa, sizeof(src.in)); - if (r < 0) + if (bind(s, &src.sa, sizeof(src.in)) < 0) return -errno; return TAKE_FD(s); } -int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, - const void *packet, size_t len) { - int r; +int dhcp_network_send_raw_socket( + int s, + const union sockaddr_union *link, + const void *packet, + size_t len) { + + /* Do not add assert(s >= 0) here, as this is called in fuzz-dhcp-server, and in that case this + * function should fail with negative errno. */ assert(link); assert(packet); - assert(len); + assert(len > 0); - r = sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll)); - if (r < 0) + if (sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll)) < 0) return -errno; return 0; } -int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, - const void *packet, size_t len) { +int dhcp_network_send_udp_socket( + int s, + be32_t address, + uint16_t port, + const void *packet, + size_t len) { + union sockaddr_union dest = { .in.sin_family = AF_INET, .in.sin_port = htobe16(port), .in.sin_addr.s_addr = address, }; - int r; assert(s >= 0); assert(packet); - assert(len); + assert(len > 0); - r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)); - if (r < 0) + if (sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)) < 0) return -errno; return 0; diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c index eeadd562..25a69a61 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp-packet.c @@ -12,21 +12,44 @@ #include "dhcp-internal.h" #include "dhcp-protocol.h" +#include "memory-util.h" #define DHCP_CLIENT_MIN_OPTIONS_SIZE 312 -int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, - uint8_t type, uint16_t arp_type, size_t optlen, - size_t *optoffset) { +int dhcp_message_init( + DHCPMessage *message, + uint8_t op, + uint32_t xid, + uint8_t type, + uint16_t arp_type, + uint8_t hlen, + const uint8_t *chaddr, + size_t optlen, + size_t *optoffset) { + size_t offset = 0; int r; assert(IN_SET(op, BOOTREQUEST, BOOTREPLY)); - assert(IN_SET(arp_type, ARPHRD_ETHER, ARPHRD_INFINIBAND)); + assert(chaddr || hlen == 0); message->op = op; message->htype = arp_type; - message->hlen = (arp_type == ARPHRD_ETHER) ? ETHER_ADDR_LEN : 0; + + /* RFC2131 section 4.1.1: + The client MUST include its hardware address in the ’chaddr’ field, if + necessary for delivery of DHCP reply messages. + + RFC 4390 section 2.1: + A DHCP client, when working over an IPoIB interface, MUST follow the + following rules: + "htype" (hardware address type) MUST be 32 [ARPPARAM]. + "hlen" (hardware address length) MUST be 0. + "chaddr" (client hardware address) field MUST be zeroed. + */ + message->hlen = (arp_type == ARPHRD_INFINIBAND) ? 0 : hlen; + memcpy_safe(message->chaddr, chaddr, message->hlen); + message->xid = htobe32(xid); message->magic = htobe32(DHCP_MAGIC_COOKIE); diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h index 4eb56aa8..f9434098 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-internal.h @@ -11,6 +11,7 @@ #include "sd-event.h" #include "sd-dhcp6-client.h" +#include "dhcp6-protocol.h" #include "hashmap.h" #include "list.h" #include "macro.h" @@ -93,6 +94,7 @@ typedef struct DHCP6IA { typedef struct sd_dhcp6_client sd_dhcp6_client; +bool dhcp6_option_can_request(uint16_t option); 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, const DHCP6IA *ia); @@ -129,6 +131,12 @@ int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *address); int dhcp6_network_send_udp_socket(int s, struct in6_addr *address, const void *packet, size_t len); +int client_parse_message( + sd_dhcp6_client *client, + DHCP6Message *message, + size_t len, + sd_dhcp6_lease *lease); + const char *dhcp6_message_type_to_string(int s) _const_; int dhcp6_message_type_from_string(const char *s) _pure_; const char *dhcp6_message_status_to_string(int s) _const_; diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h index 8801497b..8ae2ecd6 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-lease-internal.h @@ -14,10 +14,14 @@ struct sd_dhcp6_lease { unsigned n_ref; + uint8_t *clientid; + size_t clientid_len; uint8_t *serverid; size_t serverid_len; uint8_t preference; bool rapid_commit; + triple_timestamp timestamp; + struct in6_addr server_address; DHCP6IA ia; DHCP6IA pd; @@ -39,21 +43,19 @@ struct sd_dhcp6_lease { int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire); DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia); -int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, - size_t len); -int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len); +int dhcp6_lease_set_clientid(sd_dhcp6_lease *lease, const uint8_t *id, size_t len); +int dhcp6_lease_get_clientid(sd_dhcp6_lease *lease, uint8_t **ret_id, size_t *ret_len); +int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, size_t len); +int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **ret_id, size_t *ret_len); int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference); int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference); 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_add_dns(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); int dhcp6_lease_add_domains(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); int dhcp6_lease_add_ntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); -int dhcp6_lease_add_sntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen) ; +int dhcp6_lease_add_sntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); int dhcp6_lease_set_fqdn(sd_dhcp6_lease *lease, const uint8_t *optval, size_t optlen); int dhcp6_lease_new(sd_dhcp6_lease **ret); diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c index b6816de4..beace4c7 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-network.c @@ -49,6 +49,10 @@ int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *local_address) { if (r < 0) return r; + r = setsockopt_int(s, SOL_SOCKET, SO_TIMESTAMP, true); + if (r < 0) + return r; + r = bind(s, &src.sa, sizeof(src.in6)); if (r < 0) return -errno; diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c index 4249f90d..237771e6 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-option.c @@ -26,6 +26,193 @@ #define DHCP6_OPTION_IA_PD_LEN (sizeof(struct ia_pd)) #define DHCP6_OPTION_IA_TA_LEN (sizeof(struct ia_ta)) +bool dhcp6_option_can_request(uint16_t option) { + /* See Client ORO field in + * https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#dhcpv6-parameters-2 */ + + switch (option) { + case SD_DHCP6_OPTION_CLIENTID: + case SD_DHCP6_OPTION_SERVERID: + case SD_DHCP6_OPTION_IA_NA: + case SD_DHCP6_OPTION_IA_TA: + case SD_DHCP6_OPTION_IAADDR: + case SD_DHCP6_OPTION_ORO: + case SD_DHCP6_OPTION_PREFERENCE: + case SD_DHCP6_OPTION_ELAPSED_TIME: + case SD_DHCP6_OPTION_RELAY_MSG: + case SD_DHCP6_OPTION_AUTH: + case SD_DHCP6_OPTION_UNICAST: + case SD_DHCP6_OPTION_STATUS_CODE: + case SD_DHCP6_OPTION_RAPID_COMMIT: + case SD_DHCP6_OPTION_USER_CLASS: + case SD_DHCP6_OPTION_VENDOR_CLASS: + return false; + case SD_DHCP6_OPTION_VENDOR_OPTS: + return true; + case SD_DHCP6_OPTION_INTERFACE_ID: + case SD_DHCP6_OPTION_RECONF_MSG: + case SD_DHCP6_OPTION_RECONF_ACCEPT: + return false; + case SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME: + case SD_DHCP6_OPTION_SIP_SERVER_ADDRESS: + case SD_DHCP6_OPTION_DNS_SERVERS: + case SD_DHCP6_OPTION_DOMAIN_LIST: + return true; + case SD_DHCP6_OPTION_IA_PD: + case SD_DHCP6_OPTION_IA_PD_PREFIX: + return false; + case SD_DHCP6_OPTION_NIS_SERVERS: + case SD_DHCP6_OPTION_NISP_SERVERS: + case SD_DHCP6_OPTION_NIS_DOMAIN_NAME: + case SD_DHCP6_OPTION_NISP_DOMAIN_NAME: + case SD_DHCP6_OPTION_SNTP_SERVERS: + case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME: + case SD_DHCP6_OPTION_BCMCS_SERVER_D: + case SD_DHCP6_OPTION_BCMCS_SERVER_A: + case SD_DHCP6_OPTION_GEOCONF_CIVIC: + return true; + case SD_DHCP6_OPTION_REMOTE_ID: + case SD_DHCP6_OPTION_SUBSCRIBER_ID: + return false; + case SD_DHCP6_OPTION_CLIENT_FQDN: + case SD_DHCP6_OPTION_PANA_AGENT: + case SD_DHCP6_OPTION_NEW_POSIX_TIMEZONE: + case SD_DHCP6_OPTION_NEW_TZDB_TIMEZONE: + return true; + case SD_DHCP6_OPTION_ERO: + case SD_DHCP6_OPTION_LQ_QUERY: + case SD_DHCP6_OPTION_CLIENT_DATA: + case SD_DHCP6_OPTION_CLT_TIME: + case SD_DHCP6_OPTION_LQ_RELAY_DATA: + case SD_DHCP6_OPTION_LQ_CLIENT_LINK: + return false; + case SD_DHCP6_OPTION_MIP6_HNIDF: + case SD_DHCP6_OPTION_MIP6_VDINF: + case SD_DHCP6_OPTION_V6_LOST: + case SD_DHCP6_OPTION_CAPWAP_AC_V6: + return true; + case SD_DHCP6_OPTION_RELAY_ID: + return false; + case SD_DHCP6_OPTION_IPV6_ADDRESS_MOS: + case SD_DHCP6_OPTION_IPV6_FQDN_MOS: + case SD_DHCP6_OPTION_NTP_SERVER: + case SD_DHCP6_OPTION_V6_ACCESS_DOMAIN: + case SD_DHCP6_OPTION_SIP_UA_CS_LIST: + case SD_DHCP6_OPTION_BOOTFILE_URL: + case SD_DHCP6_OPTION_BOOTFILE_PARAM: + return true; + case SD_DHCP6_OPTION_CLIENT_ARCH_TYPE: + return false; + case SD_DHCP6_OPTION_NII: + case SD_DHCP6_OPTION_GEOLOCATION: + case SD_DHCP6_OPTION_AFTR_NAME: + case SD_DHCP6_OPTION_ERP_LOCAL_DOMAIN_NAME: + return true; + case SD_DHCP6_OPTION_RSOO: + return false; + case SD_DHCP6_OPTION_PD_EXCLUDE: + return true; + case SD_DHCP6_OPTION_VSS: + return false; + case SD_DHCP6_OPTION_MIP6_IDINF: + case SD_DHCP6_OPTION_MIP6_UDINF: + case SD_DHCP6_OPTION_MIP6_HNP: + case SD_DHCP6_OPTION_MIP6_HAA: + case SD_DHCP6_OPTION_MIP6_HAF: + case SD_DHCP6_OPTION_RDNSS_SELECTION: + case SD_DHCP6_OPTION_KRB_PRINCIPAL_NAME: + case SD_DHCP6_OPTION_KRB_REALM_NAME: + case SD_DHCP6_OPTION_KRB_DEFAULT_REALM_NAME: + case SD_DHCP6_OPTION_KRB_KDC: + return true; + case SD_DHCP6_OPTION_CLIENT_LINKLAYER_ADDR: + case SD_DHCP6_OPTION_LINK_ADDRESS: + case SD_DHCP6_OPTION_RADIUS: + return false; + case SD_DHCP6_OPTION_SOL_MAX_RT: + case SD_DHCP6_OPTION_INF_MAX_RT: + case SD_DHCP6_OPTION_ADDRSEL: + case SD_DHCP6_OPTION_ADDRSEL_TABLE: + case SD_DHCP6_OPTION_V6_PCP_SERVER: + return true; + case SD_DHCP6_OPTION_DHCPV4_MSG: + return false; + case SD_DHCP6_OPTION_DHCP4_O_DHCP6_SERVER: + return true; + case SD_DHCP6_OPTION_S46_RULE: + return false; + case SD_DHCP6_OPTION_S46_BR: + return true; + case SD_DHCP6_OPTION_S46_DMR: + case SD_DHCP6_OPTION_S46_V4V6BIND: + case SD_DHCP6_OPTION_S46_PORTPARAMS: + return false; + case SD_DHCP6_OPTION_S46_CONT_MAPE: + case SD_DHCP6_OPTION_S46_CONT_MAPT: + case SD_DHCP6_OPTION_S46_CONT_LW: + case SD_DHCP6_OPTION_4RD: + case SD_DHCP6_OPTION_4RD_MAP_RULE: + case SD_DHCP6_OPTION_4RD_NON_MAP_RULE: + return true; + case SD_DHCP6_OPTION_LQ_BASE_TIME: + case SD_DHCP6_OPTION_LQ_START_TIME: + case SD_DHCP6_OPTION_LQ_END_TIME: + return false; + case SD_DHCP6_OPTION_CAPTIVE_PORTAL: + case SD_DHCP6_OPTION_MPL_PARAMETERS: + return true; + case SD_DHCP6_OPTION_ANI_ATT: + case SD_DHCP6_OPTION_ANI_NETWORK_NAME: + case SD_DHCP6_OPTION_ANI_AP_NAME: + case SD_DHCP6_OPTION_ANI_AP_BSSID: + case SD_DHCP6_OPTION_ANI_OPERATOR_ID: + case SD_DHCP6_OPTION_ANI_OPERATOR_REALM: + return false; + case SD_DHCP6_OPTION_S46_PRIORITY: + return true; + case SD_DHCP6_OPTION_MUD_URL_V6: + return false; + case SD_DHCP6_OPTION_V6_PREFIX64: + return true; + case SD_DHCP6_OPTION_F_BINDING_STATUS: + case SD_DHCP6_OPTION_F_CONNECT_FLAGS: + case SD_DHCP6_OPTION_F_DNS_REMOVAL_INFO: + case SD_DHCP6_OPTION_F_DNS_HOST_NAME: + case SD_DHCP6_OPTION_F_DNS_ZONE_NAME: + case SD_DHCP6_OPTION_F_DNS_FLAGS: + case SD_DHCP6_OPTION_F_EXPIRATION_TIME: + case SD_DHCP6_OPTION_F_MAX_UNACKED_BNDUPD: + case SD_DHCP6_OPTION_F_MCLT: + case SD_DHCP6_OPTION_F_PARTNER_LIFETIME: + case SD_DHCP6_OPTION_F_PARTNER_LIFETIME_SENT: + case SD_DHCP6_OPTION_F_PARTNER_DOWN_TIME: + case SD_DHCP6_OPTION_F_PARTNER_RAW_CLT_TIME: + case SD_DHCP6_OPTION_F_PROTOCOL_VERSION: + case SD_DHCP6_OPTION_F_KEEPALIVE_TIME: + case SD_DHCP6_OPTION_F_RECONFIGURE_DATA: + case SD_DHCP6_OPTION_F_RELATIONSHIP_NAME: + case SD_DHCP6_OPTION_F_SERVER_FLAGS: + case SD_DHCP6_OPTION_F_SERVER_STATE: + case SD_DHCP6_OPTION_F_START_TIME_OF_STATE: + case SD_DHCP6_OPTION_F_STATE_EXPIRATION_TIME: + case SD_DHCP6_OPTION_RELAY_PORT: + return false; + case SD_DHCP6_OPTION_V6_SZTP_REDIRECT: + case SD_DHCP6_OPTION_S46_BIND_IPV6_PREFIX: + return true; + case SD_DHCP6_OPTION_IA_LL: + case SD_DHCP6_OPTION_LLADDR: + case SD_DHCP6_OPTION_SLAP_QUAD: + return false; + case SD_DHCP6_OPTION_V6_DOTS_RI: + case SD_DHCP6_OPTION_V6_DOTS_ADDRESS: + case SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF: + return true; + default: + return false; + } +} + static int option_append_hdr(uint8_t **buf, size_t *buflen, uint16_t optcode, size_t optlen) { DHCP6Option *option; @@ -275,7 +462,7 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { if (dns_name_is_single_label(fqdn)) r--; - r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_FQDN, 1 + r, buffer); + r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_CLIENT_FQDN, 1 + r, buffer); return r; } diff --git a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-protocol.h b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-protocol.h index c7003638..5d2af439 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/dhcp6-protocol.h +++ b/src/libnm-systemd-core/src/libsystemd-network/dhcp6-protocol.h @@ -5,6 +5,7 @@ Copyright © 2014 Intel Corporation. All rights reserved. ***/ +#include <errno.h> #include <netinet/ip6.h> #include <netinet/udp.h> @@ -36,57 +37,83 @@ enum { DHCP6_PORT_CLIENT = 546, }; -#define DHCP6_INF_TIMEOUT 1 * USEC_PER_SEC -#define DHCP6_INF_MAX_RT 120 * USEC_PER_SEC -#define DHCP6_SOL_MAX_DELAY 1 * USEC_PER_SEC -#define DHCP6_SOL_TIMEOUT 1 * USEC_PER_SEC -#define DHCP6_SOL_MAX_RT 120 * USEC_PER_SEC -#define DHCP6_REQ_TIMEOUT 1 * USEC_PER_SEC -#define DHCP6_REQ_MAX_RT 120 * USEC_PER_SEC +#define DHCP6_INF_TIMEOUT (1 * USEC_PER_SEC) +#define DHCP6_INF_MAX_RT (120 * USEC_PER_SEC) +#define DHCP6_SOL_MAX_DELAY (1 * USEC_PER_SEC) +#define DHCP6_SOL_TIMEOUT (1 * USEC_PER_SEC) +#define DHCP6_SOL_MAX_RT (120 * USEC_PER_SEC) +#define DHCP6_REQ_TIMEOUT (1 * USEC_PER_SEC) +#define DHCP6_REQ_MAX_RT (120 * USEC_PER_SEC) #define DHCP6_REQ_MAX_RC 10 -#define DHCP6_REN_TIMEOUT 10 * USEC_PER_SEC -#define DHCP6_REN_MAX_RT 600 * USEC_PER_SEC -#define DHCP6_REB_TIMEOUT 10 * USEC_PER_SEC -#define DHCP6_REB_MAX_RT 600 * USEC_PER_SEC +#define DHCP6_REN_TIMEOUT (10 * USEC_PER_SEC) +#define DHCP6_REN_MAX_RT (600 * USEC_PER_SEC) +#define DHCP6_REB_TIMEOUT (10 * USEC_PER_SEC) +#define DHCP6_REB_MAX_RT (600 * USEC_PER_SEC) -enum DHCP6State { - DHCP6_STATE_STOPPED = 0, - DHCP6_STATE_INFORMATION_REQUEST = 1, - DHCP6_STATE_SOLICITATION = 2, - DHCP6_STATE_REQUEST = 3, - DHCP6_STATE_BOUND = 4, - DHCP6_STATE_RENEW = 5, - DHCP6_STATE_REBIND = 6, -}; +typedef enum DHCP6State { + DHCP6_STATE_STOPPED, + DHCP6_STATE_INFORMATION_REQUEST, + DHCP6_STATE_SOLICITATION, + DHCP6_STATE_REQUEST, + DHCP6_STATE_BOUND, + DHCP6_STATE_RENEW, + DHCP6_STATE_REBIND, + _DHCP6_STATE_MAX, + _DHCP6_STATE_INVALID = -EINVAL, +} DHCP6State; -enum { - DHCP6_SOLICIT = 1, - DHCP6_ADVERTISE = 2, - DHCP6_REQUEST = 3, - DHCP6_CONFIRM = 4, - DHCP6_RENEW = 5, - DHCP6_REBIND = 6, - DHCP6_REPLY = 7, - DHCP6_RELEASE = 8, - DHCP6_DECLINE = 9, - DHCP6_RECONFIGURE = 10, - DHCP6_INFORMATION_REQUEST = 11, - DHCP6_RELAY_FORW = 12, - DHCP6_RELAY_REPL = 13, - _DHCP6_MESSAGE_MAX = 14, -}; +/* https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#dhcpv6-parameters-1 */ +typedef enum DHCP6MessageType { + DHCP6_MESSAGE_SOLICIT = 1, /* RFC 8415 */ + DHCP6_MESSAGE_ADVERTISE = 2, /* RFC 8415 */ + DHCP6_MESSAGE_REQUEST = 3, /* RFC 8415 */ + DHCP6_MESSAGE_CONFIRM = 4, /* RFC 8415 */ + DHCP6_MESSAGE_RENEW = 5, /* RFC 8415 */ + DHCP6_MESSAGE_REBIND = 6, /* RFC 8415 */ + DHCP6_MESSAGE_REPLY = 7, /* RFC 8415 */ + DHCP6_MESSAGE_RELEASE = 8, /* RFC 8415 */ + DHCP6_MESSAGE_DECLINE = 9, /* RFC 8415 */ + DHCP6_MESSAGE_RECONFIGURE = 10, /* RFC 8415 */ + DHCP6_MESSAGE_INFORMATION_REQUEST = 11, /* RFC 8415 */ + DHCP6_MESSAGE_RELAY_FORWARD = 12, /* RFC 8415 */ + DHCP6_MESSAGE_RELAY_REPLY = 13, /* RFC 8415 */ + DHCP6_MESSAGE_LEASE_QUERY = 14, /* RFC 5007 */ + DHCP6_MESSAGE_LEASE_QUERY_REPLY = 15, /* RFC 5007 */ + DHCP6_MESSAGE_LEASE_QUERY_DONE = 16, /* RFC 5460 */ + DHCP6_MESSAGE_LEASE_QUERY_DATA = 17, /* RFC 5460 */ + DHCP6_MESSAGE_RECONFIGURE_REQUEST = 18, /* RFC 6977 */ + DHCP6_MESSAGE_RECONFIGURE_REPLY = 19, /* RFC 6977 */ + DHCP6_MESSAGE_DHCPV4_QUERY = 20, /* RFC 7341 */ + DHCP6_MESSAGE_DHCPV4_RESPONSE = 21, /* RFC 7341 */ + DHCP6_MESSAGE_ACTIVE_LEASE_QUERY = 22, /* RFC 7653 */ + DHCP6_MESSAGE_START_TLS = 23, /* RFC 7653 */ + DHCP6_MESSAGE_BINDING_UPDATE = 24, /* RFC 8156 */ + DHCP6_MESSAGE_BINDING_REPLY = 25, /* RFC 8156 */ + DHCP6_MESSAGE_POOL_REQUEST = 26, /* RFC 8156 */ + DHCP6_MESSAGE_POOL_RESPONSE = 27, /* RFC 8156 */ + DHCP6_MESSAGE_UPDATE_REQUEST = 28, /* RFC 8156 */ + DHCP6_MESSAGE_UPDATE_REQUEST_ALL = 29, /* RFC 8156 */ + DHCP6_MESSAGE_UPDATE_DONE = 30, /* RFC 8156 */ + DHCP6_MESSAGE_CONNECT = 31, /* RFC 8156 */ + DHCP6_MESSAGE_CONNECT_REPLY = 32, /* RFC 8156 */ + DHCP6_MESSAGE_DISCONNECT = 33, /* RFC 8156 */ + DHCP6_MESSAGE_STATE = 34, /* RFC 8156 */ + DHCP6_MESSAGE_CONTACT = 35, /* RFC 8156 */ + _DHCP6_MESSAGE_TYPE_MAX, + _DHCP6_MESSAGE_TYPE_INVALID = -EINVAL, +} DHCP6MessageType; -enum { +typedef enum DHCP6NTPSubOption { DHCP6_NTP_SUBOPTION_SRV_ADDR = 1, DHCP6_NTP_SUBOPTION_MC_ADDR = 2, DHCP6_NTP_SUBOPTION_SRV_FQDN = 3, -}; +} DHCP6NTPSubOption; /* * RFC 8415, RFC 5007 and RFC 7653 status codes: * https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#dhcpv6-parameters-5 */ -enum { +typedef enum DHCP6Status { DHCP6_STATUS_SUCCESS = 0, DHCP6_STATUS_UNSPEC_FAIL = 1, DHCP6_STATUS_NO_ADDRS_AVAIL = 2, @@ -110,11 +137,12 @@ enum { DHCP6_STATUS_SERVER_SHUTTING_DOWN = 20, DHCP6_STATUS_DNS_UPDATE_NOT_SUPPORTED = 21, DHCP6_STATUS_EXCESSIVE_TIME_SKEW = 22, - _DHCP6_STATUS_MAX = 23, -}; + _DHCP6_STATUS_MAX, + _DHCP6_STATUS_INVALID = -EINVAL, +} DHCP6Status; -enum { - DHCP6_FQDN_FLAG_S = (1 << 0), - DHCP6_FQDN_FLAG_O = (1 << 1), - DHCP6_FQDN_FLAG_N = (1 << 2), -}; +typedef enum DHCP6FQDNFlag { + DHCP6_FQDN_FLAG_S = 1 << 0, + DHCP6_FQDN_FLAG_O = 1 << 1, + DHCP6_FQDN_FLAG_N = 1 << 2, +} DHCP6FQDNFlag; diff --git a/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c b/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c index 3d6d7e42..b4d7c327 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c +++ b/src/libnm-systemd-core/src/libsystemd-network/lldp-neighbor.c @@ -47,7 +47,7 @@ int lldp_neighbor_prioq_compare_func(const void *a, const void *b) { return CMP(x->until, y->until); } -_public_ sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { +sd_lldp_neighbor *sd_lldp_neighbor_ref(sd_lldp_neighbor *n) { if (!n) return NULL; @@ -72,7 +72,7 @@ static sd_lldp_neighbor *lldp_neighbor_free(sd_lldp_neighbor *n) { return mfree(n); } -_public_ sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) { +sd_lldp_neighbor *sd_lldp_neighbor_unref(sd_lldp_neighbor *n) { /* Drops one reference from the neighbor. Note that the object is not freed unless it is already unlinked from * the sd_lldp object. */ @@ -360,7 +360,7 @@ bool lldp_neighbor_equal(const sd_lldp_neighbor *a, const sd_lldp_neighbor *b) { return memcmp(LLDP_NEIGHBOR_RAW(a), LLDP_NEIGHBOR_RAW(b), a->raw_size) == 0; } -_public_ int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address) { +int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct ether_addr* address) { assert_return(n, -EINVAL); assert_return(address, -EINVAL); @@ -368,7 +368,7 @@ _public_ int sd_lldp_neighbor_get_source_address(sd_lldp_neighbor *n, struct eth return 0; } -_public_ int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address) { +int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struct ether_addr* address) { assert_return(n, -EINVAL); assert_return(address, -EINVAL); @@ -376,7 +376,7 @@ _public_ int sd_lldp_neighbor_get_destination_address(sd_lldp_neighbor *n, struc return 0; } -_public_ int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { +int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { assert_return(n, -EINVAL); assert_return(ret, -EINVAL); assert_return(size, -EINVAL); @@ -387,7 +387,7 @@ _public_ int sd_lldp_neighbor_get_raw(sd_lldp_neighbor *n, const void **ret, siz return 0; } -_public_ int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { +int sd_lldp_neighbor_get_chassis_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { assert_return(n, -EINVAL); assert_return(type, -EINVAL); assert_return(ret, -EINVAL); @@ -440,7 +440,7 @@ static int format_network_address(const void *data, size_t sz, char **ret) { return 1; } -_public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) { +int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, const char **ret) { char *k; int r; @@ -496,7 +496,7 @@ done: return 0; } -_public_ int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { +int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, const void **ret, size_t *size) { assert_return(n, -EINVAL); assert_return(type, -EINVAL); assert_return(ret, -EINVAL); @@ -511,7 +511,7 @@ _public_ int sd_lldp_neighbor_get_port_id(sd_lldp_neighbor *n, uint8_t *type, co return 0; } -_public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret) { +int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const char **ret) { char *k; int r; @@ -566,7 +566,7 @@ done: return 0; } -_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) { +int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) { assert_return(n, -EINVAL); assert_return(ret_sec, -EINVAL); @@ -574,7 +574,7 @@ _public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) { return 0; } -_public_ int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret) { +int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret) { assert_return(n, -EINVAL); assert_return(ret, -EINVAL); @@ -585,7 +585,7 @@ _public_ int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char ** return 0; } -_public_ int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret) { +int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret) { assert_return(n, -EINVAL); assert_return(ret, -EINVAL); @@ -596,7 +596,7 @@ _public_ int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const return 0; } -_public_ int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret) { +int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret) { assert_return(n, -EINVAL); assert_return(ret, -EINVAL); @@ -607,7 +607,7 @@ _public_ int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const ch return 0; } -_public_ int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret) { +int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret) { assert_return(n, -EINVAL); assert_return(ret, -EINVAL); @@ -618,7 +618,7 @@ _public_ int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret) return 0; } -_public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { +int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { assert_return(n, -EINVAL); assert_return(ret, -EINVAL); @@ -629,7 +629,7 @@ _public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint1 return 0; } -_public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { +int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret) { assert_return(n, -EINVAL); assert_return(ret, -EINVAL); @@ -640,7 +640,7 @@ _public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint return 0; } -_public_ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) { +int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) { _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; int r; @@ -661,7 +661,7 @@ _public_ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, return r; } -_public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) { +int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) { assert_return(n, -EINVAL); assert(n->raw_size >= sizeof(struct ether_header)); @@ -670,7 +670,7 @@ _public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) { return n->rindex < n->raw_size; } -_public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) { +int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) { size_t length; assert_return(n, -EINVAL); @@ -689,7 +689,7 @@ _public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) { return n->rindex < n->raw_size; } -_public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) { +int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) { assert_return(n, -EINVAL); assert_return(type, -EINVAL); @@ -703,7 +703,7 @@ _public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) { return 0; } -_public_ int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) { +int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) { uint8_t k; int r; @@ -716,7 +716,7 @@ _public_ int sd_lldp_neighbor_tlv_is_type(sd_lldp_neighbor *n, uint8_t type) { return type == k; } -_public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype) { +int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t *subtype) { const uint8_t *d; size_t length; int r; @@ -745,7 +745,7 @@ _public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[_SD_A return 0; } -_public_ int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype) { +int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[_SD_ARRAY_STATIC 3], uint8_t subtype) { uint8_t k[3], st; int r; @@ -758,7 +758,7 @@ _public_ int sd_lldp_neighbor_tlv_is_oui(sd_lldp_neighbor *n, const uint8_t oui[ return memcmp(k, oui, 3) == 0 && st == subtype; } -_public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { +int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, size_t *size) { size_t length; assert_return(n, -EINVAL); @@ -780,7 +780,7 @@ _public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret, return 0; } -_public_ int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) { +int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) { assert_return(n, -EINVAL); assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP); assert_return(clock_supported(clock), -EOPNOTSUPP); diff --git a/src/libnm-systemd-core/src/libsystemd-network/lldp-network.c b/src/libnm-systemd-core/src/libsystemd-network/lldp-network.c index 34a4f3f0..00eb9703 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/lldp-network.c +++ b/src/libnm-systemd-core/src/libsystemd-network/lldp-network.c @@ -11,7 +11,6 @@ #include "socket-util.h" int lldp_network_bind_raw_socket(int ifindex) { - static const struct sock_filter filter[] = { BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ethhdr, h_dest)), /* A <- 4 bytes of destination MAC */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0180c200, 1, 0), /* A != 01:80:c2:00 */ @@ -26,26 +25,21 @@ int lldp_network_bind_raw_socket(int ifindex) { BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept packet */ }; - static const struct sock_fprog fprog = { .len = ELEMENTSOF(filter), .filter = (struct sock_filter*) filter, }; - struct packet_mreq mreq = { .mr_ifindex = ifindex, .mr_type = PACKET_MR_MULTICAST, .mr_alen = ETH_ALEN, .mr_address = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 } }; - union sockaddr_union saddrll = { .ll.sll_family = AF_PACKET, .ll.sll_ifindex = ifindex, }; - _cleanup_close_ int fd = -1; - int r; assert(ifindex > 0); @@ -54,29 +48,24 @@ int lldp_network_bind_raw_socket(int ifindex) { if (fd < 0) return -errno; - r = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); - if (r < 0) + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0) return -errno; /* customer bridge */ - r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - if (r < 0) + if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) return -errno; /* non TPMR bridge */ mreq.mr_address[ETH_ALEN - 1] = 0x03; - r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - if (r < 0) + if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) return -errno; /* nearest bridge */ mreq.mr_address[ETH_ALEN - 1] = 0x0E; - r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); - if (r < 0) + if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) return -errno; - r = bind(fd, &saddrll.sa, sizeof(saddrll.ll)); - if (r < 0) + if (bind(fd, &saddrll.sa, sizeof(saddrll.ll)) < 0) return -errno; return TAKE_FD(fd); diff --git a/src/libnm-systemd-core/src/libsystemd-network/network-common.h b/src/libnm-systemd-core/src/libsystemd-network/network-common.h index d43b76d4..2b0e3b56 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/network-common.h +++ b/src/libnm-systemd-core/src/libsystemd-network/network-common.h @@ -8,8 +8,10 @@ int _e = (error); \ if (DEBUG_LOGGING) { \ const char *_n = NULL; \ + type *_v = (val); \ \ - (void) type##_get_ifname(val, &_n); \ + if (_v) \ + (void) type##_get_ifname(_v, &_n); \ log_interface_full_errno_zerook( \ _n, LOG_DEBUG, _e, prefix fmt, \ ##__VA_ARGS__); \ diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c index cb984b6e..1600f806 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-client.c @@ -837,7 +837,8 @@ static int client_message_init( return -ENOMEM; r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type, - client->arp_type, optlen, &optoffset); + client->arp_type, client->mac_addr_len, client->mac_addr, + optlen, &optoffset); if (r < 0) return r; @@ -853,7 +854,7 @@ static int client_message_init( secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1; packet->dhcp.secs = htobe16(secs); - /* RFC2132 section 4.1 + /* RFC2131 section 4.1 A client that cannot receive unicast IP datagrams until its protocol software has been configured with an IP address SHOULD set the BROADCAST bit in the 'flags' field to 1 in any DHCPDISCOVER or @@ -867,15 +868,6 @@ static int client_message_init( if (client->request_broadcast || client->arp_type != ARPHRD_ETHER) packet->dhcp.flags = htobe16(0x8000); - /* RFC2132 section 4.1.1: - The client MUST include its hardware address in the ’chaddr’ field, if - necessary for delivery of DHCP reply messages. Non-Ethernet - interfaces will leave 'chaddr' empty and use the client identifier - instead (eg, RFC 4390 section 2.1). - */ - if (client->arp_type == ARPHRD_ETHER) - memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN); - /* If no client identifier exists, construct an RFC 4361-compliant one */ if (client->client_id_len == 0) { size_t duid_len; @@ -1935,13 +1927,13 @@ static int client_receive_message_udp( assert(client); buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) - /* the link is down. Don't return an error or the I/O event - source will be disconnected and we won't be able to receive - packets again when the link comes back. */ + if (buflen < 0) { + if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen)) + return 0; + + log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m"); return 0; - if (buflen < 0) - return buflen; + } message = malloc0(buflen); if (!message) @@ -1949,12 +1941,11 @@ static int client_receive_message_udp( len = recv(fd, message, buflen, 0); if (len < 0) { - /* see comment above for why we shouldn't error out on ENETDOWN. */ - if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) + if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno)) return 0; - return log_dhcp_client_errno(client, errno, - "Could not receive message from UDP socket: %m"); + log_dhcp_client_errno(client, errno, "Could not receive message from UDP socket, ignoring: %m"); + return 0; } if ((size_t) len < sizeof(DHCPMessage)) { log_dhcp_client(client, "Too small to be a DHCP message: ignoring"); @@ -2000,7 +1991,9 @@ static int client_receive_message_udp( return 0; } - return client_handle_message(client, message, len); + log_dhcp_client(client, "Received message from UDP socket, processing."); + (void) client_handle_message(client, message, len); + return 0; } static int client_receive_message_raw( @@ -2028,10 +2021,13 @@ static int client_receive_message_raw( assert(client); buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) + if (buflen < 0) { + if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen)) + return 0; + + log_dhcp_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m"); return 0; - if (buflen < 0) - return buflen; + } packet = malloc0(buflen); if (!packet) @@ -2040,12 +2036,13 @@ static int client_receive_message_raw( iov = IOVEC_MAKE(packet, buflen); len = recvmsg_safe(fd, &msg, 0); - if (IN_SET(len, -EAGAIN, -EINTR, -ENETDOWN)) - return 0; - if (len < 0) - return log_dhcp_client_errno(client, len, - "Could not receive message from raw socket: %m"); + if (len < 0) { + if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len)) + return 0; + log_dhcp_client_errno(client, len, "Could not receive message from raw socket, ignoring: %m"); + return 0; + } if ((size_t) len < sizeof(DHCPPacket)) return 0; @@ -2061,7 +2058,9 @@ static int client_receive_message_raw( len -= DHCP_IP_UDP_SIZE; - return client_handle_message(client, &packet->dhcp, len); + log_dhcp_client(client, "Received message from RAW socket, processing."); + (void) client_handle_message(client, &packet->dhcp, len); + return 0; } int sd_dhcp_client_send_renew(sd_dhcp_client *client) { diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c index 4cd9295c..7a250534 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c @@ -107,12 +107,13 @@ int sd_dhcp_lease_get_servers( assert_return(lease, -EINVAL); assert_return(what >= 0, -EINVAL); assert_return(what < _SD_DHCP_LEASE_SERVER_TYPE_MAX, -EINVAL); - assert_return(addr, -EINVAL); if (lease->servers[what].size <= 0) return -ENODATA; - *addr = lease->servers[what].addr; + if (addr) + *addr = lease->servers[what].addr; + return (int) lease->servers[what].size; } @@ -252,6 +253,33 @@ int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) { return -ENODATA; } +int sd_dhcp_lease_get_6rd( + sd_dhcp_lease *lease, + uint8_t *ret_ipv4masklen, + uint8_t *ret_prefixlen, + struct in6_addr *ret_prefix, + const struct in_addr **ret_br_addresses, + size_t *ret_n_br_addresses) { + + assert_return(lease, -EINVAL); + + if (lease->sixrd_n_br_addresses <= 0) + return -ENODATA; + + if (ret_ipv4masklen) + *ret_ipv4masklen = lease->sixrd_ipv4masklen; + if (ret_prefixlen) + *ret_prefixlen = lease->sixrd_prefixlen; + if (ret_prefix) + *ret_prefix = lease->sixrd_prefix; + if (ret_br_addresses) + *ret_br_addresses = lease->sixrd_br_addresses; + if (ret_n_br_addresses) + *ret_n_br_addresses = lease->sixrd_n_br_addresses; + + return 0; +} + int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) { assert_return(lease, -EINVAL); assert_return(data, -EINVAL); @@ -290,6 +318,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) { free(lease->client_id); free(lease->vendor_specific); strv_free(lease->search_domains); + free(lease->sixrd_br_addresses); return mfree(lease); } @@ -535,6 +564,61 @@ static int lease_parse_classless_routes( return 0; } +static int lease_parse_6rd(sd_dhcp_lease *lease, const uint8_t *option, size_t len) { + uint8_t ipv4masklen, prefixlen; + struct in6_addr prefix; + _cleanup_free_ struct in_addr *br_addresses = NULL; + size_t n_br_addresses; + + assert(lease); + assert(option); + + /* See RFC 5969 Section 7.1.1 */ + + if (lease->sixrd_n_br_addresses > 0) + /* Multiple 6rd option?? */ + return -EINVAL; + + /* option-length: The length of the DHCP option in octets (22 octets with one BR IPv4 address). */ + if (len < 2 + sizeof(struct in6_addr) + sizeof(struct in_addr) || + (len - 2 - sizeof(struct in6_addr)) % sizeof(struct in_addr) != 0) + return -EINVAL; + + /* IPv4MaskLen: The number of high-order bits that are identical across all CE IPv4 addresses + * within a given 6rd domain. This may be any value between 0 and 32. Any value + * greater than 32 is invalid. */ + ipv4masklen = option[0]; + if (ipv4masklen > 32) + return -EINVAL; + + /* 6rdPrefixLen: The IPv6 prefix length of the SP's 6rd IPv6 prefix in number of bits. For the + * purpose of bounds checking by DHCP option processing, the sum of + * (32 - IPv4MaskLen) + 6rdPrefixLen MUST be less than or equal to 128. */ + prefixlen = option[1]; + if (32 - ipv4masklen + prefixlen > 128) + return -EINVAL; + + /* 6rdPrefix: The service provider's 6rd IPv6 prefix represented as a 16-octet IPv6 address. + * The bits in the prefix after the 6rdPrefixlen number of bits are reserved and + * MUST be initialized to zero by the sender and ignored by the receiver. */ + memcpy(&prefix, option + 2, sizeof(struct in6_addr)); + (void) in6_addr_mask(&prefix, prefixlen); + + /* 6rdBRIPv4Address: One or more IPv4 addresses of the 6rd Border Relay(s) for a given 6rd domain. */ + n_br_addresses = (len - 2 - sizeof(struct in6_addr)) / sizeof(struct in_addr); + br_addresses = newdup(struct in_addr, option + 2 + sizeof(struct in6_addr), n_br_addresses); + if (!br_addresses) + return -ENOMEM; + + lease->sixrd_ipv4masklen = ipv4masklen; + lease->sixrd_prefixlen = prefixlen; + lease->sixrd_prefix = prefix; + lease->sixrd_br_addresses = TAKE_PTR(br_addresses); + lease->sixrd_n_br_addresses = n_br_addresses; + + return 0; +} + int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) { sd_dhcp_lease *lease = userdata; int r; @@ -693,7 +777,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void } if (!timezone_is_valid(tz, LOG_DEBUG)) { - log_debug_errno(r, "Timezone is not valid, ignoring: %m"); + log_debug("Timezone is not valid, ignoring."); return 0; } @@ -720,6 +804,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void lease->vendor_specific_len = len; break; + case SD_DHCP_OPTION_6RD: + r = lease_parse_6rd(lease, option, len); + if (r < 0) + log_debug_errno(r, "Failed to parse 6rd option, ignoring: %m"); + break; + case SD_DHCP_OPTION_PRIVATE_BASE ... SD_DHCP_OPTION_PRIVATE_LAST: r = dhcp_lease_insert_private_option(lease, code, option, len); if (r < 0) diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c index 5398bdff..0c2206ff 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c @@ -27,6 +27,7 @@ #include "hexdecoct.h" #include "hostname-util.h" #include "in-addr-util.h" +#include "io-util.h" #include "network-common.h" #include "random-util.h" #include "socket-util.h" @@ -41,16 +42,16 @@ #define IRT_MINIMUM (600 * USEC_PER_SEC) /* 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, -}; +typedef enum DHCP6RequestIA { + DHCP6_REQUEST_IA_NA = 1 << 0, + DHCP6_REQUEST_IA_TA = 1 << 1, /* currently not used */ + DHCP6_REQUEST_IA_PD = 1 << 2, +} DHCP6RequestIA; struct sd_dhcp6_client { unsigned n_ref; - enum DHCP6State state; + DHCP6State state; sd_event *event; int event_priority; int ifindex; @@ -64,7 +65,7 @@ struct sd_dhcp6_client { DHCP6IA ia_pd; sd_event_source *timeout_t1; sd_event_source *timeout_t2; - unsigned request; + DHCP6RequestIA request_ia; be32_t transaction_id; usec_t transaction_start; struct sd_dhcp6_lease *lease; @@ -102,20 +103,42 @@ static const uint16_t default_req_opts[] = { SD_DHCP6_OPTION_SNTP_SERVERS, }; -const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = { - [DHCP6_SOLICIT] = "SOLICIT", - [DHCP6_ADVERTISE] = "ADVERTISE", - [DHCP6_REQUEST] = "REQUEST", - [DHCP6_CONFIRM] = "CONFIRM", - [DHCP6_RENEW] = "RENEW", - [DHCP6_REBIND] = "REBIND", - [DHCP6_REPLY] = "REPLY", - [DHCP6_RELEASE] = "RELEASE", - [DHCP6_DECLINE] = "DECLINE", - [DHCP6_RECONFIGURE] = "RECONFIGURE", - [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST", - [DHCP6_RELAY_FORW] = "RELAY-FORW", - [DHCP6_RELAY_REPL] = "RELAY-REPL", +const char * dhcp6_message_type_table[_DHCP6_MESSAGE_TYPE_MAX] = { + [DHCP6_MESSAGE_SOLICIT] = "Solicit", + [DHCP6_MESSAGE_ADVERTISE] = "Advertise", + [DHCP6_MESSAGE_REQUEST] = "Request", + [DHCP6_MESSAGE_CONFIRM] = "Confirm", + [DHCP6_MESSAGE_RENEW] = "Renew", + [DHCP6_MESSAGE_REBIND] = "Rebind", + [DHCP6_MESSAGE_REPLY] = "Reply", + [DHCP6_MESSAGE_RELEASE] = "Release", + [DHCP6_MESSAGE_DECLINE] = "Decline", + [DHCP6_MESSAGE_RECONFIGURE] = "Reconfigure", + [DHCP6_MESSAGE_INFORMATION_REQUEST] = "Information Request", + [DHCP6_MESSAGE_RELAY_FORWARD] = "Relay Forward", + [DHCP6_MESSAGE_RELAY_REPLY] = "Relay Reply", + [DHCP6_MESSAGE_LEASE_QUERY] = "Lease Query", + [DHCP6_MESSAGE_LEASE_QUERY_REPLY] = "Lease Query Reply", + [DHCP6_MESSAGE_LEASE_QUERY_DONE] = "Lease Query Done", + [DHCP6_MESSAGE_LEASE_QUERY_DATA] = "Lease Query Data", + [DHCP6_MESSAGE_RECONFIGURE_REQUEST] = "Reconfigure Request", + [DHCP6_MESSAGE_RECONFIGURE_REPLY] = "Reconfigure Reply", + [DHCP6_MESSAGE_DHCPV4_QUERY] = "DHCPv4 Query", + [DHCP6_MESSAGE_DHCPV4_RESPONSE] = "DHCPv4 Response", + [DHCP6_MESSAGE_ACTIVE_LEASE_QUERY] = "Active Lease Query", + [DHCP6_MESSAGE_START_TLS] = "Start TLS", + [DHCP6_MESSAGE_BINDING_UPDATE] = "Binding Update", + [DHCP6_MESSAGE_BINDING_REPLY] = "Binding Reply", + [DHCP6_MESSAGE_POOL_REQUEST] = "Pool Request", + [DHCP6_MESSAGE_POOL_RESPONSE] = "Pool Response", + [DHCP6_MESSAGE_UPDATE_REQUEST] = "Update Request", + [DHCP6_MESSAGE_UPDATE_REQUEST_ALL] = "Update Request All", + [DHCP6_MESSAGE_UPDATE_DONE] = "Update Done", + [DHCP6_MESSAGE_CONNECT] = "Connect", + [DHCP6_MESSAGE_CONNECT_REPLY] = "Connect Reply", + [DHCP6_MESSAGE_DISCONNECT] = "Disconnect", + [DHCP6_MESSAGE_STATE] = "State", + [DHCP6_MESSAGE_CONTACT] = "Contact", }; DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int); @@ -151,7 +174,7 @@ DEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int); #define DHCP6_CLIENT_DONT_DESTROY(client) \ _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client) -static int client_start(sd_dhcp6_client *client, enum DHCP6State state); +static int client_start(sd_dhcp6_client *client, DHCP6State state); int sd_dhcp6_client_set_callback( sd_dhcp6_client *client, @@ -234,10 +257,6 @@ int sd_dhcp6_client_set_mac( return 0; } - if (client->mac_addr_len == addr_len && - memcmp(&client->mac_addr, addr, addr_len) == 0) - return 0; - memcpy(&client->mac_addr, addr, addr_len); client->mac_addr_len = addr_len; client->arp_type = arp_type; @@ -475,7 +494,7 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) assert_return(client, -EINVAL); assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY); - if (option <= 0 || option >= UINT8_MAX) + if (!dhcp6_option_can_request(option)) return -EINVAL; for (t = 0; t < client->req_opts_len; t++) @@ -548,7 +567,7 @@ int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegati assert_return(client, -EINVAL); assert_return(delegation, -EINVAL); - *delegation = FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD); + *delegation = FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_PD); return 0; } @@ -556,7 +575,7 @@ int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegati 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); + SET_FLAG(client->request_ia, DHCP6_REQUEST_IA_PD, delegation); return 0; } @@ -565,7 +584,7 @@ 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); + *request = FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_NA); return 0; } @@ -573,7 +592,7 @@ int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client, int *request) { 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); + SET_FLAG(client->request_ia, DHCP6_REQUEST_IA_NA, request); return 0; } @@ -678,11 +697,11 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { switch(client->state) { case DHCP6_STATE_INFORMATION_REQUEST: - message->type = DHCP6_INFORMATION_REQUEST; + message->type = DHCP6_MESSAGE_INFORMATION_REQUEST; if (client->mudurl) { r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), + SD_DHCP6_OPTION_MUD_URL_V6, strlen(client->mudurl), client->mudurl); if (r < 0) return r; @@ -691,14 +710,14 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { break; case DHCP6_STATE_SOLICITATION: - message->type = DHCP6_SOLICIT; + message->type = DHCP6_MESSAGE_SOLICIT; r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_RAPID_COMMIT, 0, NULL); if (r < 0) return r; - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) { + if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_NA)) { r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na); if (r < 0) @@ -713,7 +732,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (client->mudurl) { r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), + SD_DHCP6_OPTION_MUD_URL_V6, strlen(client->mudurl), client->mudurl); if (r < 0) return r; @@ -738,7 +757,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { + if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_PD)) { r = dhcp6_option_append_pd(&opt, &optlen, &client->ia_pd, &client->hint_pd_prefix); if (r < 0) return r; @@ -750,9 +769,9 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { case DHCP6_STATE_RENEW: if (client->state == DHCP6_STATE_REQUEST) - message->type = DHCP6_REQUEST; + message->type = DHCP6_MESSAGE_REQUEST; else - message->type = DHCP6_RENEW; + message->type = DHCP6_MESSAGE_RENEW; r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_SERVERID, client->lease->serverid_len, @@ -760,7 +779,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (r < 0) return r; - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) { + if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) { r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia); if (r < 0) @@ -775,7 +794,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (client->mudurl) { r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), + SD_DHCP6_OPTION_MUD_URL_V6, strlen(client->mudurl), client->mudurl); if (r < 0) return r; @@ -799,7 +818,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) { + if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) { r = dhcp6_option_append_pd(&opt, &optlen, &client->lease->pd, NULL); if (r < 0) return r; @@ -808,9 +827,9 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { break; case DHCP6_STATE_REBIND: - message->type = DHCP6_REBIND; + message->type = DHCP6_MESSAGE_REBIND; - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA)) { + if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_NA)) { r = dhcp6_option_append_ia(&opt, &optlen, &client->lease->ia); if (r < 0) return r; @@ -824,7 +843,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (client->mudurl) { r = dhcp6_option_append(&opt, &optlen, - SD_DHCP6_OPTION_MUD_URL, strlen(client->mudurl), + SD_DHCP6_OPTION_MUD_URL_V6, strlen(client->mudurl), client->mudurl); if (r < 0) return r; @@ -848,7 +867,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { return r; } - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { + if (FLAGS_SET(client->request_ia, DHCP6_REQUEST_IA_PD) && client->lease->pd.addresses) { r = dhcp6_option_append_pd(&opt, &optlen, &client->lease->pd, NULL); if (r < 0) return r; @@ -859,6 +878,8 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { case DHCP6_STATE_STOPPED: case DHCP6_STATE_BOUND: return -EINVAL; + default: + assert_not_reached(); } r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ORO, @@ -873,14 +894,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { if (r < 0) return r; - elapsed_usec = time_now - client->transaction_start; - if (elapsed_usec < 0xffff * USEC_PER_MSEC * 10) - elapsed_time = htobe16(elapsed_usec / USEC_PER_MSEC / 10); - else - elapsed_time = 0xffff; - - r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME, - sizeof(elapsed_time), &elapsed_time); + /* RFC 8415 Section 21.9. + * A client MUST include an Elapsed Time option in messages to indicate how long the client has + * been trying to complete a DHCP message exchange. */ + elapsed_usec = MIN(usec_sub_unsigned(time_now, client->transaction_start) / USEC_PER_MSEC / 10, (usec_t) UINT16_MAX); + elapsed_time = htobe16(elapsed_usec); + r = dhcp6_option_append(&opt, &optlen, SD_DHCP6_OPTION_ELAPSED_TIME, sizeof(elapsed_time), &elapsed_time); if (r < 0) return r; @@ -936,7 +955,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata) static int client_timeout_resend_expire(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp6_client *client = userdata; DHCP6_CLIENT_DONT_DESTROY(client); - enum DHCP6State state; + DHCP6State state; assert(s); assert(client); @@ -980,7 +999,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda case DHCP6_STATE_SOLICITATION: - if (client->retransmit_count && client->lease) { + if (client->retransmit_count > 0 && client->lease) { client_start(client, DHCP6_STATE_REQUEST); return 0; } @@ -1027,6 +1046,8 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda case DHCP6_STATE_STOPPED: case DHCP6_STATE_BOUND: return 0; + default: + assert_not_reached(); } if (max_retransmit_count > 0 && @@ -1051,8 +1072,8 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec, void *userda client->retransmit_time += init_retransmit_time / 10; } else { - if (max_retransmit_time > 0 && - client->retransmit_time > max_retransmit_time / 2) + assert(max_retransmit_time > 0); + if (client->retransmit_time > max_retransmit_time / 2) client->retransmit_time = client_timeout_compute_random(max_retransmit_time); else client->retransmit_time += client_timeout_compute_random(client->retransmit_time); @@ -1113,7 +1134,7 @@ static int client_ensure_iaid(sd_dhcp6_client *client) { return 0; } -static int client_parse_message( +int client_parse_message( sd_dhcp6_client *client, DHCP6Message *message, size_t len, @@ -1121,7 +1142,6 @@ static int client_parse_message( uint32_t lt_t1 = UINT32_MAX, lt_t2 = UINT32_MAX; usec_t irt = IRT_DEFAULT; - bool clientid = false; int r; assert(client); @@ -1141,23 +1161,19 @@ static int client_parse_message( switch (optcode) { case SD_DHCP6_OPTION_CLIENTID: - if (clientid) - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "%s contains multiple clientids", + if (dhcp6_lease_get_clientid(lease, NULL, NULL) >= 0) + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "%s contains multiple client IDs", dhcp6_message_type_to_string(message->type)); - if (optlen != client->duid_len || - memcmp(&client->duid, optval, optlen) != 0) - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "%s DUID does not match", - dhcp6_message_type_to_string(message->type)); - - clientid = true; + r = dhcp6_lease_set_clientid(lease, optval, optlen); + if (r < 0) + return r; break; case SD_DHCP6_OPTION_SERVERID: - r = dhcp6_lease_get_serverid(lease, NULL, NULL); - if (r >= 0) - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "%s contains multiple serverids", + if (dhcp6_lease_get_serverid(lease, NULL, NULL) >= 0) + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "%s contains multiple server IDs", dhcp6_message_type_to_string(message->type)); r = dhcp6_lease_set_serverid(lease, optval, optlen); @@ -1255,35 +1271,35 @@ static int client_parse_message( case SD_DHCP6_OPTION_DNS_SERVERS: r = dhcp6_lease_add_dns(lease, optval, optlen); if (r < 0) - return r; + log_dhcp6_client_errno(client, r, "Failed to parse DNS server option, ignoring: %m"); break; case SD_DHCP6_OPTION_DOMAIN_LIST: r = dhcp6_lease_add_domains(lease, optval, optlen); if (r < 0) - return r; + log_dhcp6_client_errno(client, r, "Failed to parse domain list option, ignoring: %m"); break; case SD_DHCP6_OPTION_NTP_SERVER: r = dhcp6_lease_add_ntp(lease, optval, optlen); if (r < 0) - return r; + log_dhcp6_client_errno(client, r, "Failed to parse NTP server option, ignoring: %m"); break; case SD_DHCP6_OPTION_SNTP_SERVERS: r = dhcp6_lease_add_sntp(lease, optval, optlen); if (r < 0) - return r; + log_dhcp6_client_errno(client, r, "Failed to parse SNTP server option, ignoring: %m"); break; - case SD_DHCP6_OPTION_FQDN: + case SD_DHCP6_OPTION_CLIENT_FQDN: r = dhcp6_lease_set_fqdn(lease, optval, optlen); if (r < 0) - return r; + log_dhcp6_client_errno(client, r, "Failed to parse FQDN option, ignoring: %m"); break; @@ -1296,8 +1312,15 @@ static int client_parse_message( } } - if (!clientid) - return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "%s has incomplete options", + uint8_t *clientid; + size_t clientid_len; + if (dhcp6_lease_get_clientid(lease, &clientid, &clientid_len) < 0) + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "%s message does not contain client ID. Ignoring.", + dhcp6_message_type_to_string(message->type)); + + if (clientid_len != client->duid_len || + memcmp(clientid, &client->duid, clientid_len) != 0) + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "The client ID in %s message does not match. Ignoring.", dhcp6_message_type_to_string(message->type)); if (client->state != DHCP6_STATE_INFORMATION_REQUEST) { @@ -1325,21 +1348,32 @@ static int client_parse_message( return 0; } -static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, size_t len) { +static int client_receive_reply( + sd_dhcp6_client *client, + DHCP6Message *reply, + size_t len, + const triple_timestamp *t, + const struct in6_addr *server_address) { + _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; bool rapid_commit; int r; assert(client); assert(reply); + assert(t); - if (reply->type != DHCP6_REPLY) + if (reply->type != DHCP6_MESSAGE_REPLY) return 0; r = dhcp6_lease_new(&lease); if (r < 0) return -ENOMEM; + lease->timestamp = *t; + if (server_address) + lease->server_address = *server_address; + r = client_parse_message(client, reply, len, lease); if (r < 0) return r; @@ -1359,18 +1393,32 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si return DHCP6_STATE_BOUND; } -static int client_receive_advertise(sd_dhcp6_client *client, DHCP6Message *advertise, size_t len) { +static int client_receive_advertise( + sd_dhcp6_client *client, + DHCP6Message *advertise, + size_t len, + const triple_timestamp *t, + const struct in6_addr *server_address) { + _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; uint8_t pref_advertise = 0, pref_lease = 0; int r; - if (advertise->type != DHCP6_ADVERTISE) + assert(client); + assert(advertise); + assert(t); + + if (advertise->type != DHCP6_MESSAGE_ADVERTISE) return 0; r = dhcp6_lease_new(&lease); if (r < 0) return r; + lease->timestamp = *t; + if (server_address) + lease->server_address = *server_address; + r = client_parse_message(client, advertise, len, lease); if (r < 0) return r; @@ -1401,7 +1449,22 @@ static int client_receive_message( sd_dhcp6_client *client = userdata; DHCP6_CLIENT_DONT_DESTROY(client); + /* This needs to be initialized with zero. See #20741. */ + CMSG_BUFFER_TYPE(CMSG_SPACE_TIMEVAL) control = {}; + struct iovec iov; + union sockaddr_union sa = {}; + struct msghdr msg = { + .msg_name = &sa.sa, + .msg_namelen = sizeof(sa), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg; + triple_timestamp t = {}; _cleanup_free_ DHCP6Message *message = NULL; + struct in6_addr *server_address = NULL; ssize_t buflen, len; int r = 0; @@ -1410,52 +1473,59 @@ static int client_receive_message( assert(client->event); buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) - /* the link is down. Don't return an error or the I/O event - source will be disconnected and we won't be able to receive - packets again when the link comes back. */ + if (buflen < 0) { + if (ERRNO_IS_TRANSIENT(buflen) || ERRNO_IS_DISCONNECT(buflen)) + return 0; + + log_dhcp6_client_errno(client, buflen, "Failed to determine datagram size to read, ignoring: %m"); return 0; - if (buflen < 0) - return buflen; + } message = malloc(buflen); if (!message) return -ENOMEM; - len = recv(fd, message, buflen, 0); + iov = IOVEC_MAKE(message, buflen); + + len = recvmsg_safe(fd, &msg, MSG_DONTWAIT); if (len < 0) { - /* see comment above for why we shouldn't error out on ENETDOWN. */ - if (IN_SET(errno, EAGAIN, EINTR, ENETDOWN)) + if (ERRNO_IS_TRANSIENT(len) || ERRNO_IS_DISCONNECT(len)) return 0; - return log_dhcp6_client_errno(client, errno, "Could not receive message from UDP socket: %m"); - + log_dhcp6_client_errno(client, len, "Could not receive message from UDP socket, ignoring: %m"); + return 0; } if ((size_t) len < sizeof(DHCP6Message)) { log_dhcp6_client(client, "Too small to be DHCP6 message: ignoring"); return 0; } - switch(message->type) { - case DHCP6_SOLICIT: - case DHCP6_REQUEST: - case DHCP6_CONFIRM: - case DHCP6_RENEW: - case DHCP6_REBIND: - case DHCP6_RELEASE: - case DHCP6_DECLINE: - case DHCP6_INFORMATION_REQUEST: - case DHCP6_RELAY_FORW: - case DHCP6_RELAY_REPL: - return 0; + /* msg_namelen == 0 happens when running the test-suite over a socketpair */ + if (msg.msg_namelen > 0) { + if (msg.msg_namelen != sizeof(struct sockaddr_in6) || sa.in6.sin6_family != AF_INET6) { + log_dhcp6_client(client, "Received message from invalid source, ignoring."); + return 0; + } - case DHCP6_ADVERTISE: - case DHCP6_REPLY: - case DHCP6_RECONFIGURE: - break; + server_address = &sa.in6.sin6_addr; + } - default: - log_dhcp6_client(client, "Unknown message type %d", message->type); + CMSG_FOREACH(cmsg, &msg) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SO_TIMESTAMP && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) + triple_timestamp_from_realtime(&t, timeval_load((struct timeval*) CMSG_DATA(cmsg))); + } + + if (!triple_timestamp_is_set(&t)) + triple_timestamp_get(&t); + + if (!IN_SET(message->type, DHCP6_MESSAGE_ADVERTISE, DHCP6_MESSAGE_REPLY, DHCP6_MESSAGE_RECONFIGURE)) { + const char *type_str = dhcp6_message_type_to_string(message->type); + if (type_str) + log_dhcp6_client(client, "Received unexpected %s message, ignoring.", type_str); + else + log_dhcp6_client(client, "Received unsupported message type %u, ignoring.", message->type); return 0; } @@ -1464,7 +1534,7 @@ static int client_receive_message( switch (client->state) { case DHCP6_STATE_INFORMATION_REQUEST: - r = client_receive_reply(client, message, len); + r = client_receive_reply(client, message, len, &t, server_address); if (r < 0) { log_dhcp6_client_errno(client, r, "Failed to process received reply message, ignoring: %m"); return 0; @@ -1477,7 +1547,7 @@ static int client_receive_message( break; case DHCP6_STATE_SOLICITATION: - r = client_receive_advertise(client, message, len); + r = client_receive_advertise(client, message, len, &t, server_address); if (r < 0) { log_dhcp6_client_errno(client, r, "Failed to process received advertise message, ignoring: %m"); return 0; @@ -1493,7 +1563,7 @@ static int client_receive_message( case DHCP6_STATE_RENEW: case DHCP6_STATE_REBIND: - r = client_receive_reply(client, message, len); + r = client_receive_reply(client, message, len, &t, server_address); if (r < 0) { log_dhcp6_client_errno(client, r, "Failed to process received reply message, ignoring: %m"); return 0; @@ -1517,6 +1587,8 @@ static int client_receive_message( case DHCP6_STATE_STOPPED: return 0; + default: + assert_not_reached(); } log_dhcp6_client(client, "Recv %s", @@ -1530,14 +1602,14 @@ static int client_get_lifetime(sd_dhcp6_client *client, uint32_t *lifetime_t1, assert_return(client, -EINVAL); assert_return(client->lease, -EINVAL); - if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_NA) && client->lease->ia.addresses) { + if (FLAGS_SET(client->request_ia, 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) { + if (FLAGS_SET(client->request_ia, 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); @@ -1547,7 +1619,7 @@ static int client_get_lifetime(sd_dhcp6_client *client, uint32_t *lifetime_t1, return -ENOMSG; } -static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { +static int client_start(sd_dhcp6_client *client, DHCP6State state) { int r; usec_t timeout, time_now; uint32_t lifetime_t1, lifetime_t2; @@ -1647,6 +1719,8 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { client->state = state; return 0; + default: + assert_not_reached(); } client->transaction_id = random_u32() & htobe32(0x00ffffff); @@ -1685,7 +1759,7 @@ int sd_dhcp6_client_is_running(sd_dhcp6_client *client) { } int sd_dhcp6_client_start(sd_dhcp6_client *client) { - enum DHCP6State state = DHCP6_STATE_SOLICITATION; + DHCP6State state = DHCP6_STATE_SOLICITATION; int r; assert_return(client, -EINVAL); @@ -1696,7 +1770,7 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { if (client->state != DHCP6_STATE_STOPPED) return -EBUSY; - if (!client->information_request && !client->request) + if (!client->information_request && client->request_ia == 0) return -EINVAL; r = client_reset(client); @@ -1824,7 +1898,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) { .ia_na.type = SD_DHCP6_OPTION_IA_NA, .ia_pd.type = SD_DHCP6_OPTION_IA_PD, .ifindex = -1, - .request = DHCP6_REQUEST_IA_NA, + .request_ia = DHCP6_REQUEST_IA_NA | DHCP6_REQUEST_IA_PD, .fd = -1, .req_opts_len = ELEMENTSOF(default_req_opts), .hint_pd_prefix.iapdprefix.lifetime_preferred = (be32_t) -1, diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c index 85649d92..b46a2e33 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c @@ -13,6 +13,27 @@ #include "strv.h" #include "util.h" +int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_t *ret) { + assert_return(lease, -EINVAL); + assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP); + assert_return(clock_supported(clock), -EOPNOTSUPP); + assert_return(ret, -EINVAL); + + if (!triple_timestamp_is_set(&lease->timestamp)) + return -ENODATA; + + *ret = triple_timestamp_by_clock(&lease->timestamp, clock); + return 0; +} + +int sd_dhcp6_lease_get_server_address(sd_dhcp6_lease *lease, struct in6_addr *ret) { + assert_return(lease, -EINVAL); + assert_return(ret, -EINVAL); + + *ret = lease->server_address; + return 0; +} + int dhcp6_lease_ia_rebind_expire(const DHCP6IA *ia, uint32_t *expire) { DHCP6Address *addr; uint32_t valid = 0, t; @@ -52,12 +73,43 @@ DHCP6IA *dhcp6_lease_free_ia(DHCP6IA *ia) { return NULL; } -int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, - size_t len) { +int dhcp6_lease_set_clientid(sd_dhcp6_lease *lease, const uint8_t *id, size_t len) { + uint8_t *clientid; + + assert_return(lease, -EINVAL); + assert_return(id, -EINVAL); + assert_return(len > 0, -EINVAL); + + clientid = memdup(id, len); + if (!clientid) + return -ENOMEM; + + free_and_replace(lease->clientid, clientid); + lease->clientid_len = len; + + return 0; +} + +int dhcp6_lease_get_clientid(sd_dhcp6_lease *lease, uint8_t **ret_id, size_t *ret_len) { + assert_return(lease, -EINVAL); + + if (!lease->clientid) + return -ENODATA; + + if (ret_id) + *ret_id = lease->clientid; + if (ret_len) + *ret_len = lease->clientid_len; + + return 0; +} + +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); + assert_return(len > 0, -EINVAL); serverid = memdup(id, len); if (!serverid) @@ -69,16 +121,16 @@ int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id, return 0; } -int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len) { +int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **ret_id, size_t *ret_len) { assert_return(lease, -EINVAL); if (!lease->serverid) - return -ENOMSG; + return -ENODATA; - if (id) - *id = lease->serverid; - if (len) - *len = lease->serverid_len; + if (ret_id) + *ret_id = lease->serverid; + if (ret_len) + *ret_len = lease->serverid_len; return 0; } @@ -119,24 +171,6 @@ int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit) { return 0; } -int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) { - assert_return(lease, -EINVAL); - assert_return(iaid, -EINVAL); - - *iaid = lease->ia.ia_na.id; - - 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) { @@ -207,12 +241,13 @@ int dhcp6_lease_add_dns(sd_dhcp6_lease *lease, const uint8_t *optval, size_t opt int sd_dhcp6_lease_get_dns(sd_dhcp6_lease *lease, const struct in6_addr **ret) { assert_return(lease, -EINVAL); - assert_return(ret, -EINVAL); if (!lease->dns) return -ENOENT; - *ret = lease->dns; + if (ret) + *ret = lease->dns; + return lease->dns_count; } @@ -305,16 +340,17 @@ int dhcp6_lease_add_sntp(sd_dhcp6_lease *lease, const uint8_t *optval, size_t op int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr **ret) { assert_return(lease, -EINVAL); - assert_return(ret, -EINVAL); if (lease->ntp) { - *ret = lease->ntp; + if (ret) + *ret = lease->ntp; return lease->ntp_count; } if (lease->sntp && !lease->ntp_fqdn) { /* Fallback to the deprecated SNTP option. */ - *ret = lease->sntp; + if (ret) + *ret = lease->sntp; return lease->sntp_count; } @@ -323,12 +359,12 @@ int sd_dhcp6_lease_get_ntp_addrs(sd_dhcp6_lease *lease, const struct in6_addr ** int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ret) { assert_return(lease, -EINVAL); - assert_return(ret, -EINVAL); if (!lease->ntp_fqdn) return -ENOENT; - *ret = lease->ntp_fqdn; + if (ret) + *ret = lease->ntp_fqdn; return strv_length(lease->ntp_fqdn); } @@ -366,6 +402,7 @@ static sd_dhcp6_lease *dhcp6_lease_free(sd_dhcp6_lease *lease) { if (!lease) return NULL; + free(lease->clientid); free(lease->serverid); dhcp6_lease_free_ia(&lease->ia); dhcp6_lease_free_ia(&lease->pd); diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-ipv4acd.c b/src/libnm-systemd-core/src/libsystemd-network/sd-ipv4acd.c deleted file mode 100644 index f0612ed5..00000000 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-ipv4acd.c +++ /dev/null @@ -1,616 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include <arpa/inet.h> -#include <errno.h> -#include <netinet/if_ether.h> -#include <stdio.h> -#include <stdlib.h> - -#include "sd-ipv4acd.h" - -#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 "memory-util.h" -#include "network-common.h" -#include "random-util.h" -#include "siphash24.h" -#include "string-table.h" -#include "string-util.h" -#include "time-util.h" - -/* Constants from the RFC */ -#define PROBE_WAIT_USEC (1U * USEC_PER_SEC) -#define PROBE_NUM 3U -#define PROBE_MIN_USEC (1U * USEC_PER_SEC) -#define PROBE_MAX_USEC (2U * USEC_PER_SEC) -#define ANNOUNCE_WAIT_USEC (2U * USEC_PER_SEC) -#define ANNOUNCE_NUM 2U -#define ANNOUNCE_INTERVAL_USEC (2U * USEC_PER_SEC) -#define MAX_CONFLICTS 10U -#define RATE_LIMIT_INTERVAL_USEC (60U * USEC_PER_SEC) -#define DEFEND_INTERVAL_USEC (10U * USEC_PER_SEC) - -typedef enum IPv4ACDState { - IPV4ACD_STATE_INIT, - IPV4ACD_STATE_STARTED, - IPV4ACD_STATE_WAITING_PROBE, - IPV4ACD_STATE_PROBING, - IPV4ACD_STATE_WAITING_ANNOUNCE, - IPV4ACD_STATE_ANNOUNCING, - IPV4ACD_STATE_RUNNING, - _IPV4ACD_STATE_MAX, - _IPV4ACD_STATE_INVALID = -EINVAL, -} IPv4ACDState; - -struct sd_ipv4acd { - unsigned n_ref; - - IPv4ACDState state; - int ifindex; - int fd; - - char *ifname; - unsigned n_iteration; - unsigned n_conflict; - - sd_event_source *receive_message_event_source; - sd_event_source *timer_event_source; - - usec_t defend_window; - struct in_addr address; - - /* External */ - struct ether_addr mac_addr; - - sd_event *event; - int event_priority; - sd_ipv4acd_callback_t callback; - void *userdata; - sd_ipv4acd_check_mac_callback_t check_mac_callback; - void *check_mac_userdata; -}; - -#define log_ipv4acd_errno(acd, error, fmt, ...) \ - log_interface_prefix_full_errno( \ - "IPv4ACD: ", \ - sd_ipv4acd, acd, \ - error, fmt, ##__VA_ARGS__) -#define log_ipv4acd(acd, fmt, ...) \ - log_interface_prefix_full_errno_zerook( \ - "IPv4ACD: ", \ - sd_ipv4acd, acd, \ - 0, fmt, ##__VA_ARGS__) - -static const char * const ipv4acd_state_table[_IPV4ACD_STATE_MAX] = { - [IPV4ACD_STATE_INIT] = "init", - [IPV4ACD_STATE_STARTED] = "started", - [IPV4ACD_STATE_WAITING_PROBE] = "waiting-probe", - [IPV4ACD_STATE_PROBING] = "probing", - [IPV4ACD_STATE_WAITING_ANNOUNCE] = "waiting-announce", - [IPV4ACD_STATE_ANNOUNCING] = "announcing", - [IPV4ACD_STATE_RUNNING] = "running", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ipv4acd_state, IPv4ACDState); - -static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) { - assert(acd); - assert(st < _IPV4ACD_STATE_MAX); - - if (st != acd->state) - log_ipv4acd(acd, "%s -> %s", ipv4acd_state_to_string(acd->state), ipv4acd_state_to_string(st)); - - if (st == acd->state && !reset_counter) - acd->n_iteration++; - else { - acd->state = st; - acd->n_iteration = 0; - } -} - -static void ipv4acd_reset(sd_ipv4acd *acd) { - assert(acd); - - (void) event_source_disable(acd->timer_event_source); - acd->receive_message_event_source = sd_event_source_disable_unref(acd->receive_message_event_source); - - acd->fd = safe_close(acd->fd); - - ipv4acd_set_state(acd, IPV4ACD_STATE_INIT, true); -} - -static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) { - assert(acd); - - ipv4acd_reset(acd); - sd_event_source_unref(acd->timer_event_source); - sd_ipv4acd_detach_event(acd); - free(acd->ifname); - 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 = new(sd_ipv4acd, 1); - if (!acd) - return -ENOMEM; - - *acd = (sd_ipv4acd) { - .n_ref = 1, - .state = IPV4ACD_STATE_INIT, - .ifindex = -1, - .fd = -1, - }; - - *ret = TAKE_PTR(acd); - - return 0; -} - -static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) { - assert(acd); - - if (!acd->callback) - return; - - acd->callback(acd, event, acd->userdata); -} - -int sd_ipv4acd_stop(sd_ipv4acd *acd) { - IPv4ACDState old_state; - - if (!acd) - return 0; - - old_state = acd->state; - - ipv4acd_reset(acd); - - if (old_state == IPV4ACD_STATE_INIT) - return 0; - - log_ipv4acd(acd, "STOPPED"); - - ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP); - - return 0; -} - -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) { - usec_t next_timeout, time_now; - - assert(acd); - - next_timeout = usec; - - if (random_usec > 0) - next_timeout += (usec_t) random_u64() % random_usec; - - assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 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 int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) { - sd_ipv4acd *acd = userdata; - int r = 0; - - assert(acd); - - switch (acd->state) { - - case IPV4ACD_STATE_STARTED: - acd->defend_window = 0; - - ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true); - - if (acd->n_conflict >= MAX_CONFLICTS) { - log_ipv4acd(acd, "Max conflicts reached, delaying by %s", - FORMAT_TIMESPAN(RATE_LIMIT_INTERVAL_USEC, 0)); - r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC); - } else - r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC); - if (r < 0) - goto fail; - - break; - - case IPV4ACD_STATE_WAITING_PROBE: - case IPV4ACD_STATE_PROBING: - /* Send a probe */ - r = arp_send_probe(acd->fd, acd->ifindex, &acd->address, &acd->mac_addr); - if (r < 0) { - log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m"); - goto fail; - } - - log_ipv4acd(acd, "Probing "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(acd->address)); - - if (acd->n_iteration < PROBE_NUM - 2) { - ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false); - - r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC)); - if (r < 0) - goto fail; - } else { - ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true); - - r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0); - if (r < 0) - goto fail; - } - - break; - - case IPV4ACD_STATE_ANNOUNCING: - if (acd->n_iteration >= ANNOUNCE_NUM - 1) { - ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false); - break; - } - - _fallthrough_; - case IPV4ACD_STATE_WAITING_ANNOUNCE: - /* Send announcement packet */ - r = arp_send_announcement(acd->fd, acd->ifindex, &acd->address, &acd->mac_addr); - if (r < 0) { - log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); - goto fail; - } - - log_ipv4acd(acd, "Announcing "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(acd->address)); - - ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false); - - r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0); - if (r < 0) - goto fail; - - if (acd->n_iteration == 0) { - acd->n_conflict = 0; - ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND); - } - - break; - - default: - assert_not_reached(); - } - - return 0; - -fail: - sd_ipv4acd_stop(acd); - return 0; -} - -static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, const struct ether_arp *arp, bool announced) { - assert(acd); - assert(arp); - - /* RFC 5227 section 2.1.1. - * "the host receives any ARP packet (Request *or* Reply) on the interface where the probe is - * being performed, where the packet's 'sender IP address' is the address being probed for, - * then the host MUST treat this address as being in use by some other host" */ - if (memcmp(arp->arp_spa, &acd->address, sizeof(struct in_addr)) == 0) - return true; - - if (announced) - /* the TPA matched instead of SPA, this is not a conflict */ - return false; - - /* "any ARP Probe where the packet's 'target IP address' is the address being probed for, and - * the packet's 'sender hardware address' is not the hardware address of any of the host's - * interfaces, then the host SHOULD similarly treat this as an address conflict" */ - if (arp->ea_hdr.ar_op != htobe16(ARPOP_REQUEST)) - return false; /* not ARP Request, ignoring. */ - if (memeqzero(arp->arp_spa, sizeof(struct in_addr)) == 0) - return false; /* not ARP Probe, ignoring. */ - if (memcmp(arp->arp_tpa, &acd->address, sizeof(struct in_addr)) != 0) - return false; /* target IP address does not match, BPF code is broken? */ - - if (acd->check_mac_callback && - acd->check_mac_callback(acd, (const struct ether_addr*) arp->arp_sha, acd->check_mac_userdata) > 0) - /* sender hardware is one of the host's interfaces, ignoring. */ - return true; - - return true; /* conflict! */ -} - -static void ipv4acd_on_conflict(sd_ipv4acd *acd) { - assert(acd); - - acd->n_conflict++; - - log_ipv4acd(acd, "Conflict on "IPV4_ADDRESS_FMT_STR" (%u)", IPV4_ADDRESS_FMT_VAL(acd->address), acd->n_conflict); - - ipv4acd_reset(acd); - ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT); -} - -static int ipv4acd_on_packet( - sd_event_source *s, - int fd, - uint32_t revents, - void *userdata) { - - sd_ipv4acd *acd = userdata; - struct ether_arp packet; - ssize_t n; - int r; - - assert(s); - assert(acd); - assert(fd >= 0); - - n = recv(fd, &packet, sizeof(struct ether_arp), 0); - if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) - return 0; - - log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m"); - goto fail; - } - if ((size_t) n != sizeof(struct ether_arp)) { - log_ipv4acd(acd, "Ignoring too short ARP packet."); - return 0; - } - - switch (acd->state) { - - case IPV4ACD_STATE_ANNOUNCING: - case IPV4ACD_STATE_RUNNING: - - if (ipv4acd_arp_conflict(acd, &packet, true)) { - usec_t ts; - - assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &ts) >= 0); - - /* Defend address */ - if (ts > acd->defend_window) { - acd->defend_window = ts + DEFEND_INTERVAL_USEC; - r = arp_send_announcement(acd->fd, acd->ifindex, &acd->address, &acd->mac_addr); - if (r < 0) { - log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m"); - goto fail; - } - - log_ipv4acd(acd, "Defending "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(acd->address)); - - } else - ipv4acd_on_conflict(acd); - } - break; - - case IPV4ACD_STATE_WAITING_PROBE: - case IPV4ACD_STATE_PROBING: - case IPV4ACD_STATE_WAITING_ANNOUNCE: - if (ipv4acd_arp_conflict(acd, &packet, false)) - ipv4acd_on_conflict(acd); - break; - - default: - assert_not_reached(); - } - - return 0; - -fail: - sd_ipv4acd_stop(acd); - return 0; -} - -int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) { - assert_return(acd, -EINVAL); - assert_return(ifindex > 0, -EINVAL); - assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - - acd->ifindex = ifindex; - - return 0; -} - -int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd) { - if (!acd) - return -EINVAL; - - return acd->ifindex; -} - -int sd_ipv4acd_set_ifname(sd_ipv4acd *acd, const char *ifname) { - assert_return(acd, -EINVAL); - assert_return(ifname, -EINVAL); - - if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE)) - return -EINVAL; - - return free_and_strdup(&acd->ifname, ifname); -} - -int sd_ipv4acd_get_ifname(sd_ipv4acd *acd, const char **ret) { - int r; - - assert_return(acd, -EINVAL); - - r = get_ifname(acd->ifindex, &acd->ifname); - if (r < 0) - return r; - - if (ret) - *ret = acd->ifname; - - return 0; -} - -int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) { - int r; - - assert_return(acd, -EINVAL); - assert_return(addr, -EINVAL); - assert_return(!ether_addr_is_null(addr), -EINVAL); - - acd->mac_addr = *addr; - - if (!sd_ipv4acd_is_running(acd)) - return 0; - - assert(acd->fd >= 0); - r = arp_update_filter(acd->fd, &acd->address, &acd->mac_addr); - if (r < 0) { - ipv4acd_reset(acd); - return r; - } - - return 0; -} - -int sd_ipv4acd_detach_event(sd_ipv4acd *acd) { - assert_return(acd, -EINVAL); - - acd->event = sd_event_unref(acd->event); - - return 0; -} - -int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority) { - int r; - - assert_return(acd, -EINVAL); - assert_return(!acd->event, -EBUSY); - - if (event) - acd->event = sd_event_ref(event); - else { - r = sd_event_default(&acd->event); - if (r < 0) - return r; - } - - acd->event_priority = priority; - - return 0; -} - -int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata) { - assert_return(acd, -EINVAL); - - acd->callback = cb; - acd->userdata = userdata; - - return 0; -} - -int sd_ipv4acd_set_check_mac_callback(sd_ipv4acd *acd, sd_ipv4acd_check_mac_callback_t cb, void *userdata) { - assert_return(acd, -EINVAL); - - acd->check_mac_callback = cb; - acd->check_mac_userdata = userdata; - return 0; -} - -int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) { - int r; - - assert_return(acd, -EINVAL); - assert_return(address, -EINVAL); - assert_return(in4_addr_is_set(address), -EINVAL); - - if (in4_addr_equal(&acd->address, address)) - return 0; - - acd->address = *address; - - if (!sd_ipv4acd_is_running(acd)) - return 0; - - assert(acd->fd >= 0); - r = arp_update_filter(acd->fd, &acd->address, &acd->mac_addr); - if (r < 0) - goto fail; - - r = ipv4acd_set_next_wakeup(acd, 0, 0); - if (r < 0) - goto fail; - - ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true); - return 0; - -fail: - ipv4acd_reset(acd); - return r; -} - -int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address) { - assert_return(acd, -EINVAL); - assert_return(address, -EINVAL); - - *address = acd->address; - - return 0; -} - -int sd_ipv4acd_is_running(sd_ipv4acd *acd) { - assert_return(acd, false); - - return acd->state != IPV4ACD_STATE_INIT; -} - -int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts) { - int r; - - assert_return(acd, -EINVAL); - assert_return(acd->event, -EINVAL); - assert_return(acd->ifindex > 0, -EINVAL); - assert_return(in4_addr_is_set(&acd->address), -EINVAL); - assert_return(!ether_addr_is_null(&acd->mac_addr), -EINVAL); - assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); - - r = arp_network_bind_raw_socket(acd->ifindex, &acd->address, &acd->mac_addr); - if (r < 0) - return r; - - CLOSE_AND_REPLACE(acd->fd, r); - - if (reset_conflicts) - acd->n_conflict = 0; - - r = sd_event_add_io(acd->event, &acd->receive_message_event_source, acd->fd, EPOLLIN, ipv4acd_on_packet, acd); - if (r < 0) - goto fail; - - r = sd_event_source_set_priority(acd->receive_message_event_source, acd->event_priority); - if (r < 0) - goto fail; - - (void) sd_event_source_set_description(acd->receive_message_event_source, "ipv4acd-receive-message"); - - r = ipv4acd_set_next_wakeup(acd, 0, 0); - if (r < 0) - goto fail; - - ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true); - return 0; - -fail: - ipv4acd_reset(acd); - return r; -} diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-ipv4ll.c b/src/libnm-systemd-core/src/libsystemd-network/sd-ipv4ll.c deleted file mode 100644 index 4a500dfc..00000000 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-ipv4ll.c +++ /dev/null @@ -1,382 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. -***/ - -#include "nm-sd-adapt-core.h" - -#include <arpa/inet.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> - -#include "sd-id128.h" -#include "sd-ipv4acd.h" -#include "sd-ipv4ll.h" - -#include "alloc-util.h" -#include "ether-addr-util.h" -#include "in-addr-util.h" -#include "network-common.h" -#include "random-util.h" -#include "siphash24.h" -#include "sparse-endian.h" -#include "string-util.h" -#include "util.h" - -#define IPV4LL_NETWORK UINT32_C(0xA9FE0000) -#define IPV4LL_NETMASK UINT32_C(0xFFFF0000) - -#define IPV4LL_DONT_DESTROY(ll) \ - _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll) - -struct sd_ipv4ll { - unsigned n_ref; - - sd_ipv4acd *acd; - - be32_t address; /* the address pushed to ACD */ - struct ether_addr mac; - - struct { - le64_t value; - le64_t generation; - } seed; - bool seed_set; - - /* External */ - be32_t claimed_address; - - sd_ipv4ll_callback_t callback; - void *userdata; - - sd_ipv4ll_check_mac_callback_t check_mac_callback; - void *check_mac_userdata; -}; - -#define log_ipv4ll_errno(ll, error, fmt, ...) \ - log_interface_prefix_full_errno( \ - "IPv4LL: ", \ - sd_ipv4ll, ll, \ - error, fmt, ##__VA_ARGS__) -#define log_ipv4ll(ll, fmt, ...) \ - log_interface_prefix_full_errno_zerook( \ - "IPv4LL: ", \ - sd_ipv4ll, ll, \ - 0, fmt, ##__VA_ARGS__) - -static void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata); -static int ipv4ll_check_mac(sd_ipv4acd *acd, const struct ether_addr *mac, void *userdata); - -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; - - assert_return(ret, -EINVAL); - - ll = new0(sd_ipv4ll, 1); - if (!ll) - return -ENOMEM; - - ll->n_ref = 1; - - r = sd_ipv4acd_new(&ll->acd); - if (r < 0) - return r; - - r = sd_ipv4acd_set_callback(ll->acd, ipv4ll_on_acd, ll); - if (r < 0) - return r; - - r = sd_ipv4acd_set_check_mac_callback(ll->acd, ipv4ll_check_mac, ll); - if (r < 0) - return r; - - *ret = TAKE_PTR(ll); - - return 0; -} - -int sd_ipv4ll_stop(sd_ipv4ll *ll) { - if (!ll) - return 0; - - return sd_ipv4acd_stop(ll->acd); -} - -int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int ifindex) { - assert_return(ll, -EINVAL); - assert_return(ifindex > 0, -EINVAL); - assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); - - return sd_ipv4acd_set_ifindex(ll->acd, ifindex); -} - -int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll) { - if (!ll) - return -EINVAL; - - return sd_ipv4acd_get_ifindex(ll->acd); -} - -int sd_ipv4ll_set_ifname(sd_ipv4ll *ll, const char *ifname) { - assert_return(ll, -EINVAL); - assert_return(ifname, -EINVAL); - - return sd_ipv4acd_set_ifname(ll->acd, ifname); -} - -int sd_ipv4ll_get_ifname(sd_ipv4ll *ll, const char **ret) { - assert_return(ll, -EINVAL); - - return sd_ipv4acd_get_ifname(ll->acd, ret); -} - -int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) { - int r; - - assert_return(ll, -EINVAL); - assert_return(addr, -EINVAL); - assert_return(!ether_addr_is_null(addr), -EINVAL); - - r = sd_ipv4acd_set_mac(ll->acd, addr); - if (r < 0) - return r; - - ll->mac = *addr; - return 0; -} - -int sd_ipv4ll_detach_event(sd_ipv4ll *ll) { - assert_return(ll, -EINVAL); - - return sd_ipv4acd_detach_event(ll->acd); -} - -int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority) { - assert_return(ll, -EINVAL); - - return sd_ipv4acd_attach_event(ll->acd, event, priority); -} - -int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata) { - assert_return(ll, -EINVAL); - - ll->callback = cb; - ll->userdata = userdata; - - return 0; -} - -int sd_ipv4ll_set_check_mac_callback(sd_ipv4ll *ll, sd_ipv4ll_check_mac_callback_t cb, void *userdata) { - assert_return(ll, -EINVAL); - - ll->check_mac_callback = cb; - ll->check_mac_userdata = userdata; - - return 0; -} - -int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address) { - assert_return(ll, -EINVAL); - assert_return(address, -EINVAL); - - if (ll->claimed_address == 0) - return -ENOENT; - - address->s_addr = ll->claimed_address; - - return 0; -} - -int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed) { - assert_return(ll, -EINVAL); - assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY); - - ll->seed.value = htole64(seed); - ll->seed_set = true; - - return 0; -} - -int sd_ipv4ll_is_running(sd_ipv4ll *ll) { - assert_return(ll, false); - - return sd_ipv4acd_is_running(ll->acd); -} - -static bool ipv4ll_address_is_valid(const struct in_addr *address) { - assert(address); - - if (!in4_addr_is_link_local(address)) - return false; - - return !IN_SET(be32toh(address->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U); -} - -int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) { - int r; - - assert_return(ll, -EINVAL); - assert_return(address, -EINVAL); - assert_return(ipv4ll_address_is_valid(address), -EINVAL); - - r = sd_ipv4acd_set_address(ll->acd, address); - if (r < 0) - return r; - - ll->address = address->s_addr; - - return 0; -} - -#define PICK_HASH_KEY SD_ID128_MAKE(15,ac,82,a6,d6,3f,49,78,98,77,5d,0c,69,02,94,0b) - -static int ipv4ll_pick_address(sd_ipv4ll *ll) { - _cleanup_free_ char *address = NULL; - be32_t addr; - - assert(ll); - - do { - uint64_t h; - - h = siphash24(&ll->seed, sizeof(ll->seed), PICK_HASH_KEY.bytes); - - /* Increase the generation counter by one */ - ll->seed.generation = htole64(le64toh(ll->seed.generation) + 1); - - addr = htobe32((h & UINT32_C(0x0000FFFF)) | IPV4LL_NETWORK); - } while (addr == ll->address || - IN_SET(be32toh(addr) & 0x0000FF00U, 0x0000U, 0xFF00U)); - - (void) in_addr_to_string(AF_INET, &(union in_addr_union) { .in.s_addr = addr }, &address); - log_ipv4ll(ll, "Picked new IP address %s.", strna(address)); - - return sd_ipv4ll_set_address(ll, &(struct in_addr) { addr }); -} - -#define MAC_HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2) - -static int ipv4ll_start_internal(sd_ipv4ll *ll, bool reset_generation) { - int r; - bool picked_address = false; - - assert_return(ll, -EINVAL); - assert_return(!ether_addr_is_null(&ll->mac), -EINVAL); - - /* If no random seed is set, generate some from the MAC address */ - if (!ll->seed_set) - ll->seed.value = htole64(siphash24(ll->mac.ether_addr_octet, ETH_ALEN, MAC_HASH_KEY.bytes)); - - if (reset_generation) - ll->seed.generation = 0; - - if (ll->address == 0) { - r = ipv4ll_pick_address(ll); - if (r < 0) - return r; - - picked_address = true; - } - - r = sd_ipv4acd_start(ll->acd, reset_generation); - if (r < 0) { - - /* We couldn't start? If so, let's forget the picked address again, the user might make a change and - * retry, and we want the new data to take effect when picking an address. */ - if (picked_address) - ll->address = 0; - - return r; - } - - return 1; -} - -int sd_ipv4ll_start(sd_ipv4ll *ll) { - assert_return(ll, -EINVAL); - - if (sd_ipv4ll_is_running(ll)) - return 0; - - return ipv4ll_start_internal(ll, true); -} - -int sd_ipv4ll_restart(sd_ipv4ll *ll) { - ll->address = 0; - - return ipv4ll_start_internal(ll, false); -} - -static void ipv4ll_client_notify(sd_ipv4ll *ll, int event) { - assert(ll); - - if (ll->callback) - ll->callback(ll, event, ll->userdata); -} - -void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) { - sd_ipv4ll *ll = userdata; - IPV4LL_DONT_DESTROY(ll); - int r; - - assert(acd); - assert(ll); - - switch (event) { - - case SD_IPV4ACD_EVENT_STOP: - ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); - ll->claimed_address = 0; - break; - - case SD_IPV4ACD_EVENT_BIND: - ll->claimed_address = ll->address; - ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_BIND); - break; - - case SD_IPV4ACD_EVENT_CONFLICT: - /* if an address was already bound we must call up to the - user to handle this, otherwise we just try again */ - if (ll->claimed_address != 0) { - ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_CONFLICT); - - ll->claimed_address = 0; - } else { - r = sd_ipv4ll_restart(ll); - if (r < 0) - goto error; - } - - break; - - default: - assert_not_reached(); - } - - return; - -error: - ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP); -} - -static int ipv4ll_check_mac(sd_ipv4acd *acd, const struct ether_addr *mac, void *userdata) { - sd_ipv4ll *ll = userdata; - - assert(ll); - - if (ll->check_mac_callback) - return ll->check_mac_callback(ll, mac, ll->check_mac_userdata); - - return 0; -} diff --git a/src/libnm-systemd-core/src/libsystemd-network/sd-lldp-rx.c b/src/libnm-systemd-core/src/libsystemd-network/sd-lldp-rx.c index 9da2b149..f50e9c8d 100644 --- a/src/libnm-systemd-core/src/libsystemd-network/sd-lldp-rx.c +++ b/src/libnm-systemd-core/src/libsystemd-network/sd-lldp-rx.c @@ -202,6 +202,9 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents space = next_datagram_size_fd(fd); if (space < 0) { + if (ERRNO_IS_TRANSIENT(space) || ERRNO_IS_DISCONNECT(space)) + return 0; + log_lldp_rx_errno(lldp_rx, space, "Failed to determine datagram size to read, ignoring: %m"); return 0; } @@ -214,7 +217,7 @@ static int lldp_rx_receive_datagram(sd_event_source *s, int fd, uint32_t revents length = recv(fd, LLDP_NEIGHBOR_RAW(n), n->raw_size, MSG_DONTWAIT); if (length < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) + if (ERRNO_IS_TRANSIENT(errno) || ERRNO_IS_DISCONNECT(errno)) return 0; log_lldp_rx_errno(lldp_rx, errno, "Failed to read LLDP datagram, ignoring: %m"); @@ -251,7 +254,7 @@ int sd_lldp_rx_is_running(sd_lldp_rx *lldp_rx) { return lldp_rx->fd >= 0; } -_public_ int sd_lldp_rx_start(sd_lldp_rx *lldp_rx) { +int sd_lldp_rx_start(sd_lldp_rx *lldp_rx) { int r; assert_return(lldp_rx, -EINVAL); @@ -285,7 +288,7 @@ fail: return r; } -_public_ int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx) { +int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx) { if (!sd_lldp_rx_is_running(lldp_rx)) return 0; @@ -297,7 +300,7 @@ _public_ int sd_lldp_rx_stop(sd_lldp_rx *lldp_rx) { return 1; } -_public_ int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64_t priority) { +int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64_t priority) { int r; assert_return(lldp_rx, -EINVAL); @@ -317,7 +320,7 @@ _public_ int sd_lldp_rx_attach_event(sd_lldp_rx *lldp_rx, sd_event *event, int64 return 0; } -_public_ int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx) { +int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx) { assert_return(lldp_rx, -EINVAL); assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY); @@ -327,13 +330,13 @@ _public_ int sd_lldp_rx_detach_event(sd_lldp_rx *lldp_rx) { return 0; } -_public_ sd_event* sd_lldp_rx_get_event(sd_lldp_rx *lldp_rx) { +sd_event* sd_lldp_rx_get_event(sd_lldp_rx *lldp_rx) { assert_return(lldp_rx, NULL); return lldp_rx->event; } -_public_ int sd_lldp_rx_set_callback(sd_lldp_rx *lldp_rx, sd_lldp_rx_callback_t cb, void *userdata) { +int sd_lldp_rx_set_callback(sd_lldp_rx *lldp_rx, sd_lldp_rx_callback_t cb, void *userdata) { assert_return(lldp_rx, -EINVAL); lldp_rx->callback = cb; @@ -342,7 +345,7 @@ _public_ int sd_lldp_rx_set_callback(sd_lldp_rx *lldp_rx, sd_lldp_rx_callback_t return 0; } -_public_ int sd_lldp_rx_set_ifindex(sd_lldp_rx *lldp_rx, int ifindex) { +int sd_lldp_rx_set_ifindex(sd_lldp_rx *lldp_rx, int ifindex) { assert_return(lldp_rx, -EINVAL); assert_return(ifindex > 0, -EINVAL); assert_return(!sd_lldp_rx_is_running(lldp_rx), -EBUSY); @@ -394,7 +397,7 @@ static sd_lldp_rx *lldp_rx_free(sd_lldp_rx *lldp_rx) { DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_lldp_rx, sd_lldp_rx, lldp_rx_free); -_public_ int sd_lldp_rx_new(sd_lldp_rx **ret) { +int sd_lldp_rx_new(sd_lldp_rx **ret) { _cleanup_(sd_lldp_rx_unrefp) sd_lldp_rx *lldp_rx = NULL; assert_return(ret, -EINVAL); @@ -462,7 +465,7 @@ static inline int neighbor_compare_func(sd_lldp_neighbor * const *a, sd_lldp_nei return lldp_neighbor_id_compare_func(&(*a)->id, &(*b)->id); } -_public_ int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***ret) { +int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***ret) { _cleanup_free_ sd_lldp_neighbor **l = NULL; sd_lldp_neighbor *n; int k = 0; @@ -491,7 +494,7 @@ _public_ int sd_lldp_rx_get_neighbors(sd_lldp_rx *lldp_rx, sd_lldp_neighbor ***r return k; } -_public_ int sd_lldp_rx_set_neighbors_max(sd_lldp_rx *lldp_rx, uint64_t m) { +int sd_lldp_rx_set_neighbors_max(sd_lldp_rx *lldp_rx, uint64_t m) { assert_return(lldp_rx, -EINVAL); assert_return(m > 0, -EINVAL); @@ -501,7 +504,7 @@ _public_ int sd_lldp_rx_set_neighbors_max(sd_lldp_rx *lldp_rx, uint64_t m) { return 0; } -_public_ int sd_lldp_rx_match_capabilities(sd_lldp_rx *lldp_rx, uint16_t mask) { +int sd_lldp_rx_match_capabilities(sd_lldp_rx *lldp_rx, uint16_t mask) { assert_return(lldp_rx, -EINVAL); assert_return(mask != 0, -EINVAL); @@ -510,7 +513,7 @@ _public_ int sd_lldp_rx_match_capabilities(sd_lldp_rx *lldp_rx, uint16_t mask) { return 0; } -_public_ int sd_lldp_rx_set_filter_address(sd_lldp_rx *lldp_rx, const struct ether_addr *addr) { +int sd_lldp_rx_set_filter_address(sd_lldp_rx *lldp_rx, const struct ether_addr *addr) { assert_return(lldp_rx, -EINVAL); /* In order to deal nicely with bridges that send back our own packets, allow one address to be filtered, so diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h b/src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h index 08b409fe..74cbc269 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h +++ b/src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h @@ -71,6 +71,7 @@ struct sd_event_source { uint64_t prepare_iteration; sd_event_destroy_t destroy_callback; + sd_event_handler_t ratelimit_expire_callback; LIST_FIELDS(sd_event_source, sources); @@ -214,6 +215,11 @@ struct inotify_data { * the events locally if they can't be coalesced). */ unsigned n_pending; + /* If this counter is non-zero, don't GC the inotify data object even if not used to watch any inode + * anymore. This is useful to pin the object for a bit longer, after the last event source needing it + * is gone. */ + unsigned n_busy; + /* A linked list of all inotify objects with data already read, that still need processing. We keep this list * to make it efficient to figure out what inotify objects to process data on next. */ LIST_FIELDS(struct inotify_data, buffered); diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c index 7cc55be1..13e16f9b 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c @@ -86,6 +86,30 @@ int event_reset_time( return created; } +int event_reset_time_relative( + sd_event *e, + sd_event_source **s, + clockid_t clock, + uint64_t usec, + uint64_t accuracy, + sd_event_time_handler_t callback, + void *userdata, + int64_t priority, + const char *description, + bool force_reset) { + + usec_t usec_now; + int r; + + assert(e); + + r = sd_event_now(e, clock, &usec_now); + if (r < 0) + return log_debug_errno(r, "sd-event: Failed to get the current time: %m"); + + return event_reset_time(e, s, clock, usec_add(usec_now, usec), accuracy, callback, userdata, priority, description, force_reset); +} + int event_source_disable(sd_event_source *s) { if (!s) return 0; diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h index c8f97bc8..64a41992 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h +++ b/src/libnm-systemd-core/src/libsystemd/sd-event/event-util.h @@ -5,9 +5,27 @@ #include "sd-event.h" -int event_reset_time(sd_event *e, sd_event_source **s, - clockid_t clock, uint64_t usec, uint64_t accuracy, - sd_event_time_handler_t callback, void *userdata, - int64_t priority, const char *description, bool force_reset); +int event_reset_time( + sd_event *e, + sd_event_source **s, + clockid_t clock, + uint64_t usec, + uint64_t accuracy, + sd_event_time_handler_t callback, + void *userdata, + int64_t priority, + const char *description, + bool force_reset); +int event_reset_time_relative( + sd_event *e, + sd_event_source **s, + clockid_t clock, + uint64_t usec, + uint64_t accuracy, + sd_event_time_handler_t callback, + void *userdata, + int64_t priority, + const char *description, + bool force_reset); int event_source_disable(sd_event_source *s); int event_source_is_enabled(sd_event_source *s); diff --git a/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c b/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c index 0acbdd54..e87d900c 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-event/sd-event.c @@ -1824,6 +1824,29 @@ static void event_free_inode_data( free(d); } +static void event_gc_inotify_data( + sd_event *e, + struct inotify_data *d) { + + assert(e); + + /* GCs the inotify data object if we don't need it anymore. That's the case if we don't want to watch + * any inode with it anymore, which in turn happens if no event source of this priority is interested + * in any inode any longer. That said, we maintain an extra busy counter: if non-zero we'll delay GC + * (under the expectation that the GC is called again once the counter is decremented). */ + + if (!d) + return; + + if (!hashmap_isempty(d->inodes)) + return; + + if (d->n_busy > 0) + return; + + event_free_inotify_data(e, d); +} + static void event_gc_inode_data( sd_event *e, struct inode_data *d) { @@ -1841,8 +1864,7 @@ static void event_gc_inode_data( inotify_data = d->inotify_data; event_free_inode_data(e, d); - if (inotify_data && hashmap_isempty(inotify_data->inodes)) - event_free_inotify_data(e, inotify_data); + event_gc_inotify_data(e, inotify_data); } static int event_make_inode_data( @@ -1971,24 +1993,25 @@ static int inotify_exit_callback(sd_event_source *s, const struct inotify_event return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); } -_public_ int sd_event_add_inotify( +static int event_add_inotify_fd_internal( sd_event *e, sd_event_source **ret, - const char *path, + int fd, + bool donate, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata) { + _cleanup_close_ int donated_fd = donate ? fd : -1; + _cleanup_(source_freep) sd_event_source *s = NULL; struct inotify_data *inotify_data = NULL; struct inode_data *inode_data = NULL; - _cleanup_close_ int fd = -1; - _cleanup_(source_freep) sd_event_source *s = NULL; struct stat st; int r; assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); - assert_return(path, -EINVAL); + assert_return(fd >= 0, -EBADF); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); @@ -2001,12 +2024,6 @@ _public_ int sd_event_add_inotify( if (mask & IN_MASK_ADD) return -EINVAL; - fd = open(path, O_PATH|O_CLOEXEC| - (mask & IN_ONLYDIR ? O_DIRECTORY : 0)| - (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0)); - if (fd < 0) - return -errno; - if (fstat(fd, &st) < 0) return -errno; @@ -2026,14 +2043,24 @@ _public_ int sd_event_add_inotify( r = event_make_inode_data(e, inotify_data, st.st_dev, st.st_ino, &inode_data); if (r < 0) { - event_free_inotify_data(e, inotify_data); + event_gc_inotify_data(e, inotify_data); return r; } /* Keep the O_PATH fd around until the first iteration of the loop, so that we can still change the priority of * the event source, until then, for which we need the original inode. */ if (inode_data->fd < 0) { - inode_data->fd = TAKE_FD(fd); + if (donated_fd >= 0) + inode_data->fd = TAKE_FD(donated_fd); + else { + inode_data->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (inode_data->fd < 0) { + r = -errno; + event_gc_inode_data(e, inode_data); + return r; + } + } + LIST_PREPEND(to_close, e->inode_data_to_close, inode_data); } @@ -2046,8 +2073,6 @@ _public_ int sd_event_add_inotify( if (r < 0) return r; - (void) sd_event_source_set_description(s, path); - if (ret) *ret = s; TAKE_PTR(s); @@ -2055,6 +2080,48 @@ _public_ int sd_event_add_inotify( return 0; } +_public_ int sd_event_add_inotify_fd( + sd_event *e, + sd_event_source **ret, + int fd, + uint32_t mask, + sd_event_inotify_handler_t callback, + void *userdata) { + + return event_add_inotify_fd_internal(e, ret, fd, /* donate= */ false, mask, callback, userdata); +} + +_public_ int sd_event_add_inotify( + sd_event *e, + sd_event_source **ret, + const char *path, + uint32_t mask, + sd_event_inotify_handler_t callback, + void *userdata) { + + sd_event_source *s = NULL; /* avoid false maybe-uninitialized warning */ + int fd, r; + + assert_return(path, -EINVAL); + + fd = open(path, O_PATH|O_CLOEXEC| + (mask & IN_ONLYDIR ? O_DIRECTORY : 0)| + (mask & IN_DONT_FOLLOW ? O_NOFOLLOW : 0)); + if (fd < 0) + return -errno; + + r = event_add_inotify_fd_internal(e, &s, fd, /* donate= */ true, mask, callback, userdata); + if (r < 0) + return r; + + (void) sd_event_source_set_description(s, path); + + if (ret) + *ret = s; + + return r; +} + static sd_event_source* event_source_free(sd_event_source *s) { if (!s) return NULL; @@ -2845,7 +2912,7 @@ fail: return r; } -static int event_source_leave_ratelimit(sd_event_source *s) { +static int event_source_leave_ratelimit(sd_event_source *s, bool run_callback) { int r; assert(s); @@ -2877,6 +2944,30 @@ static int event_source_leave_ratelimit(sd_event_source *s) { ratelimit_reset(&s->rate_limit); log_debug("Event source %p (%s) left rate limit state.", s, strna(s->description)); + + if (run_callback && s->ratelimit_expire_callback) { + s->dispatching = true; + r = s->ratelimit_expire_callback(s, s->userdata); + s->dispatching = false; + + if (r < 0) { + log_debug_errno(r, "Ratelimit expiry callback of event source %s (type %s) returned error, %s: %m", + strna(s->description), + event_source_type_to_string(s->type), + s->exit_on_failure ? "exiting" : "disabling"); + + if (s->exit_on_failure) + (void) sd_event_exit(s->event, r); + } + + if (s->n_ref == 0) + source_free(s); + else if (r < 0) + assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); + + return 1; + } + return 0; fail: @@ -3055,7 +3146,7 @@ static int flush_timer(sd_event *e, int fd, uint32_t events, usec_t *next) { ss = read(fd, &x, sizeof(x)); if (ss < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) + if (ERRNO_IS_TRANSIENT(errno)) return 0; return -errno; @@ -3076,6 +3167,7 @@ static int process_timer( struct clock_data *d) { sd_event_source *s; + bool callback_invoked = false; int r; assert(e); @@ -3093,9 +3185,11 @@ static int process_timer( * again. */ assert(s->ratelimited); - r = event_source_leave_ratelimit(s); + r = event_source_leave_ratelimit(s, /* run_callback */ true); if (r < 0) return r; + else if (r == 1) + callback_invoked = true; continue; } @@ -3110,7 +3204,7 @@ static int process_timer( event_source_time_prioq_reshuffle(s); } - return 0; + return callback_invoked; } static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priority) { @@ -3258,7 +3352,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events, i n = read(d->fd, &si, sizeof(si)); if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) + if (ERRNO_IS_TRANSIENT(errno)) return 0; return -errno; @@ -3312,7 +3406,7 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t n = read(d->fd, &d->buffer, sizeof(d->buffer)); if (n < 0) { - if (IN_SET(errno, EAGAIN, EINTR)) + if (ERRNO_IS_TRANSIENT(errno)) return 0; return -errno; @@ -3560,13 +3654,23 @@ static int source_dispatch(sd_event_source *s) { sz = offsetof(struct inotify_event, name) + d->buffer.ev.len; assert(d->buffer_filled >= sz); + /* If the inotify callback destroys the event source then this likely means we don't need to + * watch the inode anymore, and thus also won't need the inotify object anymore. But if we'd + * free it immediately, then we couldn't drop the event from the inotify event queue without + * memory corruption anymore, as below. Hence, let's not free it immediately, but mark it + * "busy" with a counter (which will ensure it's not GC'ed away prematurely). Let's then + * explicitly GC it after we are done dropping the inotify event from the buffer. */ + d->n_busy++; r = s->inotify.callback(s, &d->buffer.ev, s->userdata); + d->n_busy--; - /* When no event is pending anymore on this inotify object, then let's drop the event from the - * buffer. */ + /* When no event is pending anymore on this inotify object, then let's drop the event from + * the inotify event queue buffer. */ if (d->n_pending == 0) event_inotify_data_drop(e, d, sz); + /* Now we don't want to access 'd' anymore, it's OK to GC now. */ + event_gc_inotify_data(e, d); break; } @@ -3591,7 +3695,7 @@ static int source_dispatch(sd_event_source *s) { if (s->n_ref == 0) source_free(s); else if (r < 0) - sd_event_source_set_enabled(s, SD_EVENT_OFF); + assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); return 1; } @@ -3632,7 +3736,7 @@ static int event_prepare(sd_event *e) { if (s->n_ref == 0) source_free(s); else if (r < 0) - sd_event_source_set_enabled(s, SD_EVENT_OFF); + assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0); } return 0; @@ -3693,10 +3797,7 @@ static int arm_watchdog(sd_event *e) { if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) its.it_value.tv_nsec = 1; - if (timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) - return -errno; - - return 0; + return RET_NERRNO(timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL)); } static int process_watchdog(sd_event *e) { @@ -3806,7 +3907,7 @@ static int epoll_wait_usec( int maxevents, usec_t timeout) { - int r, msec; + int msec; #if 0 static bool epoll_pwait2_absent = false; @@ -3846,14 +3947,7 @@ static int epoll_wait_usec( msec = (int) k; } - r = epoll_wait(fd, - events, - maxevents, - msec); - if (r < 0) - return -errno; - - return r; + return RET_NERRNO(epoll_wait(fd, events, maxevents, msec)); } static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t *ret_min_priority) { @@ -4024,15 +4118,15 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { if (r < 0) goto finish; - r = process_timer(e, e->timestamp.realtime, &e->realtime); + r = process_inotify(e); if (r < 0) goto finish; - r = process_timer(e, e->timestamp.boottime, &e->boottime); + r = process_timer(e, e->timestamp.realtime, &e->realtime); if (r < 0) goto finish; - r = process_timer(e, e->timestamp.monotonic, &e->monotonic); + r = process_timer(e, e->timestamp.boottime, &e->boottime); if (r < 0) goto finish; @@ -4044,9 +4138,20 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { if (r < 0) goto finish; - r = process_inotify(e); + r = process_timer(e, e->timestamp.monotonic, &e->monotonic); if (r < 0) goto finish; + else if (r == 1) { + /* Ratelimit expiry callback was called. Let's postpone processing pending sources and + * put loop in the initial state in order to evaluate (in the next iteration) also sources + * there were potentially re-enabled by the callback. + * + * Wondering why we treat only this invocation of process_timer() differently? Once event + * source is ratelimited we essentially transform it into CLOCK_MONOTONIC timer hence + * ratelimit expiry callback is never called for any other timer type. */ + r = 0; + goto finish; + } if (event_next_pending(e)) { e->state = SD_EVENT_PENDING; @@ -4117,7 +4222,7 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { this_run = now(CLOCK_MONOTONIC); - l = u64log2(this_run - e->last_run_usec); + l = log2u64(this_run - e->last_run_usec); assert(l < ELEMENTSOF(e->delays)); e->delays[l]++; @@ -4416,7 +4521,7 @@ _public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval /* When ratelimiting is configured we'll always reset the rate limit state first and start fresh, * non-ratelimited. */ - r = event_source_leave_ratelimit(s); + r = event_source_leave_ratelimit(s, /* run_callback */ false); if (r < 0) return r; @@ -4424,6 +4529,13 @@ _public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval return 0; } +_public_ int sd_event_source_set_ratelimit_expire_callback(sd_event_source *s, sd_event_handler_t callback) { + assert_return(s, -EINVAL); + + s->ratelimit_expire_callback = callback; + return 0; +} + _public_ int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval, unsigned *ret_burst) { assert_return(s, -EINVAL); diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c index d80145a8..9ec2abc8 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/id128-util.c @@ -224,7 +224,7 @@ int id128_get_product(sd_id128_t *ret) { r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &uuid); if (r == -ENOENT) - r = id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID, &uuid); + r = id128_read("/proc/device-tree/vm,uuid", ID128_UUID, &uuid); if (r < 0) return r; diff --git a/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c b/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c index 0860f493..c3ed3bbb 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-id128/sd-id128.c @@ -6,21 +6,14 @@ #include <fcntl.h> #include <unistd.h> -#if HAVE_OPENSSL -#include <openssl/hmac.h> -#include <openssl/sha.h> -#endif - #include "sd-id128.h" #include "alloc-util.h" #include "fd-util.h" #include "hexdecoct.h" +#include "hmac.h" #include "id128-util.h" #include "io-util.h" -#if !HAVE_OPENSSL -#include "khash.h" -#endif #include "macro.h" #include "missing_syscall.h" #include "random-util.h" @@ -283,43 +276,15 @@ _public_ int sd_id128_randomize(sd_id128_t *ret) { } static int get_app_specific(sd_id128_t base, sd_id128_t app_id, sd_id128_t *ret) { + uint8_t hmac[SHA256_DIGEST_SIZE]; sd_id128_t result; assert(ret); -#if HAVE_OPENSSL - /* We prefer doing this in-process, since we this means we are not dependent on kernel configuration, - * and this also works in locked down container environments. But some distros don't like OpenSSL's - * license and its (in-) compatibility with GPL2, hence also support khash */ - uint8_t md[256/8]; - if (!HMAC(EVP_sha256(), - &base, sizeof(base), - (const unsigned char*) &app_id, sizeof(app_id), - md, NULL)) - return -ENOTRECOVERABLE; + hmac_sha256(&base, sizeof(base), &app_id, sizeof(app_id), hmac); /* Take only the first half. */ - memcpy(&result, md, MIN(sizeof(md), sizeof(result))); -#else - _cleanup_(khash_unrefp) khash *h = NULL; - const void *p; - int r; - - r = khash_new_with_key(&h, "hmac(sha256)", &base, sizeof(base)); - if (r < 0) - return r; - - r = khash_put(h, &app_id, sizeof(app_id)); - if (r < 0) - return r; - - r = khash_digest_data(h, &p); - if (r < 0) - return r; - - /* We chop off the trailing 16 bytes */ - memcpy(&result, p, MIN(khash_get_size(h), sizeof(result))); -#endif + memcpy(&result, hmac, MIN(sizeof(hmac), sizeof(result))); *ret = id128_make_v4_uuid(result); return 0; diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp-client.h b/src/libnm-systemd-core/src/systemd/sd-dhcp-client.h index 23979b12..4af4b45f 100644 --- a/src/libnm-systemd-core/src/systemd/sd-dhcp-client.h +++ b/src/libnm-systemd-core/src/systemd/sd-dhcp-client.h @@ -45,65 +45,66 @@ enum { }; enum { - SD_DHCP_OPTION_PAD = 0, - SD_DHCP_OPTION_SUBNET_MASK = 1, - SD_DHCP_OPTION_TIME_OFFSET = 2, - SD_DHCP_OPTION_ROUTER = 3, - SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6, - SD_DHCP_OPTION_LPR_SERVER = 9, - SD_DHCP_OPTION_HOST_NAME = 12, - SD_DHCP_OPTION_BOOT_FILE_SIZE = 13, - SD_DHCP_OPTION_DOMAIN_NAME = 15, - SD_DHCP_OPTION_ROOT_PATH = 17, - SD_DHCP_OPTION_ENABLE_IP_FORWARDING = 19, - SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20, - SD_DHCP_OPTION_POLICY_FILTER = 21, - SD_DHCP_OPTION_INTERFACE_MDR = 22, - SD_DHCP_OPTION_INTERFACE_TTL = 23, - SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24, - SD_DHCP_OPTION_INTERFACE_MTU = 26, - SD_DHCP_OPTION_BROADCAST = 28, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_ROUTER_DISCOVER = 31, - SD_DHCP_OPTION_STATIC_ROUTE = 33, - SD_DHCP_OPTION_NTP_SERVER = 42, - SD_DHCP_OPTION_VENDOR_SPECIFIC = 43, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_NETBIOS_NAMESERVER = 44, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_NETBIOS_NODETYPE = 46, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_NETBIOS_SCOPE = 47, - SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50, - SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51, - SD_DHCP_OPTION_OVERLOAD = 52, - SD_DHCP_OPTION_MESSAGE_TYPE = 53, - SD_DHCP_OPTION_SERVER_IDENTIFIER = 54, - SD_DHCP_OPTION_PARAMETER_REQUEST_LIST = 55, - SD_DHCP_OPTION_ERROR_MESSAGE = 56, - SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57, - SD_DHCP_OPTION_RENEWAL_T1_TIME = 58, - SD_DHCP_OPTION_REBINDING_T2_TIME = 59, - SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60, - SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61, - SD_DHCP_OPTION_SMTP_SERVER = 69, - SD_DHCP_OPTION_POP3_SERVER = 70, - SD_DHCP_OPTION_USER_CLASS = 77, - SD_DHCP_OPTION_FQDN = 81, - SD_DHCP_OPTION_RELAY_AGENT_INFORMATION = 82, - SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100, - SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101, - SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119, - SD_DHCP_OPTION_SIP_SERVER = 120, - SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, - SD_DHCP_OPTION_MUD_URL = 161, - SD_DHCP_OPTION_PRIVATE_BASE = 224, - /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_PAD = 0, + SD_DHCP_OPTION_SUBNET_MASK = 1, + SD_DHCP_OPTION_TIME_OFFSET = 2, + SD_DHCP_OPTION_ROUTER = 3, + SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6, + SD_DHCP_OPTION_LPR_SERVER = 9, + SD_DHCP_OPTION_HOST_NAME = 12, + SD_DHCP_OPTION_BOOT_FILE_SIZE = 13, + SD_DHCP_OPTION_DOMAIN_NAME = 15, + SD_DHCP_OPTION_ROOT_PATH = 17, + SD_DHCP_OPTION_ENABLE_IP_FORWARDING = 19, + SD_DHCP_OPTION_ENABLE_IP_FORWARDING_NL = 20, + SD_DHCP_OPTION_POLICY_FILTER = 21, + SD_DHCP_OPTION_INTERFACE_MDR = 22, + SD_DHCP_OPTION_INTERFACE_TTL = 23, + SD_DHCP_OPTION_INTERFACE_MTU_AGING_TIMEOUT = 24, + SD_DHCP_OPTION_INTERFACE_MTU = 26, + SD_DHCP_OPTION_BROADCAST = 28, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_ROUTER_DISCOVER = 31, + SD_DHCP_OPTION_STATIC_ROUTE = 33, + SD_DHCP_OPTION_NTP_SERVER = 42, + SD_DHCP_OPTION_VENDOR_SPECIFIC = 43, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_NETBIOS_NAMESERVER = 44, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_NETBIOS_NODETYPE = 46, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_NETBIOS_SCOPE = 47, + SD_DHCP_OPTION_REQUESTED_IP_ADDRESS = 50, + SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME = 51, + SD_DHCP_OPTION_OVERLOAD = 52, + SD_DHCP_OPTION_MESSAGE_TYPE = 53, + SD_DHCP_OPTION_SERVER_IDENTIFIER = 54, + SD_DHCP_OPTION_PARAMETER_REQUEST_LIST = 55, + SD_DHCP_OPTION_ERROR_MESSAGE = 56, + SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE = 57, + SD_DHCP_OPTION_RENEWAL_T1_TIME = 58, + SD_DHCP_OPTION_REBINDING_T2_TIME = 59, + SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60, + SD_DHCP_OPTION_CLIENT_IDENTIFIER = 61, + SD_DHCP_OPTION_SMTP_SERVER = 69, + SD_DHCP_OPTION_POP3_SERVER = 70, + SD_DHCP_OPTION_USER_CLASS = 77, + SD_DHCP_OPTION_FQDN = 81, + SD_DHCP_OPTION_RELAY_AGENT_INFORMATION = 82, + SD_DHCP_OPTION_NEW_POSIX_TIMEZONE = 100, + SD_DHCP_OPTION_NEW_TZDB_TIMEZONE = 101, + SD_DHCP_OPTION_DOMAIN_SEARCH_LIST = 119, + SD_DHCP_OPTION_SIP_SERVER = 120, + SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, + SD_DHCP_OPTION_MUD_URL = 161, + SD_DHCP_OPTION_6RD = 212, + SD_DHCP_OPTION_PRIVATE_BASE = 224, + /* Windows 10 option to send when Anonymize=true */ SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE = 249, - /* Windows 10 option to send when Anonymize=true */ - SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY = 252, - SD_DHCP_OPTION_PRIVATE_LAST = 254, - SD_DHCP_OPTION_END = 255, + /* Windows 10 option to send when Anonymize=true */ + SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY = 252, + SD_DHCP_OPTION_PRIVATE_LAST = 254, + SD_DHCP_OPTION_END = 255, }; /* Suboptions for SD_DHCP_OPTION_RELAY_AGENT_INFORMATION option */ diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h b/src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h index 5abf9a40..478bbfd7 100644 --- a/src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h +++ b/src/libnm-systemd-core/src/systemd/sd-dhcp-lease.h @@ -71,6 +71,13 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes); int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len); int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len); int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone); +int sd_dhcp_lease_get_6rd( + sd_dhcp_lease *lease, + uint8_t *ret_ipv4masklen, + uint8_t *ret_prefixlen, + struct in6_addr *ret_prefix, + const struct in_addr **ret_br_addresses, + size_t *ret_n_br_addresses); int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination); int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length); diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h b/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h index f3889782..0e23c84e 100644 --- a/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h +++ b/src/libnm-systemd-core/src/systemd/sd-dhcp6-client.h @@ -39,44 +39,151 @@ enum { SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST = 13, }; +/* https://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xhtml#dhcpv6-parameters-2 */ enum { - SD_DHCP6_OPTION_CLIENTID = 1, - SD_DHCP6_OPTION_SERVERID = 2, - SD_DHCP6_OPTION_IA_NA = 3, - SD_DHCP6_OPTION_IA_TA = 4, - SD_DHCP6_OPTION_IAADDR = 5, - SD_DHCP6_OPTION_ORO = 6, - SD_DHCP6_OPTION_PREFERENCE = 7, - SD_DHCP6_OPTION_ELAPSED_TIME = 8, - SD_DHCP6_OPTION_RELAY_MSG = 9, + SD_DHCP6_OPTION_CLIENTID = 1, /* RFC 8415 */ + SD_DHCP6_OPTION_SERVERID = 2, /* RFC 8415 */ + SD_DHCP6_OPTION_IA_NA = 3, /* RFC 8415 */ + SD_DHCP6_OPTION_IA_TA = 4, /* RFC 8415 */ + SD_DHCP6_OPTION_IAADDR = 5, /* RFC 8415 */ + SD_DHCP6_OPTION_ORO = 6, /* RFC 8415 */ + SD_DHCP6_OPTION_PREFERENCE = 7, /* RFC 8415 */ + SD_DHCP6_OPTION_ELAPSED_TIME = 8, /* RFC 8415 */ + SD_DHCP6_OPTION_RELAY_MSG = 9, /* RFC 8415 */ /* option code 10 is unassigned */ - SD_DHCP6_OPTION_AUTH = 11, - SD_DHCP6_OPTION_UNICAST = 12, - SD_DHCP6_OPTION_STATUS_CODE = 13, - SD_DHCP6_OPTION_RAPID_COMMIT = 14, - SD_DHCP6_OPTION_USER_CLASS = 15, - SD_DHCP6_OPTION_VENDOR_CLASS = 16, - SD_DHCP6_OPTION_VENDOR_OPTS = 17, - SD_DHCP6_OPTION_INTERFACE_ID = 18, - SD_DHCP6_OPTION_RECONF_MSG = 19, - SD_DHCP6_OPTION_RECONF_ACCEPT = 20, - + SD_DHCP6_OPTION_AUTH = 11, /* RFC 8415 */ + SD_DHCP6_OPTION_UNICAST = 12, /* RFC 8415 */ + SD_DHCP6_OPTION_STATUS_CODE = 13, /* RFC 8415 */ + SD_DHCP6_OPTION_RAPID_COMMIT = 14, /* RFC 8415 */ + SD_DHCP6_OPTION_USER_CLASS = 15, /* RFC 8415 */ + SD_DHCP6_OPTION_VENDOR_CLASS = 16, /* RFC 8415 */ + SD_DHCP6_OPTION_VENDOR_OPTS = 17, /* RFC 8415 */ + SD_DHCP6_OPTION_INTERFACE_ID = 18, /* RFC 8415 */ + SD_DHCP6_OPTION_RECONF_MSG = 19, /* RFC 8415 */ + SD_DHCP6_OPTION_RECONF_ACCEPT = 20, /* RFC 8415 */ + SD_DHCP6_OPTION_SIP_SERVER_DOMAIN_NAME = 21, /* RFC 3319 */ + SD_DHCP6_OPTION_SIP_SERVER_ADDRESS = 22, /* RFC 3319 */ SD_DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */ SD_DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */ - SD_DHCP6_OPTION_IA_PD = 25, /* RFC 3633, prefix delegation */ - SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, prefix delegation */ - + SD_DHCP6_OPTION_IA_PD = 25, /* RFC 3633, RFC 8415 */ + SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, RFC 8415 */ + SD_DHCP6_OPTION_NIS_SERVERS = 27, /* RFC 3898 */ + SD_DHCP6_OPTION_NISP_SERVERS = 28, /* RFC 3898 */ + SD_DHCP6_OPTION_NIS_DOMAIN_NAME = 29, /* RFC 3898 */ + SD_DHCP6_OPTION_NISP_DOMAIN_NAME = 30, /* RFC 3898 */ SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */ - SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 8415, sec. 21.23 */ - + SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 4242, 8415, sec. 21.23 */ + SD_DHCP6_OPTION_BCMCS_SERVER_D = 33, /* RFC 4280 */ + SD_DHCP6_OPTION_BCMCS_SERVER_A = 34, /* RFC 4280 */ /* option code 35 is unassigned */ - - SD_DHCP6_OPTION_FQDN = 39, /* RFC 4704 */ - + SD_DHCP6_OPTION_GEOCONF_CIVIC = 36, /* RFC 4776 */ + SD_DHCP6_OPTION_REMOTE_ID = 37, /* RFC 4649 */ + SD_DHCP6_OPTION_SUBSCRIBER_ID = 38, /* RFC 4580 */ + SD_DHCP6_OPTION_CLIENT_FQDN = 39, /* RFC 4704 */ + SD_DHCP6_OPTION_PANA_AGENT = 40, /* RFC 5192 */ + SD_DHCP6_OPTION_NEW_POSIX_TIMEZONE = 41, /* RFC 4833 */ + SD_DHCP6_OPTION_NEW_TZDB_TIMEZONE = 42, /* RFC 4833 */ + SD_DHCP6_OPTION_ERO = 43, /* RFC 4994 */ + SD_DHCP6_OPTION_LQ_QUERY = 44, /* RFC 5007 */ + SD_DHCP6_OPTION_CLIENT_DATA = 45, /* RFC 5007 */ + SD_DHCP6_OPTION_CLT_TIME = 46, /* RFC 5007 */ + SD_DHCP6_OPTION_LQ_RELAY_DATA = 47, /* RFC 5007 */ + SD_DHCP6_OPTION_LQ_CLIENT_LINK = 48, /* RFC 5007 */ + SD_DHCP6_OPTION_MIP6_HNIDF = 49, /* RFC 6610 */ + SD_DHCP6_OPTION_MIP6_VDINF = 50, /* RFC 6610 */ + SD_DHCP6_OPTION_V6_LOST = 51, /* RFC 5223 */ + SD_DHCP6_OPTION_CAPWAP_AC_V6 = 52, /* RFC 5417 */ + SD_DHCP6_OPTION_RELAY_ID = 53, /* RFC 5460 */ + SD_DHCP6_OPTION_IPV6_ADDRESS_MOS = 54, /* RFC 5678 */ + SD_DHCP6_OPTION_IPV6_FQDN_MOS = 55, /* RFC 5678 */ SD_DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */ - SD_DHCP6_OPTION_MUD_URL = 112, /* RFC 8250 */ - - /* option codes 89-142 are unassigned */ + SD_DHCP6_OPTION_V6_ACCESS_DOMAIN = 57, /* RFC 5986 */ + SD_DHCP6_OPTION_SIP_UA_CS_LIST = 58, /* RFC 6011 */ + SD_DHCP6_OPTION_BOOTFILE_URL = 59, /* RFC 5970 */ + SD_DHCP6_OPTION_BOOTFILE_PARAM = 60, /* RFC 5970 */ + SD_DHCP6_OPTION_CLIENT_ARCH_TYPE = 61, /* RFC 5970 */ + SD_DHCP6_OPTION_NII = 62, /* RFC 5970 */ + SD_DHCP6_OPTION_GEOLOCATION = 63, /* RFC 6225 */ + SD_DHCP6_OPTION_AFTR_NAME = 64, /* RFC 6334 */ + SD_DHCP6_OPTION_ERP_LOCAL_DOMAIN_NAME = 65, /* RFC 6440 */ + SD_DHCP6_OPTION_RSOO = 66, /* RFC 6422 */ + SD_DHCP6_OPTION_PD_EXCLUDE = 67, /* RFC 6603 */ + SD_DHCP6_OPTION_VSS = 68, /* RFC 6607 */ + SD_DHCP6_OPTION_MIP6_IDINF = 69, /* RFC 6610 */ + SD_DHCP6_OPTION_MIP6_UDINF = 70, /* RFC 6610 */ + SD_DHCP6_OPTION_MIP6_HNP = 71, /* RFC 6610 */ + SD_DHCP6_OPTION_MIP6_HAA = 72, /* RFC 6610 */ + SD_DHCP6_OPTION_MIP6_HAF = 73, /* RFC 6610 */ + SD_DHCP6_OPTION_RDNSS_SELECTION = 74, /* RFC 6731 */ + SD_DHCP6_OPTION_KRB_PRINCIPAL_NAME = 75, /* RFC 6784 */ + SD_DHCP6_OPTION_KRB_REALM_NAME = 76, /* RFC 6784 */ + SD_DHCP6_OPTION_KRB_DEFAULT_REALM_NAME = 77, /* RFC 6784 */ + SD_DHCP6_OPTION_KRB_KDC = 78, /* RFC 6784 */ + SD_DHCP6_OPTION_CLIENT_LINKLAYER_ADDR = 79, /* RFC 6939 */ + SD_DHCP6_OPTION_LINK_ADDRESS = 80, /* RFC 6977 */ + SD_DHCP6_OPTION_RADIUS = 81, /* RFC 7037 */ + SD_DHCP6_OPTION_SOL_MAX_RT = 82, /* RFC 7083, RFC 8415 */ + SD_DHCP6_OPTION_INF_MAX_RT = 83, /* RFC 7083, RFC 8415 */ + SD_DHCP6_OPTION_ADDRSEL = 84, /* RFC 7078 */ + SD_DHCP6_OPTION_ADDRSEL_TABLE = 85, /* RFC 7078 */ + SD_DHCP6_OPTION_V6_PCP_SERVER = 86, /* RFC 7291 */ + SD_DHCP6_OPTION_DHCPV4_MSG = 87, /* RFC 7341 */ + SD_DHCP6_OPTION_DHCP4_O_DHCP6_SERVER = 88, /* RFC 7341 */ + SD_DHCP6_OPTION_S46_RULE = 89, /* RFC 7598 */ + SD_DHCP6_OPTION_S46_BR = 90, /* RFC 7598, RFC 8539 */ + SD_DHCP6_OPTION_S46_DMR = 91, /* RFC 7598 */ + SD_DHCP6_OPTION_S46_V4V6BIND = 92, /* RFC 7598 */ + SD_DHCP6_OPTION_S46_PORTPARAMS = 93, /* RFC 7598 */ + SD_DHCP6_OPTION_S46_CONT_MAPE = 94, /* RFC 7598 */ + SD_DHCP6_OPTION_S46_CONT_MAPT = 95, /* RFC 7598 */ + SD_DHCP6_OPTION_S46_CONT_LW = 96, /* RFC 7598 */ + SD_DHCP6_OPTION_4RD = 97, /* RFC 7600 */ + SD_DHCP6_OPTION_4RD_MAP_RULE = 98, /* RFC 7600 */ + SD_DHCP6_OPTION_4RD_NON_MAP_RULE = 99, /* RFC 7600 */ + SD_DHCP6_OPTION_LQ_BASE_TIME = 100, /* RFC 7653 */ + SD_DHCP6_OPTION_LQ_START_TIME = 101, /* RFC 7653 */ + SD_DHCP6_OPTION_LQ_END_TIME = 102, /* RFC 7653 */ + SD_DHCP6_OPTION_CAPTIVE_PORTAL = 103, /* RFC 8910 */ + SD_DHCP6_OPTION_MPL_PARAMETERS = 104, /* RFC 7774 */ + SD_DHCP6_OPTION_ANI_ATT = 105, /* RFC 7839 */ + SD_DHCP6_OPTION_ANI_NETWORK_NAME = 106, /* RFC 7839 */ + SD_DHCP6_OPTION_ANI_AP_NAME = 107, /* RFC 7839 */ + SD_DHCP6_OPTION_ANI_AP_BSSID = 108, /* RFC 7839 */ + SD_DHCP6_OPTION_ANI_OPERATOR_ID = 109, /* RFC 7839 */ + SD_DHCP6_OPTION_ANI_OPERATOR_REALM = 110, /* RFC 7839 */ + SD_DHCP6_OPTION_S46_PRIORITY = 111, /* RFC 8026 */ + SD_DHCP6_OPTION_MUD_URL_V6 = 112, /* RFC 8520 */ + SD_DHCP6_OPTION_V6_PREFIX64 = 113, /* RFC 8115 */ + SD_DHCP6_OPTION_F_BINDING_STATUS = 114, /* RFC 8156 */ + SD_DHCP6_OPTION_F_CONNECT_FLAGS = 115, /* RFC 8156 */ + SD_DHCP6_OPTION_F_DNS_REMOVAL_INFO = 116, /* RFC 8156 */ + SD_DHCP6_OPTION_F_DNS_HOST_NAME = 117, /* RFC 8156 */ + SD_DHCP6_OPTION_F_DNS_ZONE_NAME = 118, /* RFC 8156 */ + SD_DHCP6_OPTION_F_DNS_FLAGS = 119, /* RFC 8156 */ + SD_DHCP6_OPTION_F_EXPIRATION_TIME = 120, /* RFC 8156 */ + SD_DHCP6_OPTION_F_MAX_UNACKED_BNDUPD = 121, /* RFC 8156 */ + SD_DHCP6_OPTION_F_MCLT = 122, /* RFC 8156 */ + SD_DHCP6_OPTION_F_PARTNER_LIFETIME = 123, /* RFC 8156 */ + SD_DHCP6_OPTION_F_PARTNER_LIFETIME_SENT = 124, /* RFC 8156 */ + SD_DHCP6_OPTION_F_PARTNER_DOWN_TIME = 125, /* RFC 8156 */ + SD_DHCP6_OPTION_F_PARTNER_RAW_CLT_TIME = 126, /* RFC 8156 */ + SD_DHCP6_OPTION_F_PROTOCOL_VERSION = 127, /* RFC 8156 */ + SD_DHCP6_OPTION_F_KEEPALIVE_TIME = 128, /* RFC 8156 */ + SD_DHCP6_OPTION_F_RECONFIGURE_DATA = 129, /* RFC 8156 */ + SD_DHCP6_OPTION_F_RELATIONSHIP_NAME = 130, /* RFC 8156 */ + SD_DHCP6_OPTION_F_SERVER_FLAGS = 131, /* RFC 8156 */ + SD_DHCP6_OPTION_F_SERVER_STATE = 132, /* RFC 8156 */ + SD_DHCP6_OPTION_F_START_TIME_OF_STATE = 133, /* RFC 8156 */ + SD_DHCP6_OPTION_F_STATE_EXPIRATION_TIME = 134, /* RFC 8156 */ + SD_DHCP6_OPTION_RELAY_PORT = 135, /* RFC 8357 */ + SD_DHCP6_OPTION_V6_SZTP_REDIRECT = 136, /* RFC 8572 */ + SD_DHCP6_OPTION_S46_BIND_IPV6_PREFIX = 137, /* RFC 8539 */ + SD_DHCP6_OPTION_IA_LL = 138, /* RFC 8947 */ + SD_DHCP6_OPTION_LLADDR = 139, /* RFC 8947 */ + SD_DHCP6_OPTION_SLAP_QUAD = 140, /* RFC 8948 */ + SD_DHCP6_OPTION_V6_DOTS_RI = 141, /* RFC 8973 */ + SD_DHCP6_OPTION_V6_DOTS_ADDRESS = 142, /* RFC 8973 */ + SD_DHCP6_OPTION_IPV6_ADDRESS_ANDSF = 143, /* RFC 6153 */ /* option codes 144-65535 are unassigned */ }; diff --git a/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h b/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h index a10901e5..472276de 100644 --- a/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h +++ b/src/libnm-systemd-core/src/systemd/sd-dhcp6-lease.h @@ -21,6 +21,7 @@ #include <inttypes.h> #include <netinet/in.h> +#include <sys/types.h> #include "_sd-common.h" @@ -28,6 +29,9 @@ _SD_BEGIN_DECLARATIONS; typedef struct sd_dhcp6_lease sd_dhcp6_lease; +int sd_dhcp6_lease_get_timestamp(sd_dhcp6_lease *lease, clockid_t clock, uint64_t *ret); +int sd_dhcp6_lease_get_server_address(sd_dhcp6_lease *lease, struct in6_addr *ret); + void sd_dhcp6_lease_reset_address_iter(sd_dhcp6_lease *lease); int sd_dhcp6_lease_get_address(sd_dhcp6_lease *lease, struct in6_addr *addr, diff --git a/src/libnm-systemd-core/src/systemd/sd-event.h b/src/libnm-systemd-core/src/systemd/sd-event.h index 2ae2a0da..63984eef 100644 --- a/src/libnm-systemd-core/src/systemd/sd-event.h +++ b/src/libnm-systemd-core/src/systemd/sd-event.h @@ -93,6 +93,7 @@ int sd_event_add_signal(sd_event *e, sd_event_source **s, int sig, sd_event_sign int sd_event_add_child(sd_event *e, sd_event_source **s, pid_t pid, int options, sd_event_child_handler_t callback, void *userdata); int sd_event_add_child_pidfd(sd_event *e, sd_event_source **s, int pidfd, int options, sd_event_child_handler_t callback, void *userdata); int sd_event_add_inotify(sd_event *e, sd_event_source **s, const char *path, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata); +int sd_event_add_inotify_fd(sd_event *e, sd_event_source **s, int fd, uint32_t mask, sd_event_inotify_handler_t callback, void *userdata); int sd_event_add_defer(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); int sd_event_add_post(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); int sd_event_add_exit(sd_event *e, sd_event_source **s, sd_event_handler_t callback, void *userdata); @@ -165,6 +166,7 @@ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b); int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval_usec, unsigned burst); int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval_usec, unsigned *ret_burst); int sd_event_source_is_ratelimited(sd_event_source *s); +int sd_event_source_set_ratelimit_expire_callback(sd_event_source *s, sd_event_handler_t callback); /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); diff --git a/src/libnm-systemd-core/src/systemd/sd-ipv4acd.h b/src/libnm-systemd-core/src/systemd/sd-ipv4acd.h deleted file mode 100644 index 90d3f0a0..00000000 --- a/src/libnm-systemd-core/src/systemd/sd-ipv4acd.h +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdipv4acdfoo -#define foosdipv4acdfoo - -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/ethernet.h> -#include <netinet/in.h> -#include <stdbool.h> - -#include "sd-event.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -enum { - SD_IPV4ACD_EVENT_STOP = 0, - SD_IPV4ACD_EVENT_BIND = 1, - SD_IPV4ACD_EVENT_CONFLICT = 2, -}; - -typedef struct sd_ipv4acd sd_ipv4acd; -typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *acd, int event, void *userdata); -typedef int (*sd_ipv4acd_check_mac_callback_t)(sd_ipv4acd *acd, const struct ether_addr *mac, void *userdata); - -int sd_ipv4acd_detach_event(sd_ipv4acd *acd); -int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority); -int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address); -int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata); -int sd_ipv4acd_set_check_mac_callback(sd_ipv4acd *acd, sd_ipv4acd_check_mac_callback_t cb, void *userdata); -int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr); -int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index); -int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd); -int sd_ipv4acd_set_ifname(sd_ipv4acd *acd, const char *interface_name); -int sd_ipv4acd_get_ifname(sd_ipv4acd *acd, const char **ret); -int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address); -int sd_ipv4acd_is_running(sd_ipv4acd *acd); -int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts); -int sd_ipv4acd_stop(sd_ipv4acd *acd); -sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd); -sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd); -int sd_ipv4acd_new(sd_ipv4acd **ret); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/libnm-systemd-core/src/systemd/sd-ipv4ll.h b/src/libnm-systemd-core/src/systemd/sd-ipv4ll.h deleted file mode 100644 index ed014b53..00000000 --- a/src/libnm-systemd-core/src/systemd/sd-ipv4ll.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#ifndef foosdipv4llfoo -#define foosdipv4llfoo - -/*** - Copyright © 2014 Axis Communications AB. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/ethernet.h> -#include <netinet/in.h> - -#include "sd-event.h" - -#include "_sd-common.h" - -_SD_BEGIN_DECLARATIONS; - -enum { - SD_IPV4LL_EVENT_STOP = 0, - SD_IPV4LL_EVENT_BIND = 1, - SD_IPV4LL_EVENT_CONFLICT = 2, -}; - -typedef struct sd_ipv4ll sd_ipv4ll; -typedef void (*sd_ipv4ll_callback_t)(sd_ipv4ll *ll, int event, void *userdata); -typedef int (*sd_ipv4ll_check_mac_callback_t)(sd_ipv4ll *ll, const struct ether_addr *mac, void *userdata); - -int sd_ipv4ll_detach_event(sd_ipv4ll *ll); -int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority); -int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address); -int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata); -int sd_ipv4ll_set_check_mac_callback(sd_ipv4ll *ll, sd_ipv4ll_check_mac_callback_t cb, void *userdata); -int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr); -int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index); -int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll); -int sd_ipv4ll_set_ifname(sd_ipv4ll *ll, const char *interface_name); -int sd_ipv4ll_get_ifname(sd_ipv4ll *ll, const char **ret); -int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address); -int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed); -int sd_ipv4ll_is_running(sd_ipv4ll *ll); -int sd_ipv4ll_restart(sd_ipv4ll *ll); -int sd_ipv4ll_start(sd_ipv4ll *ll); -int sd_ipv4ll_stop(sd_ipv4ll *ll); -sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll); -sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll); -int sd_ipv4ll_new(sd_ipv4ll **ret); - -_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4ll, sd_ipv4ll_unref); - -_SD_END_DECLARATIONS; - -#endif diff --git a/src/libnm-systemd-core/src/systemd/sd-ndisc.h b/src/libnm-systemd-core/src/systemd/sd-ndisc.h index f45b2ad6..ab9ff55d 100644 --- a/src/libnm-systemd-core/src/systemd/sd-ndisc.h +++ b/src/libnm-systemd-core/src/systemd/sd-ndisc.h @@ -82,9 +82,6 @@ int sd_ndisc_set_ifname(sd_ndisc *nd, const char *interface_name); int sd_ndisc_get_ifname(sd_ndisc *nd, const char **ret); int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr); -int sd_ndisc_get_mtu(sd_ndisc *nd, uint32_t *ret); -int sd_ndisc_get_hop_limit(sd_ndisc *nd, uint8_t *ret); - int sd_ndisc_router_from_raw(sd_ndisc_router **ret, const void *raw, size_t raw_size); sd_ndisc_router *sd_ndisc_router_ref(sd_ndisc_router *rt); sd_ndisc_router *sd_ndisc_router_unref(sd_ndisc_router *rt); |