diff options
| author | Michael Biebl <biebl@debian.org> | 2019-12-18 18:29:24 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2019-12-18 18:29:24 +0100 |
| commit | 28028b26b3371756811e95d894f709f4b1207c00 (patch) | |
| tree | 6fe7316fd743b51042db47601a8ef8814b3134ac /src/systemd | |
| parent | e22609983008e1a669196ad64ba3a59ae8c76e0d (diff) | |
New upstream version 1.22.0 upstream/1.22.0
Diffstat (limited to 'src/systemd')
32 files changed, 572 insertions, 331 deletions
diff --git a/src/systemd/meson.build b/src/systemd/meson.build index af1d0c8b..5c4fa3e2 100644 --- a/src/systemd/meson.build +++ b/src/systemd/meson.build @@ -1,45 +1,48 @@ +sources = files( + 'src/libsystemd-network/arp-util.c', + 'src/libsystemd-network/dhcp-identifier.c', + 'src/libsystemd-network/dhcp-network.c', + 'src/libsystemd-network/dhcp-option.c', + 'src/libsystemd-network/dhcp-packet.c', + 'src/libsystemd-network/dhcp6-network.c', + 'src/libsystemd-network/dhcp6-option.c', + 'src/libsystemd-network/lldp-neighbor.c', + 'src/libsystemd-network/lldp-network.c', + 'src/libsystemd-network/network-internal.c', + 'src/libsystemd-network/sd-dhcp-client.c', + '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.c', + 'src/libsystemd/sd-event/event-util.c', + 'src/libsystemd/sd-event/sd-event.c', + 'src/libsystemd/sd-id128/id128-util.c', + 'src/libsystemd/sd-id128/sd-id128.c', + 'nm-sd.c', + 'nm-sd-utils-core.c', + 'nm-sd-utils-dhcp.c', + 'sd-adapt-core/nm-sd-adapt-core.c', +) + +incs = include_directories( + 'sd-adapt-core', + 'src/libsystemd-network', + 'src/libsystemd/sd-event', + 'src/systemd', +) + +deps = [ + daemon_nm_default_dep, + libnm_systemd_shared_dep, +] + libnm_systemd_core = static_library( 'nm-systemd-core', - sources: files( - 'sd-adapt-core/nm-sd-adapt-core.c', - 'src/libsystemd-network/arp-util.c', - 'src/libsystemd-network/dhcp-identifier.c', - 'src/libsystemd-network/dhcp-network.c', - 'src/libsystemd-network/dhcp-option.c', - 'src/libsystemd-network/dhcp-packet.c', - 'src/libsystemd-network/dhcp6-network.c', - 'src/libsystemd-network/dhcp6-option.c', - 'src/libsystemd-network/lldp-neighbor.c', - 'src/libsystemd-network/lldp-network.c', - 'src/libsystemd-network/network-internal.c', - 'src/libsystemd-network/sd-dhcp-client.c', - '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.c', - 'src/libsystemd/sd-event/event-util.c', - 'src/libsystemd/sd-event/sd-event.c', - 'src/libsystemd/sd-id128/id128-util.c', - 'src/libsystemd/sd-id128/sd-id128.c', - 'nm-sd.c', - 'nm-sd-utils-core.c', - 'nm-sd-utils-dhcp.c', - ), - include_directories: [ - src_inc, - include_directories( - 'sd-adapt-core', - 'src/libsystemd-network', - 'src/libsystemd/sd-event', - 'src/systemd', - ) - ], - dependencies: [ - libnm_core_dep, - ], - c_args: [ - '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD', - ], + sources: sources, + include_directories: incs, + dependencies: deps, + c_args: '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD', + link_with: libc_siphash, ) diff --git a/src/systemd/nm-sd-utils-core.c b/src/systemd/nm-sd-utils-core.c index 42560789..4057c70a 100644 --- a/src/systemd/nm-sd-utils-core.c +++ b/src/systemd/nm-sd-utils-core.c @@ -1,18 +1,5 @@ -/* This library 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 of the License, or (at your option) any later version. - * - * This library 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 this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/systemd/nm-sd-utils-core.h b/src/systemd/nm-sd-utils-core.h index a7b092b3..3b0bc23b 100644 --- a/src/systemd/nm-sd-utils-core.h +++ b/src/systemd/nm-sd-utils-core.h @@ -1,18 +1,5 @@ -/* This library 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 of the License, or (at your option) any later version. - * - * This library 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 this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/systemd/nm-sd-utils-dhcp.c b/src/systemd/nm-sd-utils-dhcp.c index 49a924b6..4cfe054c 100644 --- a/src/systemd/nm-sd-utils-dhcp.c +++ b/src/systemd/nm-sd-utils-dhcp.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library 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 of the License, or (at your option) any later version. - * - * This library 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 this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #include "nm-default.h" diff --git a/src/systemd/nm-sd-utils-dhcp.h b/src/systemd/nm-sd-utils-dhcp.h index 496bf374..5228eb25 100644 --- a/src/systemd/nm-sd-utils-dhcp.h +++ b/src/systemd/nm-sd-utils-dhcp.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library 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 of the License, or (at your option) any later version. - * - * This library 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 this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__ diff --git a/src/systemd/nm-sd.c b/src/systemd/nm-sd.c index bcab328f..a277f430 100644 --- a/src/systemd/nm-sd.c +++ b/src/systemd/nm-sd.c @@ -1,17 +1,5 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ @@ -30,7 +18,6 @@ typedef struct SDEventSource { GSource source; GPollFD pollfd; sd_event *event; - guint *default_source_id; } SDEventSource; static gboolean @@ -48,41 +35,49 @@ event_check (GSource *source) static gboolean event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data) { - return sd_event_dispatch (((SDEventSource *)source)->event) > 0; + return sd_event_dispatch (((SDEventSource *) source)->event) > 0; } static void event_finalize (GSource *source) { - SDEventSource *s; + SDEventSource *s = (SDEventSource *) source; - s = (SDEventSource *) source; sd_event_unref (s->event); - if (s->default_source_id) - *s->default_source_id = 0; } static SDEventSource * -event_create_source (sd_event *event, guint *default_source_id) +event_create_source (sd_event *event) { - static GSourceFuncs event_funcs = { + static const GSourceFuncs event_funcs = { .prepare = event_prepare, .check = event_check, .dispatch = event_dispatch, .finalize = event_finalize, }; SDEventSource *source; + gboolean is_default_event = FALSE; + int r; - g_return_val_if_fail (event, NULL); + if (!event) { + is_default_event = TRUE; + r = sd_event_default (&event); + if (r < 0) + g_return_val_if_reached (NULL); + } - source = (SDEventSource *) g_source_new (&event_funcs, sizeof (SDEventSource)); + source = (SDEventSource *) g_source_new ((GSourceFuncs *) &event_funcs, sizeof (SDEventSource)); - source->event = sd_event_ref (event); - source->pollfd.fd = sd_event_get_fd (event); - source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; - source->default_source_id = default_source_id; + source->event = is_default_event + ? g_steal_pointer (&event) + : sd_event_ref (event); - g_source_add_poll ((GSource *) source, &source->pollfd); + source->pollfd = (GPollFD) { + .fd = sd_event_get_fd (source->event), + .events = G_IO_IN | G_IO_HUP | G_IO_ERR, + }; + + g_source_add_poll (&source->source, &source->pollfd); return source; } @@ -92,35 +87,15 @@ event_attach (sd_event *event, GMainContext *context) { SDEventSource *source; guint id; - int r; - sd_event *e = event; - guint *p_default_source_id = NULL; - if (!e) { - static guint default_source_id = 0; + source = event_create_source (event); - if (default_source_id) { - /* The default event cannot be registered multiple times. */ - g_return_val_if_reached (0); - } + g_return_val_if_fail (source, 0); - r = sd_event_default (&e); - if (r < 0) - g_return_val_if_reached (0); - - p_default_source_id = &default_source_id; - } - - source = event_create_source (e, p_default_source_id); id = g_source_attach ((GSource *) source, context); g_source_unref ((GSource *) source); - if (!event) { - *p_default_source_id = id; - sd_event_unref (e); - } - - g_return_val_if_fail (id, 0); + nm_assert (id != 0); return id; } diff --git a/src/systemd/nm-sd.h b/src/systemd/nm-sd.h index 07fc2ad4..99904243 100644 --- a/src/systemd/nm-sd.h +++ b/src/systemd/nm-sd.h @@ -1,17 +1,5 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ diff --git a/src/systemd/sd-adapt-core/nm-sd-adapt-core.c b/src/systemd/sd-adapt-core/nm-sd-adapt-core.c index c461752e..a9f8bd1c 100644 --- a/src/systemd/sd-adapt-core/nm-sd-adapt-core.c +++ b/src/systemd/sd-adapt-core/nm-sd-adapt-core.c @@ -1,17 +1,5 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ diff --git a/src/systemd/sd-adapt-core/nm-sd-adapt-core.h b/src/systemd/sd-adapt-core/nm-sd-adapt-core.h index bd71dd18..81bc7320 100644 --- a/src/systemd/sd-adapt-core/nm-sd-adapt-core.h +++ b/src/systemd/sd-adapt-core/nm-sd-adapt-core.h @@ -1,18 +1,5 @@ -/* This program 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 of the License, or (at your option) any later version. - * - * This library 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 this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: LGPL-2.1+ +/* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/systemd/src/libsystemd-network/dhcp-internal.h index e0269b54..6a803d7b 100644 --- a/src/systemd/src/libsystemd-network/dhcp-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-internal.h @@ -15,11 +15,21 @@ #include "dhcp-protocol.h" #include "socket-util.h" +typedef struct sd_dhcp_option { + unsigned n_ref; + + uint8_t option; + void *data; + size_t length; +} sd_dhcp_option; + +extern const struct hash_ops dhcp_option_hash_ops; + 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, uint16_t arp_type, uint16_t port); -int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port); +int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type); int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len); int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, @@ -41,7 +51,7 @@ uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len); void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, uint16_t source, be32_t destination_addr, - uint16_t destination, uint16_t len); + uint16_t destination, uint16_t len, int ip_service_type); int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port); diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h index 122042ab..a2d0f8bd 100644 --- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp-lease-internal.h @@ -58,6 +58,9 @@ struct sd_dhcp_lease { struct in_addr *ntp; size_t ntp_size; + struct in_addr *sip; + size_t sip_size; + struct sd_dhcp_route *static_route; size_t static_route_size, static_route_allocated; diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c index 858fe57c..1f01ece1 100644 --- a/src/systemd/src/libsystemd-network/dhcp-network.c +++ b/src/systemd/src/libsystemd-network/dhcp-network.c @@ -11,7 +11,6 @@ #include <net/if_arp.h> #include <stdio.h> #include <string.h> -#include <sys/socket.h> #include <linux/filter.h> #include <linux/if_infiniband.h> #include <linux/if_packet.h> @@ -148,7 +147,7 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, bcast_addr, ð_mac, arp_type, dhcp_hlen, port); } -int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) { +int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) { union sockaddr_union src = { .in.sin_family = AF_INET, .in.sin_port = htobe16(port), @@ -161,7 +160,11 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) { if (s < 0) return -errno; - r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6); + if (ip_service_type >= 0) + 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; diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/systemd/src/libsystemd-network/dhcp-option.c index 50238b0a..49193879 100644 --- a/src/systemd/src/libsystemd-network/dhcp-option.c +++ b/src/systemd/src/libsystemd-network/dhcp-option.c @@ -8,10 +8,10 @@ #include <errno.h> #include <stdint.h> #include <stdio.h> -#include <string.h> #include "alloc-util.h" #include "dhcp-internal.h" +#include "dhcp-server-internal.h" #include "memory-util.h" #include "strv.h" #include "utf8.h" @@ -29,7 +29,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, case SD_DHCP_OPTION_PAD: case SD_DHCP_OPTION_END: - if (size < *offset + 1) + if (*offset + 1 > size) return -ENOBUFS; options[*offset] = code; @@ -37,42 +37,83 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, break; case SD_DHCP_OPTION_USER_CLASS: { - size_t len = 0; + size_t total = 0; char **s; - STRV_FOREACH(s, (char **) optval) - len += strlen(*s) + 1; + STRV_FOREACH(s, (char **) optval) { + size_t len = strlen(*s); + + if (len > 255) + return -ENAMETOOLONG; + + total += 1 + len; + } - if (size < *offset + len + 2) + if (*offset + 2 + total > size) return -ENOBUFS; options[*offset] = code; - options[*offset + 1] = len; + options[*offset + 1] = total; *offset += 2; STRV_FOREACH(s, (char **) optval) { - len = strlen(*s); - - if (len > 255) - return -ENAMETOOLONG; + size_t len = strlen(*s); options[*offset] = len; - memcpy_safe(&options[*offset + 1], *s, len); - *offset += len + 1; + memcpy(&options[*offset + 1], *s, len); + *offset += 1 + len; + } + + break; + } + case SD_DHCP_OPTION_SIP_SERVER: + if (*offset + 3 + optlen > size) + return -ENOBUFS; + + options[*offset] = code; + options[*offset + 1] = optlen + 1; + options[*offset + 2] = 1; + + memcpy_safe(&options[*offset + 3], optval, optlen); + *offset += 3 + optlen; + + break; + case SD_DHCP_OPTION_VENDOR_SPECIFIC: { + OrderedHashmap *s = (OrderedHashmap *) optval; + struct sd_dhcp_option *p; + size_t l = 0; + Iterator i; + + ORDERED_HASHMAP_FOREACH(p, s, i) + l += p->length + 2; + + if (*offset + l + 2 > size) + return -ENOBUFS; + + options[*offset] = code; + options[*offset + 1] = l; + + *offset += 2; + + ORDERED_HASHMAP_FOREACH(p, s, i) { + options[*offset] = p->option; + options[*offset + 1] = p->length; + memcpy(&options[*offset + 2], p->data, p->length); + *offset += 2 + p->length; } break; } default: - if (size < *offset + optlen + 2) + if (*offset + 2 + optlen > size) return -ENOBUFS; options[*offset] = code; options[*offset + 1] = optlen; memcpy_safe(&options[*offset + 2], optval, optlen); - *offset += optlen + 2; + *offset += 2 + optlen; break; } @@ -83,22 +124,25 @@ static int option_append(uint8_t options[], size_t size, size_t *offset, int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_t overload, uint8_t code, size_t optlen, const void *optval) { - size_t file_offset = 0, sname_offset =0; - bool file, sname; + const bool use_file = overload & DHCP_OVERLOAD_FILE; + const bool use_sname = overload & DHCP_OVERLOAD_SNAME; int r; assert(message); assert(offset); - file = overload & DHCP_OVERLOAD_FILE; - sname = overload & DHCP_OVERLOAD_SNAME; + /* If *offset is in range [0, size), we are writing to ->options, + * if *offset is in range [size, size + sizeof(message->file)) and use_file, we are writing to ->file, + * if *offset is in range [size + use_file*sizeof(message->file), size + use_file*sizeof(message->file) + sizeof(message->sname)) + * and use_sname, we are writing to ->sname. + */ if (*offset < size) { /* still space in the options array */ r = option_append(message->options, size, offset, code, optlen, optval); if (r >= 0) return 0; - else if (r == -ENOBUFS && (file || sname)) { + else if (r == -ENOBUFS && (use_file || use_sname)) { /* did not fit, but we have more buffers to try close the options array and move the offset to its end */ r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); @@ -110,8 +154,8 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, return r; } - if (overload & DHCP_OVERLOAD_FILE) { - file_offset = *offset - size; + if (use_file) { + size_t file_offset = *offset - size; if (file_offset < sizeof(message->file)) { /* still space in the 'file' array */ @@ -119,7 +163,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, if (r >= 0) { *offset = size + file_offset; return 0; - } else if (r == -ENOBUFS && sname) { + } else if (r == -ENOBUFS && use_sname) { /* did not fit, but we have more buffers to try close the file array and move the offset to its end */ r = option_append(message->options, size, offset, SD_DHCP_OPTION_END, 0, NULL); @@ -132,19 +176,18 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, } } - if (overload & DHCP_OVERLOAD_SNAME) { - sname_offset = *offset - size - (file ? sizeof(message->file) : 0); + if (use_sname) { + size_t sname_offset = *offset - size - use_file*sizeof(message->file); if (sname_offset < sizeof(message->sname)) { /* still space in the 'sname' array */ r = option_append(message->sname, sizeof(message->sname), &sname_offset, code, optlen, optval); if (r >= 0) { - *offset = size + (file ? sizeof(message->file) : 0) + sname_offset; + *offset = size + use_file*sizeof(message->file) + sname_offset; return 0; - } else { + } else /* no space, or other error, give up */ return r; - } } } @@ -274,3 +317,43 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t c return message_type; } + +static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) { + if (!i) + return NULL; + + free(i->data); + return mfree(i); +} + +int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret) { + assert_return(ret, -EINVAL); + assert_return(length == 0 || data, -EINVAL); + + _cleanup_free_ void *q = memdup(data, length); + if (!q) + return -ENOMEM; + + sd_dhcp_option *p = new(sd_dhcp_option, 1); + if (!p) + return -ENOMEM; + + *p = (sd_dhcp_option) { + .n_ref = 1, + .option = option, + .length = length, + .data = TAKE_PTR(q), + }; + + *ret = TAKE_PTR(p); + return 0; +} + +DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free); +DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR( + dhcp_option_hash_ops, + void, + trivial_hash_func, + trivial_compare_func, + sd_dhcp_option, + sd_dhcp_option_unref); diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/systemd/src/libsystemd-network/dhcp-packet.c index 9e565e28..2062be91 100644 --- a/src/systemd/src/libsystemd-network/dhcp-packet.c +++ b/src/systemd/src/libsystemd-network/dhcp-packet.c @@ -77,12 +77,15 @@ uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len) { void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr, uint16_t source_port, be32_t destination_addr, - uint16_t destination_port, uint16_t len) { + uint16_t destination_port, uint16_t len, int ip_service_type) { packet->ip.version = IPVERSION; packet->ip.ihl = DHCP_IP_SIZE / 4; packet->ip.tot_len = htobe16(len); - packet->ip.tos = IPTOS_CLASS_CS6; + if (ip_service_type >= 0) + packet->ip.tos = ip_service_type; + else + packet->ip.tos = IPTOS_CLASS_CS6; packet->ip.protocol = IPPROTO_UDP; packet->ip.saddr = source_addr; diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/systemd/src/libsystemd-network/dhcp6-internal.h index f28ba68d..517e357d 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-internal.h +++ b/src/systemd/src/libsystemd-network/dhcp6-internal.h @@ -85,7 +85,7 @@ typedef struct DHCP6IA DHCP6IA; int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code, size_t optlen, const void *optval); int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia); -int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd); +int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix); int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn); int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/systemd/src/libsystemd-network/dhcp6-network.c index 73c195a7..d43680a5 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-network.c +++ b/src/systemd/src/libsystemd-network/dhcp6-network.c @@ -10,7 +10,6 @@ #include <netinet/ip6.h> #include <stdio.h> #include <string.h> -#include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <linux/if_packet.h> diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index 562a34b5..bb4c4d91 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -7,7 +7,6 @@ #include <errno.h> #include <netinet/in.h> -#include <string.h> #include "sd-dhcp6-client.h" @@ -170,9 +169,10 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) { return r; } -int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) { +int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) { DHCP6Option *option = (DHCP6Option *)buf; size_t i = sizeof(*option) + sizeof(pd->ia_pd); + DHCP6PDPrefixOption *prefix_opt; DHCP6Address *prefix; assert_return(buf, -EINVAL); @@ -185,10 +185,7 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) { option->code = htobe16(SD_DHCP6_OPTION_IA_PD); memcpy(&option->data, &pd->ia_pd, sizeof(pd->ia_pd)); - LIST_FOREACH(addresses, prefix, pd->addresses) { - DHCP6PDPrefixOption *prefix_opt; - if (len < i + sizeof(*prefix_opt)) return -ENOBUFS; @@ -196,9 +193,19 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd) { prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); - memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, - sizeof(struct iapdprefix)); + memcpy(&prefix_opt->iapdprefix, &prefix->iapdprefix, sizeof(struct iapdprefix)); + i += sizeof(*prefix_opt); + } + + if (hint_pd_prefix && hint_pd_prefix->iapdprefix.prefixlen > 0) { + if (len < i + sizeof(*prefix_opt)) + return -ENOBUFS; + + prefix_opt = (DHCP6PDPrefixOption *)&buf[i]; + prefix_opt->option.code = htobe16(SD_DHCP6_OPTION_IA_PD_PREFIX); + prefix_opt->option.len = htobe16(sizeof(prefix_opt->iapdprefix)); + memcpy(&prefix_opt->iapdprefix, &hint_pd_prefix->iapdprefix, sizeof(struct iapdprefix)); i += sizeof(*prefix_opt); } diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/systemd/src/libsystemd-network/lldp-neighbor.c index 530af034..238d718b 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.c +++ b/src/systemd/src/libsystemd-network/lldp-neighbor.c @@ -10,7 +10,7 @@ #include "lldp-internal.h" #include "lldp-neighbor.h" #include "memory-util.h" -#include "missing.h" +#include "missing_network.h" #include "unaligned.h" static void lldp_neighbor_id_hash_func(const LLDPNeighborID *id, struct siphash *state) { diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/systemd/src/libsystemd-network/lldp-network.c index 5ba9f081..f4764dd1 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.c +++ b/src/systemd/src/libsystemd-network/lldp-network.c @@ -7,7 +7,7 @@ #include "fd-util.h" #include "lldp-network.h" -#include "missing.h" +#include "missing_network.h" #include "socket-util.h" int lldp_network_bind_raw_socket(int ifindex) { diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c index 209ce884..7d22e754 100644 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ b/src/systemd/src/libsystemd-network/network-internal.c @@ -22,6 +22,7 @@ #include "parse-util.h" #include "siphash24.h" #include "socket-util.h" +#include "string-table.h" #include "string-util.h" #include "strv.h" #include "utf8.h" @@ -139,15 +140,38 @@ static int net_condition_test_property(char * const *match_property, sd_device * return true; } +static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = { + [NL80211_IFTYPE_ADHOC] = "ad-hoc", + [NL80211_IFTYPE_STATION] = "station", + [NL80211_IFTYPE_AP] = "ap", + [NL80211_IFTYPE_AP_VLAN] = "ap-vlan", + [NL80211_IFTYPE_WDS] = "wds", + [NL80211_IFTYPE_MONITOR] = "monitor", + [NL80211_IFTYPE_MESH_POINT] = "mesh-point", + [NL80211_IFTYPE_P2P_CLIENT] = "p2p-client", + [NL80211_IFTYPE_P2P_GO] = "p2p-go", + [NL80211_IFTYPE_P2P_DEVICE] = "p2p-device", + [NL80211_IFTYPE_OCB] = "ocb", + [NL80211_IFTYPE_NAN] = "nan", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype); + bool net_match_config(Set *match_mac, char * const *match_paths, char * const *match_drivers, char * const *match_types, char * const *match_names, char * const *match_property, + char * const *match_wifi_iftype, + char * const *match_ssid, + Set *match_bssid, sd_device *device, const struct ether_addr *dev_mac, - const char *dev_name) { + const char *dev_name, + enum nl80211_iftype wifi_iftype, + const char *ssid, + const struct ether_addr *bssid) { const char *dev_path = NULL, *dev_driver = NULL, *dev_type = NULL, *mac_str; @@ -181,6 +205,15 @@ bool net_match_config(Set *match_mac, if (!net_condition_test_property(match_property, device)) return false; + if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(wifi_iftype))) + return false; + + if (!net_condition_test_strv(match_ssid, ssid)) + return false; + + if (match_bssid && (!bssid || !set_contains(match_bssid, bssid))) + return false; + return true; } @@ -257,7 +290,7 @@ int config_parse_match_strv( for (;;) { _cleanup_free_ char *word = NULL, *k = NULL; - r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE); + r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); if (r == 0) return 0; if (r == -ENOMEM) diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h index 487421fb..2eb0cba5 100644 --- a/src/systemd/src/libsystemd-network/network-internal.h +++ b/src/systemd/src/libsystemd-network/network-internal.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once +#include <linux/nl80211.h> #include <stdbool.h> #include "sd-device.h" @@ -21,9 +22,15 @@ bool net_match_config(Set *match_mac, char * const *match_type, char * const *match_name, char * const *match_property, + char * const *match_wifi_iftype, + char * const *match_ssid, + Set *match_bssid, sd_device *device, const struct ether_addr *dev_mac, - const char *dev_name); + const char *dev_name, + enum nl80211_iftype wifi_iftype, + const char *ssid, + const struct ether_addr *bssid); CONFIG_PARSER_PROTOTYPE(config_parse_net_condition); CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index 2f531bc7..0266161d 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -10,7 +10,6 @@ #include <net/if_arp.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/ioctl.h> #include <linux/if_infiniband.h> @@ -92,6 +91,7 @@ struct sd_dhcp_client { usec_t start_time; uint64_t attempt; uint64_t max_attempts; + OrderedHashmap *options; usec_t request_sent; sd_event_source *timeout_t1; sd_event_source *timeout_t2; @@ -100,6 +100,7 @@ struct sd_dhcp_client { void *userdata; sd_dhcp_lease *lease; usec_t start_delay; + int ip_service_type; }; static const uint8_t default_req_opts[] = { @@ -234,6 +235,7 @@ int sd_dhcp_client_set_mac( DHCP_CLIENT_DONT_DESTROY(client); bool need_restart = false; + int r; assert_return(client, -EINVAL); assert_return(addr, -EINVAL); @@ -261,8 +263,11 @@ int sd_dhcp_client_set_mac( client->mac_addr_len = addr_len; client->arp_type = arp_type; - if (need_restart && client->state != DHCP_STATE_STOPPED) - sd_dhcp_client_start(client); + if (need_restart && client->state != DHCP_STATE_STOPPED) { + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); + } return 0; } @@ -298,6 +303,7 @@ int sd_dhcp_client_set_client_id( DHCP_CLIENT_DONT_DESTROY(client); bool need_restart = false; + int r; assert_return(client, -EINVAL); assert_return(data, -EINVAL); @@ -331,8 +337,11 @@ int sd_dhcp_client_set_client_id( memcpy(&client->client_id.raw.data, data, data_len); client->client_id_len = data_len + sizeof (client->client_id.type); - if (need_restart && client->state != DHCP_STATE_STOPPED) - sd_dhcp_client_start(client); + if (need_restart && client->state != DHCP_STATE_STOPPED) { + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); + } return 0; } @@ -363,7 +372,7 @@ static int dhcp_client_set_iaid_duid_internal( if (duid) { r = dhcp_validate_duid_len(duid_type, duid_len, true); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to validate length of DUID: %m"); } zero(client->client_id); @@ -378,7 +387,7 @@ static int dhcp_client_set_iaid_duid_internal( true, &client->client_id.ns.iaid); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set IAID: %m"); } } @@ -390,32 +399,32 @@ static int dhcp_client_set_iaid_duid_internal( switch (duid_type) { case DUID_TYPE_LLT: if (client->mac_addr_len == 0) - return -EOPNOTSUPP; + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); r = dhcp_identifier_set_duid_llt(&client->client_id.ns.duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &len); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set DUID-LLT: %m"); break; case DUID_TYPE_EN: r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &len); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set DUID-EN: %m"); break; case DUID_TYPE_LL: if (client->mac_addr_len == 0) - return -EOPNOTSUPP; + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); r = dhcp_identifier_set_duid_ll(&client->client_id.ns.duid, client->mac_addr, client->mac_addr_len, client->arp_type, &len); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set DUID-LL: %m"); break; case DUID_TYPE_UUID: r = dhcp_identifier_set_duid_uuid(&client->client_id.ns.duid, &len); if (r < 0) - return r; + return log_dhcp_client_errno(client, r, "Failed to set DUID-UUID: %m"); break; default: - return -EINVAL; + return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); } client->client_id_len = sizeof(client->client_id.type) + len + @@ -424,7 +433,9 @@ static int dhcp_client_set_iaid_duid_internal( if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { log_dhcp_client(client, "Configured %sDUID, restarting.", iaid_append ? "IAID+" : ""); client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); - sd_dhcp_client_start(client); + r = sd_dhcp_client_start(client); + if (r < 0) + return log_dhcp_client_errno(client, r, "Failed to restart DHCPv4 client: %m"); } return 0; @@ -534,6 +545,24 @@ int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempt return 0; } +int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) { + int r; + + assert_return(client, -EINVAL); + assert_return(v, -EINVAL); + + r = ordered_hashmap_ensure_allocated(&client->options, &dhcp_option_hash_ops); + if (r < 0) + return r; + + r = ordered_hashmap_put(client->options, UINT_TO_PTR(v->option), v); + if (r < 0) + return r; + + sd_dhcp_option_ref(v); + return 0; +} + int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { assert_return(client, -EINVAL); @@ -546,6 +575,14 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) { return 0; } +int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) { + assert_return(client, -EINVAL); + + client->ip_service_type = type; + + return 0; +} + static int client_notify(sd_dhcp_client *client, int event) { assert(client); @@ -778,7 +815,7 @@ static int dhcp_client_send_raw( size_t len) { dhcp_packet_append_ip_headers(packet, INADDR_ANY, client->port, - INADDR_BROADCAST, DHCP_PORT_SERVER, len); + INADDR_BROADCAST, DHCP_PORT_SERVER, len, client->ip_service_type); return dhcp_network_send_raw_socket(client->fd, &client->link, packet, len); @@ -787,6 +824,8 @@ static int dhcp_client_send_raw( static int client_send_discover(sd_dhcp_client *client) { _cleanup_free_ DHCPPacket *discover = NULL; size_t optoffset, optlen; + sd_dhcp_option *j; + Iterator i; int r; assert(client); @@ -803,7 +842,9 @@ static int client_send_discover(sd_dhcp_client *client) { address be assigned, and may include the ’IP address lease time’ option to suggest the lease time it would like. */ - if (client->last_addr != INADDR_ANY) { + /* RFC7844 section 3: + SHOULD NOT contain any other option. */ + if (!client->anonymize && client->last_addr != INADDR_ANY) { r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, 4, &client->last_addr); @@ -848,6 +889,13 @@ static int client_send_discover(sd_dhcp_client *client) { return r; } + ORDERED_HASHMAP_FOREACH(j, client->options, i) { + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, + j->option, j->length, j->data); + if (r < 0) + return r; + } + r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_END, 0, NULL); if (r < 0) @@ -866,41 +914,6 @@ static int client_send_discover(sd_dhcp_client *client) { return 0; } -static int client_send_release(sd_dhcp_client *client) { - _cleanup_free_ DHCPPacket *release = NULL; - size_t optoffset, optlen; - int r; - - assert(client); - assert(!IN_SET(client->state, DHCP_STATE_STOPPED)); - - r = client_message_init(client, &release, DHCP_RELEASE, - &optlen, &optoffset); - if (r < 0) - return r; - - /* Fill up release IP and MAC */ - release->dhcp.ciaddr = client->lease->address; - memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len); - - r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0, - SD_DHCP_OPTION_END, 0, NULL); - if (r < 0) - return r; - - r = dhcp_network_send_udp_socket(client->fd, - client->lease->server_address, - DHCP_PORT_SERVER, - &release->dhcp, - sizeof(DHCPMessage) + optoffset); - if (r < 0) - return r; - - log_dhcp_client(client, "RELEASE"); - - return 0; -} - static int client_send_request(sd_dhcp_client *client) { _cleanup_free_ DHCPPacket *request = NULL; size_t optoffset, optlen; @@ -1000,15 +1013,14 @@ static int client_send_request(sd_dhcp_client *client) { if (r < 0) return r; - if (client->state == DHCP_STATE_RENEWING) { + if (client->state == DHCP_STATE_RENEWING) r = dhcp_network_send_udp_socket(client->fd, client->lease->server_address, DHCP_PORT_SERVER, &request->dhcp, sizeof(DHCPMessage) + optoffset); - } else { + else r = dhcp_client_send_raw(client, request, sizeof(DHCPPacket) + optoffset); - } if (r < 0) return r; @@ -1216,7 +1228,7 @@ static int client_initialize_time_events(sd_dhcp_client *client) { assert(client); assert(client->event); - if (client->start_delay) { + if (client->start_delay > 0) { assert_se(sd_event_now(client->event, clock_boottime_or_monotonic(), &usec) >= 0); usec += client->start_delay; } @@ -1667,7 +1679,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i goto error; } - r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port); + r = dhcp_network_bind_udp_socket(client->ifindex, client->lease->address, client->port, client->ip_service_type); if (r < 0) { log_dhcp_client(client, "could not bind UDP socket"); goto error; @@ -1887,6 +1899,17 @@ static int client_receive_message_raw( return client_handle_message(client, &packet->dhcp, len); } +int sd_dhcp_client_send_renew(sd_dhcp_client *client) { + assert_return(client, -EINVAL); + assert_return(client->fd >= 0, -EINVAL); + + client->start_delay = 0; + client->attempt = 1; + client->state = DHCP_STATE_RENEWING; + + return client_initialize_time_events(client); +} + int sd_dhcp_client_start(sd_dhcp_client *client) { int r; @@ -1915,8 +1938,35 @@ int sd_dhcp_client_start(sd_dhcp_client *client) { int sd_dhcp_client_send_release(sd_dhcp_client *client) { assert_return(client, -EINVAL); + assert_return(client->state != DHCP_STATE_STOPPED, -ESTALE); + assert_return(client->lease, -EUNATCH); + + _cleanup_free_ DHCPPacket *release = NULL; + size_t optoffset, optlen; + int r; + + r = client_message_init(client, &release, DHCP_RELEASE, &optlen, &optoffset); + if (r < 0) + return r; + + /* Fill up release IP and MAC */ + release->dhcp.ciaddr = client->lease->address; + memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len); + + r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0, + SD_DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; - client_send_release(client); + r = dhcp_network_send_udp_socket(client->fd, + client->lease->server_address, + DHCP_PORT_SERVER, + &release->dhcp, + sizeof(DHCPMessage) + optoffset); + if (r < 0) + return r; + + log_dhcp_client(client, "RELEASE"); return 0; } @@ -1966,7 +2016,8 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) { } static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { - assert(client); + if (!client) + return NULL; log_dhcp_client(client, "FREE"); @@ -1985,17 +2036,16 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { free(client->hostname); free(client->vendor_class_identifier); client->user_class = strv_free(client->user_class); + ordered_hashmap_free(client->options); return mfree(client); } DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free); int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { - _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = NULL; - assert_return(ret, -EINVAL); - client = new(sd_dhcp_client, 1); + _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1); if (!client) return -ENOMEM; @@ -2008,6 +2058,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { .port = DHCP_PORT_CLIENT, .anonymize = !!anonymize, .max_attempts = (uint64_t) -1, + .ip_service_type = -1, }; /* NOTE: this could be moved to a function. */ if (anonymize) { diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c index 7559d066..ac6fe3f4 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -7,9 +7,7 @@ #include <arpa/inet.h> #include <errno.h> -#include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -122,6 +120,17 @@ int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) { return (int) lease->ntp_size; } +int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) { + assert_return(lease, -EINVAL); + assert_return(addr, -EINVAL); + + if (lease->sip_size <= 0) + return -ENODATA; + + *addr = lease->sip; + return (int) lease->sip_size; +} + int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { assert_return(lease, -EINVAL); assert_return(domainname, -EINVAL); @@ -271,6 +280,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) { free(lease->domainname); free(lease->dns); free(lease->ntp); + free(lease->sip); free(lease->static_route); free(lease->client_id); free(lease->vendor_specific); @@ -404,6 +414,36 @@ static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_add return 0; } +static int lease_parse_sip_server(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) { + assert(option); + assert(ret); + assert(n_ret); + + if (len <= 0) { + *ret = mfree(*ret); + *n_ret = 0; + } else { + size_t n_addresses; + struct in_addr *addresses; + int l = len - 1; + + if (l % 4 != 0) + return -EINVAL; + + n_addresses = l / 4; + + addresses = newdup(struct in_addr, option + 1, n_addresses); + if (!addresses) + return -ENOMEM; + + free(*ret); + *ret = addresses; + *n_ret = n_addresses; + } + + return 0; +} + static int lease_parse_routes( const uint8_t *option, size_t len, struct sd_dhcp_route **routes, size_t *routes_size, size_t *routes_allocated) { @@ -557,6 +597,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void log_debug_errno(r, "Failed to parse NTP server, ignoring: %m"); break; + case SD_DHCP_OPTION_SIP_SERVER: + r = lease_parse_sip_server(option, len, &lease->sip, &lease->sip_size); + if (r < 0) + log_debug_errno(r, "Failed to parse SIP server, ignoring: %m"); + break; + case SD_DHCP_OPTION_STATIC_ROUTE: r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); if (r < 0) @@ -895,6 +941,13 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { fputc('\n', f); } + r = sd_dhcp_lease_get_sip(lease, &addresses); + if (r > 0) { + fputs("SIP=", f); + serialize_in_addrs(f, addresses, r, false, NULL); + fputc('\n', f); + } + r = sd_dhcp_lease_get_domainname(lease, &string); if (r >= 0) fprintf(f, "DOMAINNAME=%s\n", string); @@ -985,6 +1038,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { *broadcast = NULL, *dns = NULL, *ntp = NULL, + *sip = NULL, *mtu = NULL, *routes = NULL, *domains = NULL, @@ -1013,6 +1067,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { "BROADCAST", &broadcast, "DNS", &dns, "NTP", &ntp, + "SIP", &sip, "MTU", &mtu, "DOMAINNAME", &lease->domainname, "HOSTNAME", &lease->hostname, @@ -1117,6 +1172,14 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { lease->ntp_size = r; } + if (sip) { + r = deserialize_in_addrs(&lease->sip, sip); + if (r < 0) + log_debug_errno(r, "Failed to deserialize SIP servers %s, ignoring: %m", sip); + else + lease->ntp_size = r; + } + if (mtu) { r = safe_atou16(mtu, &lease->mtu); if (r < 0) diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c index f67a45bd..e1150f98 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -6,7 +6,6 @@ #include "nm-sd-adapt-core.h" #include <errno.h> -#include <string.h> #include <sys/ioctl.h> #include <linux/if_arp.h> #include <linux/if_infiniband.h> @@ -31,6 +30,9 @@ #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN +#define IRT_DEFAULT (1 * USEC_PER_DAY) +#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, @@ -45,6 +47,7 @@ struct sd_dhcp6_client { sd_event *event; int event_priority; int ifindex; + DHCP6Address hint_pd_prefix; struct in6_addr local_address; uint8_t mac_addr[MAX_MAC_ADDR_LEN]; size_t mac_addr_len; @@ -73,6 +76,8 @@ struct sd_dhcp6_client { void *userdata; struct duid duid; size_t duid_len; + usec_t information_request_time_usec; + usec_t information_refresh_time_usec; }; static const uint16_t default_req_opts[] = { @@ -184,6 +189,22 @@ int sd_dhcp6_client_set_mac( return 0; } +int sd_dhcp6_client_set_prefix_delegation_hint( + sd_dhcp6_client *client, + uint8_t prefixlen, + const struct in6_addr *pd_address) { + + assert_return(client, -EINVAL); + assert_return(pd_address, -EINVAL); + + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + + client->hint_pd_prefix.iapdprefix.address = *pd_address; + client->hint_pd_prefix.iapdprefix.prefixlen = prefixlen; + + return 0; +} + static int client_ensure_duid(sd_dhcp6_client *client) { if (client->duid_len != 0) return 0; @@ -213,7 +234,7 @@ static int dhcp6_client_set_duid_internal( if (r < 0) { r = dhcp_validate_duid_len(duid_type, duid_len, false); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to validate length of DUID: %m"); log_dhcp6_client(client, "Setting DUID of type %u with unexpected content", duid_type); } @@ -225,32 +246,32 @@ static int dhcp6_client_set_duid_internal( switch (duid_type) { case DUID_TYPE_LLT: if (client->mac_addr_len == 0) - return -EOPNOTSUPP; + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LLT, MAC address is not set."); r = dhcp_identifier_set_duid_llt(&client->duid, llt_time, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to set DUID-LLT: %m"); break; case DUID_TYPE_EN: r = dhcp_identifier_set_duid_en(&client->duid, &client->duid_len); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to set DUID-EN: %m"); break; case DUID_TYPE_LL: if (client->mac_addr_len == 0) - return -EOPNOTSUPP; + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set DUID-LL, MAC address is not set."); r = dhcp_identifier_set_duid_ll(&client->duid, client->mac_addr, client->mac_addr_len, client->arp_type, &client->duid_len); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to set DUID-LL: %m"); break; case DUID_TYPE_UUID: r = dhcp_identifier_set_duid_uuid(&client->duid, &client->duid_len); if (r < 0) - return r; + return log_dhcp6_client_errno(client, r, "Failed to set DUID-UUID: %m"); break; default: - return -EINVAL; + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(EINVAL), "Invalid DUID type"); } #else /* NM_IGNORED */ g_return_val_if_reached (-EINVAL); @@ -493,7 +514,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { } if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { - r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd); + r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix); if (r < 0) return r; @@ -531,7 +552,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { } if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { - r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd); + r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); if (r < 0) return r; @@ -557,7 +578,7 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) { } if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) { - r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd); + r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL); if (r < 0) return r; @@ -826,6 +847,7 @@ static int client_parse_message( uint32_t lt_t1 = ~0, lt_t2 = ~0; bool clientid = false; size_t pos = 0; + usec_t irt = IRT_DEFAULT; int r; assert(client); @@ -1000,6 +1022,13 @@ static int client_parse_message( return r; break; + + case SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME: + if (optlen != 4) + return -EINVAL; + + irt = unaligned_read_be32((be32_t *) optval) * USEC_PER_SEC; + break; } pos += offsetof(DHCP6Option, data) + optlen; @@ -1031,6 +1060,8 @@ static int client_parse_message( } } + client->information_refresh_time_usec = MAX(irt, IRT_MINIMUM); + return 0; } @@ -1431,8 +1462,15 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { client->fd = r; } - if (client->information_request) + if (client->information_request) { + usec_t t = now(CLOCK_MONOTONIC); + + if (t < usec_add(client->information_request_time_usec, client->information_refresh_time_usec)) + return 0; + + client->information_request_time_usec = t; state = DHCP6_STATE_INFORMATION_REQUEST; + } log_dhcp6_client(client, "Started in %s mode", client->information_request? "Information request": @@ -1521,6 +1559,8 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) { .request = DHCP6_REQUEST_IA_NA, .fd = -1, .req_opts_len = ELEMENTSOF(default_req_opts), + .hint_pd_prefix.iapdprefix.lifetime_preferred = (be32_t) -1, + .hint_pd_prefix.iapdprefix.lifetime_valid = (be32_t) -1, .req_opts = TAKE_PTR(req_opts), }; diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/systemd/src/libsystemd-network/sd-ipv4acd.c index e7561480..3efa8170 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -10,7 +10,6 @@ #include <netinet/if_ether.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "sd-ipv4acd.h" diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/systemd/src/libsystemd-network/sd-ipv4ll.c index daac8839..2d17b4fe 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c +++ b/src/systemd/src/libsystemd-network/sd-ipv4ll.c @@ -9,7 +9,6 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include "sd-id128.h" #include "sd-ipv4acd.h" diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/systemd/src/libsystemd/sd-event/sd-event.c index c3781706..7c4566e3 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/systemd/src/libsystemd/sd-event/sd-event.c @@ -18,7 +18,7 @@ #include "list.h" #include "macro.h" #include "memory-util.h" -#include "missing.h" +#include "missing_syscall.h" #include "prioq.h" #include "process-util.h" #include "set.h" @@ -773,11 +773,13 @@ static void source_disconnect(sd_event_source *s) { event = s->event; - s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID; s->event = NULL; LIST_REMOVE(sources, event->sources, s); event->n_sources--; + /* Note that we don't invalidate the type here, since we still need it in order to close the fd or + * pidfd associated with this event source, which we'll do only on source_free(). */ + if (!s->floating) sd_event_unref(event); } @@ -2556,7 +2558,7 @@ static int process_child(sd_event *e) { * benefit in leaving it queued */ assert(s->child.options & (WSTOPPED|WCONTINUED)); - waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED))); + (void) waitid(P_PID, s->child.pid, &s->child.siginfo, WNOHANG|(s->child.options & (WSTOPPED|WCONTINUED))); } r = source_set_pending(s, true); diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/systemd/src/libsystemd/sd-id128/sd-id128.c index eeb29e97..c0d0fe81 100644 --- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c +++ b/src/systemd/src/libsystemd/sd-id128/sd-id128.c @@ -15,7 +15,7 @@ #include "io-util.h" #include "khash.h" #include "macro.h" -#include "missing.h" +#include "missing_syscall.h" #include "random-util.h" #include "user-util.h" #include "util.h" diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/systemd/src/systemd/sd-dhcp-client.h index ab62368e..f97e35b6 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/systemd/src/systemd/sd-dhcp-client.h @@ -26,6 +26,7 @@ #include <stdbool.h> #include "sd-dhcp-lease.h" +#include "sd-dhcp-option.h" #include "sd-event.h" #include "_sd-common.h" @@ -87,6 +88,7 @@ enum { 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_PRIVATE_BASE = 224, /* Windows 10 option to send when Anonymize=true */ @@ -173,10 +175,16 @@ int sd_dhcp_client_set_user_class( int sd_dhcp_client_get_lease( sd_dhcp_client *client, sd_dhcp_lease **ret); +int sd_dhcp_client_set_service_type( + sd_dhcp_client *client, + int type); + +int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v); int sd_dhcp_client_stop(sd_dhcp_client *client); int sd_dhcp_client_start(sd_dhcp_client *client); int sd_dhcp_client_send_release(sd_dhcp_client *client); +int sd_dhcp_client_send_renew(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client); diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/systemd/src/systemd/sd-dhcp-lease.h index d299c791..b80d607f 100644 --- a/src/systemd/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/src/systemd/sd-dhcp-lease.h @@ -44,6 +44,7 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); diff --git a/src/systemd/src/systemd/sd-dhcp-option.h b/src/systemd/src/systemd/sd-dhcp-option.h new file mode 100644 index 00000000..45dbd279 --- /dev/null +++ b/src/systemd/src/systemd/sd-dhcp-option.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#ifndef foosddhcpoptionhfoo +#define foosddhcpoptionhfoo + +/*** + Copyright © 2013 Intel Corporation. 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 <inttypes.h> +#include <sys/types.h> + +#include "_sd-common.h" + +_SD_BEGIN_DECLARATIONS; + +typedef struct sd_dhcp_option sd_dhcp_option; + +int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret); +sd_dhcp_option *sd_dhcp_option_ref(sd_dhcp_option *ra); +sd_dhcp_option *sd_dhcp_option_unref(sd_dhcp_option *ra); + +_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref); + +_SD_END_DECLARATIONS; + +#endif diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/systemd/src/systemd/sd-dhcp6-client.h index 43d38f5c..be34d43e 100644 --- a/src/systemd/src/systemd/sd-dhcp6-client.h +++ b/src/systemd/src/systemd/sd-dhcp6-client.h @@ -66,6 +66,7 @@ enum { SD_DHCP6_OPTION_IA_PD_PREFIX = 26, /* RFC 3633, prefix delegation */ SD_DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075, deprecated */ + SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME = 32, /* RFC 8415, sec. 21.23 */ /* option code 35 is unassigned */ @@ -119,6 +120,10 @@ int sd_dhcp6_client_get_information_request( int sd_dhcp6_client_set_request_option( sd_dhcp6_client *client, uint16_t option); +int sd_dhcp6_client_set_prefix_delegation_hint( + sd_dhcp6_client *client, + uint8_t prefixlen, + const struct in6_addr *pd_address); int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation); int sd_dhcp6_client_set_prefix_delegation(sd_dhcp6_client *client, |