diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/meson.build | 2 | ||||
-rw-r--r-- | src/network/networkd-address.c | 168 | ||||
-rw-r--r-- | src/network/networkd-address.h | 9 | ||||
-rw-r--r-- | src/network/networkd-dhcp4.c | 181 | ||||
-rw-r--r-- | src/network/networkd-ipv4acd.c | 271 | ||||
-rw-r--r-- | src/network/networkd-ipv4acd.h | 10 | ||||
-rw-r--r-- | src/network/networkd-link.c | 24 | ||||
-rw-r--r-- | src/network/networkd-link.h | 3 |
8 files changed, 326 insertions, 342 deletions
diff --git a/src/network/meson.build b/src/network/meson.build index 5a3a23101d..4e137d7b9e 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -79,6 +79,8 @@ sources = files(''' networkd-dhcp4.h networkd-dhcp6.c networkd-dhcp6.h + networkd-ipv4acd.c + networkd-ipv4acd.h networkd-ipv4ll.c networkd-ipv4ll.h networkd-ipv6-proxy-ndp.c diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index a8f081ec81..35305aff99 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -9,6 +9,7 @@ #include "netlink-util.h" #include "networkd-address-pool.h" #include "networkd-address.h" +#include "networkd-ipv4acd.h" #include "networkd-manager.h" #include "networkd-network.h" #include "networkd-queue.h" @@ -129,6 +130,7 @@ static int address_new_static(Network *network, const char *filename, unsigned s address->network = network; address->section = TAKE_PTR(n); + address->is_static = true; r = ordered_hashmap_ensure_put(&network->addresses_by_section, &network_config_hash_ops, address->section, address); if (r < 0) @@ -152,6 +154,7 @@ Address *address_free(Address *address) { set_remove(address->link->addresses, address); set_remove(address->link->addresses_foreign, address); + set_remove(address->link->addresses_ipv4acd, address); set_remove(address->link->static_addresses, address); if (address->link->dhcp_address == address) address->link->dhcp_address = NULL; @@ -994,8 +997,6 @@ int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, return 1; } -static int ipv4_dad_configure(Address *address); - static int address_configure( const Address *address, Link *link, @@ -1242,6 +1243,12 @@ static int address_is_ready_to_configure(Link *link, const Address *address) { return log_link_warning_errno(link, SYNTHETIC_ERRNO(E2BIG), "Too many addresses are configured, refusing: %m"); + if (address->family == AF_INET && + address->duplicate_address_detection & ADDRESS_FAMILY_IPV4 && + link->hw_addr.length == ETH_ALEN && + !ether_addr_is_null(&link->hw_addr.ether)) + return ipv4acd_address_is_ready_to_configure(link, address); + r = address_add(link, address, NULL); if (r < 0) return log_link_warning_errno(link, r, "Could not add address: %m");; @@ -1286,12 +1293,6 @@ int request_process_address(Request *req) { if (r < 0) log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m"); - if (FLAGS_SET(a->duplicate_address_detection, ADDRESS_FAMILY_IPV4)) { - r = ipv4_dad_configure(a); - if (r < 0) - log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m"); - } - return 1; } @@ -1475,157 +1476,6 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, return 1; } -static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { - Address *address; - Link *link; - int r; - - assert(acd); - assert(userdata); - - address = (Address *) userdata; - link = address->link; - - assert(address->family == AF_INET); - - switch (event) { - case SD_IPV4ACD_EVENT_STOP: - log_link_debug(link, "Stopping ACD client..."); - return; - - case SD_IPV4ACD_EVENT_BIND: - log_link_debug(link, "Successfully claimed address "IPV4_ADDRESS_FMT_STR, - IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); - link_check_ready(link); - break; - - case SD_IPV4ACD_EVENT_CONFLICT: - log_link_warning(link, "DAD conflict. Dropping address "IPV4_ADDRESS_FMT_STR, - IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); - r = address_remove(address, link); - if (r < 0) - log_link_error_errno(link, r, "Failed to drop DAD conflicted address "IPV4_ADDRESS_FMT_STR, - IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); - - link_check_ready(link); - break; - - default: - assert_not_reached("Invalid IPv4ACD event."); - } - - (void) sd_ipv4acd_stop(acd); - - return; -} - -static int ipv4_dad_configure(Address *address) { - int r; - - assert(address); - assert(address->link); - - if (address->family != AF_INET) - return 0; - - log_address_debug(address, "Starting IPv4ACD client. Probing", address->link); - - if (!address->acd) { - r = sd_ipv4acd_new(&address->acd); - if (r < 0) - return r; - - r = sd_ipv4acd_attach_event(address->acd, address->link->manager->event, 0); - if (r < 0) - return r; - } - - r = sd_ipv4acd_set_ifindex(address->acd, address->link->ifindex); - if (r < 0) - return r; - - r = sd_ipv4acd_set_mac(address->acd, &address->link->hw_addr.ether); - if (r < 0) - return r; - - r = sd_ipv4acd_set_address(address->acd, &address->in_addr.in); - if (r < 0) - return r; - - r = sd_ipv4acd_set_callback(address->acd, static_address_on_acd, address); - if (r < 0) - return r; - - return sd_ipv4acd_start(address->acd, true); -} - -static int ipv4_dad_update_mac_one(Address *address) { - bool running; - int r; - - assert(address); - - if (!address->acd) - return 0; - - running = sd_ipv4acd_is_running(address->acd); - - r = sd_ipv4acd_stop(address->acd); - if (r < 0) - return r; - - r = sd_ipv4acd_set_mac(address->acd, &address->link->hw_addr.ether); - if (r < 0) - return r; - - if (running) { - r = sd_ipv4acd_start(address->acd, true); - if (r < 0) - return r; - } - - return 0; -} - -int ipv4_dad_update_mac(Link *link) { - Address *address; - int k, r = 0; - - assert(link); - - SET_FOREACH(address, link->addresses) { - k = ipv4_dad_update_mac_one(address); - if (k < 0 && r >= 0) - r = k; - } - - return r; -} - -int ipv4_dad_stop(Link *link) { - Address *address; - int k, r = 0; - - assert(link); - - SET_FOREACH(address, link->addresses) { - k = sd_ipv4acd_stop(address->acd); - if (k < 0 && r >= 0) - r = k; - } - - return r; -} - -void ipv4_dad_unref(Link *link) { - Address *address; - - assert(link); - - SET_FOREACH(address, link->addresses) - address->acd = sd_ipv4acd_unref(address->acd); -} - int config_parse_broadcast( const char *unit, const char *filename, diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h index a24320fca2..ff3d46abdd 100644 --- a/src/network/networkd-address.h +++ b/src/network/networkd-address.h @@ -41,12 +41,13 @@ typedef struct Address { bool scope_set:1; bool ip_masquerade_done:1; + bool is_static:1; /* currently only used by IPv4ACD */ + bool acd_announced:1; AddressFamily duplicate_address_detection; + sd_ipv4acd *acd; /* Called when address become ready */ address_ready_callback_t callback; - - sd_ipv4acd *acd; } Address; int address_new(Address **ret); @@ -71,10 +72,6 @@ int link_get_ipv6_address(Link *link, const struct in6_addr *address, Address ** int link_get_ipv4_address(Link *link, const struct in_addr *address, unsigned char prefixlen, Address **ret); int manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready); -void ipv4_dad_unref(Link *link); -int ipv4_dad_stop(Link *link); -int ipv4_dad_update_mac(Link *link); - int link_request_address( Link *link, Address *address, diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 1aaeda98e2..f80adcdbcf 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -14,6 +14,7 @@ #include "network-internal.h" #include "networkd-address.h" #include "networkd-dhcp4.h" +#include "networkd-ipv4acd.h" #include "networkd-link.h" #include "networkd-manager.h" #include "networkd-network.h" @@ -84,9 +85,6 @@ static int dhcp4_release_old_lease(Link *link) { static void dhcp4_check_ready(Link *link) { int r; - if (link->network->dhcp_send_decline && !link->dhcp4_address_bind) - return; - if (link->dhcp4_messages > 0) { log_link_debug(link, "%s(): DHCPv4 address and routes are not set.", __func__); return; @@ -768,159 +766,32 @@ int dhcp4_lease_lost(Link *link) { link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); link_dirty(link); - (void) sd_ipv4acd_stop(link->dhcp_acd); - - if (r < 0) - return r; - - r = link_request_static_nexthops(link, true); - if (r < 0) - return r; - - return link_request_static_routes(link, true); -} - -static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { - struct in_addr address; - Link *link; - int r; - - assert(acd); - assert(userdata); - - link = userdata; - - switch (event) { - case SD_IPV4ACD_EVENT_STOP: - log_link_debug(link, "Stopping ACD client for DHCPv4 address."); - return; - - case SD_IPV4ACD_EVENT_BIND: - if (DEBUG_LOGGING) { - (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address); - log_link_debug(link, "Successfully claimed DHCPv4 address "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address)); - } - link->dhcp4_address_bind = true; - dhcp4_check_ready(link); - break; - - case SD_IPV4ACD_EVENT_CONFLICT: - (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address); - log_link_warning(link, "DAD conflict. Dropping DHCPv4 address "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address)); - - r = sd_dhcp_client_send_decline(link->dhcp_client); - if (r < 0) - log_link_warning_errno(link, r, "Failed to send DHCP DECLINE, ignoring: %m"); - - if (link->dhcp_lease) { - r = dhcp4_lease_lost(link); - if (r < 0) - link_enter_failed(link); - } - break; - - default: - assert_not_reached("Invalid IPv4ACD event."); - } - - (void) sd_ipv4acd_stop(acd); - - return; -} - -static int dhcp4_configure_dad(Link *link) { - int r; - - assert(link); - assert(link->manager); - assert(link->network); - - if (!link->network->dhcp_send_decline) - return 0; - - if (!link->dhcp_acd) { - r = sd_ipv4acd_new(&link->dhcp_acd); - if (r < 0) - return r; - - r = sd_ipv4acd_attach_event(link->dhcp_acd, link->manager->event, 0); - if (r < 0) - return r; - } - - r = sd_ipv4acd_set_ifindex(link->dhcp_acd, link->ifindex); - if (r < 0) - return r; - - r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->hw_addr.ether); - if (r < 0) - return r; - - return 0; -} - -static int dhcp4_dad_update_mac(Link *link) { - bool running; - int r; - - assert(link); - - if (!link->dhcp_acd) - return 0; - - running = sd_ipv4acd_is_running(link->dhcp_acd); + if (link->network->dhcp_send_decline) { + Address *a; - r = sd_ipv4acd_stop(link->dhcp_acd); - if (r < 0) - return r; + /* The acquired address may be still ARP probing and not configured. */ - r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->hw_addr.ether); - if (r < 0) - return r; + SET_FOREACH(a, link->addresses_ipv4acd) + if (!a->is_static && address_get(link, a, NULL) < 0) { + Request req = { + .link = link, + .address = a, + }; - if (running) { - r = sd_ipv4acd_start(link->dhcp_acd, true); - if (r < 0) - return r; + log_link_debug(link, "Canceling the request to configure DHCPv4 address "IPV4_ADDRESS_FMT_STR, + IPV4_ADDRESS_FMT_VAL(a->in_addr.in)); + request_drop(ordered_set_get(link->manager->request_queue, &req)); + } } - return 0; -} - -static int dhcp4_start_acd(Link *link) { - struct in_addr addr, old; - int r; - - if (!link->network->dhcp_send_decline) - return 0; - - if (!link->dhcp_lease) - return 0; - - (void) sd_ipv4acd_stop(link->dhcp_acd); - - link->dhcp4_address_bind = false; - - r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr); - if (r < 0) - return r; - - r = sd_ipv4acd_get_address(link->dhcp_acd, &old); - if (r < 0) - return r; - - r = sd_ipv4acd_set_address(link->dhcp_acd, &addr); if (r < 0) return r; - r = sd_ipv4acd_set_callback(link->dhcp_acd, dhcp_address_on_acd, link); + r = link_request_static_nexthops(link, true); if (r < 0) return r; - log_link_debug(link, "Starting IPv4ACD client. Probing DHCPv4 address "IPV4_ADDRESS_FMT_STR, - IPV4_ADDRESS_FMT_VAL(addr)); - - return sd_ipv4acd_start(link->dhcp_acd, !in4_addr_equal(&addr, &old)); + return link_request_static_routes(link, true); } static int dhcp4_address_ready_callback(Address *address) { @@ -957,11 +828,6 @@ static int dhcp4_after_address_configure(Request *req, void *object) { } link->dhcp_address = address; - - r = dhcp4_start_acd(link); - if (r < 0) - return log_link_error_errno(link, r, "Failed to start IPv4ACD for DHCPv4 address: %m"); - return 0; } @@ -1057,6 +923,7 @@ static int dhcp4_request_address(Link *link, bool announce) { addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr; SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link)); addr->route_metric = link->network->dhcp_route_metric; + addr->duplicate_address_detection = link->network->dhcp_send_decline ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_NO; if (address_get(link, addr, NULL) < 0) link->dhcp4_configured = false; @@ -1687,10 +1554,6 @@ int dhcp4_configure(Link *link) { if (r < 0) return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set initial DHCPv4 address: %m"); - r = dhcp4_configure_dad(link); - if (r < 0) - return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to configure service type: %m"); - return dhcp4_set_client_identifier(link); } @@ -1708,15 +1571,7 @@ int dhcp4_update_mac(Link *link) { if (r < 0) return r; - r = dhcp4_set_client_identifier(link); - if (r < 0) - return r; - - r = dhcp4_dad_update_mac(link); - if (r < 0) - return r; - - return 0; + return dhcp4_set_client_identifier(link); } int dhcp4_start(Link *link) { diff --git a/src/network/networkd-ipv4acd.c b/src/network/networkd-ipv4acd.c new file mode 100644 index 0000000000..06dfa2d540 --- /dev/null +++ b/src/network/networkd-ipv4acd.c @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "sd-dhcp-client.h" +#include "sd-ipv4acd.h" + +#include "networkd-address.h" +#include "networkd-dhcp4.h" +#include "networkd-ipv4acd.h" +#include "networkd-link.h" +#include "networkd-manager.h" + +static int static_address_on_stop(Link *link, Address *address) { + int r; + + assert(link); + assert(address); + + if (address_get(link, address, NULL) < 0) + return 0; + + log_link_debug(link, "Removing address "IPV4_ADDRESS_FMT_STR", as the ACD client is stopped.", + IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); + + r = address_remove(address, link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to remove address "IPV4_ADDRESS_FMT_STR": %m", + IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); + + return 0; +} + +static int static_address_on_conflict(Link *link, Address *address) { + int r; + + assert(link); + assert(address); + + if (address_get(link, address, NULL) < 0) { + log_link_warning(link, "Cannot configure requested address "IPV4_ADDRESS_FMT_STR", as an address conflict is detected.", + IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); + return 0; + } + + log_link_warning(link, "Dropping address "IPV4_ADDRESS_FMT_STR", as an address conflict is detected.", + IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); + + r = address_remove(address, link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to remove address "IPV4_ADDRESS_FMT_STR": %m", + IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); + + return 0; +} + +static int dhcp4_address_on_conflict(Link *link) { + int r; + + assert(link); + assert(link->dhcp_client); + + r = sd_dhcp_client_send_decline(link->dhcp_client); + if (r < 0) + log_link_warning_errno(link, r, "Failed to send DHCP DECLINE, ignoring: %m"); + + if (!link->dhcp_lease) + /* Unlikely, but during probing the address, the lease may be lost. */ + return 0; + + log_link_warning(link, "Dropping DHCPv4 lease, as an address conflict is detected."); + r = dhcp4_lease_lost(link); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to drop DHCPv4 lease: %m"); + + /* It is not necessary to call address_remove() here, as dhcp4_lease_lost() removes it. */ + return 0; +} + +static void on_acd(sd_ipv4acd *acd, int event, void *userdata, bool is_static) { + Address *address = userdata; + Link *link; + int r; + + assert(acd); + assert(address); + assert(address->acd == acd); + assert(address->link); + assert(address->family == AF_INET); + + link = address->link; + + switch (event) { + case SD_IPV4ACD_EVENT_STOP: + if (is_static) { + r = static_address_on_stop(link, address); + if (r < 0) + link_enter_failed(link); + } + + /* We have nothing to do for DHCPv4 lease here, as the dhcp client is already stopped + * when stopping the ipv4acd client. See link_stop_engines(). */ + break; + + case SD_IPV4ACD_EVENT_BIND: + log_link_debug(link, "Successfully claimed address "IPV4_ADDRESS_FMT_STR, + IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); + + address->acd_announced = true; + break; + + case SD_IPV4ACD_EVENT_CONFLICT: + if (is_static) + r = static_address_on_conflict(link, address); + else + r = dhcp4_address_on_conflict(link); + if (r < 0) + link_enter_failed(link); + break; + + default: + assert_not_reached("Invalid IPv4ACD event."); + } +} + +static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { + on_acd(acd, event, userdata, true); +} + +static void dhcp4_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { + on_acd(acd, event, userdata, false); +} + +static int ipv4acd_configure(Link *link, const Address *a) { + _cleanup_(address_freep) Address *address = NULL; + int r; + + assert(link); + assert(a); + assert(a->family == AF_INET); + + log_link_debug(link, "Configuring IPv4ACD for address "IPV4_ADDRESS_FMT_STR, + IPV4_ADDRESS_FMT_VAL(a->in_addr.in)); + + r = address_dup(a, &address); + if (r < 0) + return r; + + r = set_ensure_put(&link->addresses_ipv4acd, &address_hash_ops, address); + if (r < 0) + return r; + if (r == 0) + return -EEXIST; + address->link = link; + + r = sd_ipv4acd_new(&address->acd); + if (r < 0) + return r; + + r = sd_ipv4acd_attach_event(address->acd, link->manager->event, 0); + if (r < 0) + return r; + + r = sd_ipv4acd_set_ifindex(address->acd, link->ifindex); + if (r < 0) + return r; + + r = sd_ipv4acd_set_mac(address->acd, &link->hw_addr.ether); + if (r < 0) + return r; + + r = sd_ipv4acd_set_address(address->acd, &address->in_addr.in); + if (r < 0) + return r; + + r = sd_ipv4acd_set_callback(address->acd, + address->is_static ? static_address_on_acd : dhcp4_address_on_acd, + address); + if (r < 0) + return r; + + if (link_has_carrier(link)) { + r = sd_ipv4acd_start(address->acd, true); + if (r < 0) + return r; + } + + TAKE_PTR(address); + return 0; +} + +int ipv4acd_address_is_ready_to_configure(Link *link, const Address *address) { + Address *acd_address; + int r; + + acd_address = set_get(link->addresses_ipv4acd, address); + if (!acd_address) { + r = ipv4acd_configure(link, address); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to configure IPv4ACD client: %m"); + + return false; + } + + if (!acd_address->acd_announced) + return false; + + r = set_ensure_put(&link->addresses, &address_hash_ops, acd_address); + if (r < 0) + return log_oom(); + if (r == 0) + return log_link_warning_errno(link, SYNTHETIC_ERRNO(EEXIST), "Address already exists."); + + acd_address->flags |= IFA_F_TENTATIVE; + return true; +} + +int ipv4acd_update_mac(Link *link) { + Address *address; + int k, r = 0; + + assert(link); + + if (link->hw_addr.length != ETH_ALEN) + return 0; + if (ether_addr_is_null(&link->hw_addr.ether)) + return 0; + + SET_FOREACH(address, link->addresses_ipv4acd) { + assert(address->acd); + + k = sd_ipv4acd_set_mac(address->acd, &link->hw_addr.ether); + if (k < 0) + r = k; + } + if (r < 0) + link_enter_failed(link); + + return r; +} + +int ipv4acd_start(Link *link) { + Address *address; + int r; + + assert(link); + + SET_FOREACH(address, link->addresses_ipv4acd) { + if (sd_ipv4acd_is_running(address->acd)) + continue; + + r = sd_ipv4acd_start(address->acd, true); + if (r < 0) + return r; + } + + return 0; +} + +int ipv4acd_stop(Link *link) { + Address *address; + int k, r = 0; + + assert(link); + + SET_FOREACH(address, link->addresses_ipv4acd) { + k = sd_ipv4acd_stop(address->acd); + if (k < 0) + r = k; + } + + return r; +} diff --git a/src/network/networkd-ipv4acd.h b/src/network/networkd-ipv4acd.h new file mode 100644 index 0000000000..d2b4ff775f --- /dev/null +++ b/src/network/networkd-ipv4acd.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +typedef struct Address Address; +typedef struct Link Link; + +int ipv4acd_address_is_ready_to_configure(Link *link, const Address *address); +int ipv4acd_update_mac(Link *link); +int ipv4acd_start(Link *link); +int ipv4acd_stop(Link *link); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index ba1bd283df..4efe74ad41 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -33,6 +33,7 @@ #include "networkd-dhcp-server.h" #include "networkd-dhcp4.h" #include "networkd-dhcp6.h" +#include "networkd-ipv4acd.h" #include "networkd-ipv4ll.h" #include "networkd-ipv6-proxy-ndp.h" #include "networkd-link-bus.h" @@ -204,7 +205,6 @@ static void link_free_engines(Link *link) { link->dhcp_server = sd_dhcp_server_unref(link->dhcp_server); link->dhcp_client = sd_dhcp_client_unref(link->dhcp_client); link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); - link->dhcp_acd = sd_ipv4acd_unref(link->dhcp_acd); link->lldp = sd_lldp_unref(link->lldp); link_lldp_emit_stop(link); @@ -216,8 +216,6 @@ static void link_free_engines(Link *link) { link->dhcp6_lease = sd_dhcp6_lease_unref(link->dhcp6_lease); link->ndisc = sd_ndisc_unref(link->ndisc); link->radv = sd_radv_unref(link->radv); - - ipv4_dad_unref(link); } static Link *link_free(Link *link) { @@ -244,6 +242,7 @@ static Link *link_free(Link *link) { link->addresses = set_free(link->addresses); link->addresses_foreign = set_free(link->addresses_foreign); + link->addresses_ipv4acd = set_free(link->addresses_ipv4acd); link->pool_addresses = set_free(link->pool_addresses); link->static_addresses = set_free(link->static_addresses); link->dhcp6_addresses = set_free(link->dhcp6_addresses); @@ -361,6 +360,7 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) { bool keep_dhcp = may_keep_dhcp && link->network && + !link->network->dhcp_send_decline && /* IPv4 ACD for the DHCPv4 address is running. */ (link->manager->restarting || FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP_ON_STOP)); @@ -370,10 +370,6 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) { r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m"); } - k = sd_ipv4acd_stop(link->dhcp_acd); - if (k < 0) - r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client for DHCPv4: %m"); - k = sd_dhcp_server_stop(link->dhcp_server); if (k < 0) r = log_link_warning_errno(link, k, "Could not stop DHCPv4 server: %m"); @@ -386,7 +382,7 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) { if (k < 0) r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m"); - k = ipv4_dad_stop(link); + k = ipv4acd_stop(link); if (k < 0) r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client: %m"); @@ -668,6 +664,10 @@ static int link_acquire_dynamic_ipv4_conf(Link *link) { return log_link_warning_errno(link, r, "Could not start DHCP server: %m"); } + r = ipv4acd_start(link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not start IPv4 ACD client: %m"); + return 0; } @@ -2039,6 +2039,10 @@ static int link_update_hardware_address(Link *link, sd_netlink_message *message) r = ipv4ll_update_mac(link); if (r < 0) + return log_link_debug_errno(link, r, "Could not update MAC address in IPv4 ACD client: %m"); + + r = ipv4ll_update_mac(link); + if (r < 0) return log_link_debug_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); r = dhcp4_update_mac(link); @@ -2065,10 +2069,6 @@ static int link_update_hardware_address(Link *link, sd_netlink_message *message) return log_link_debug_errno(link, r, "Could not update MAC address for LLDP: %m"); } - r = ipv4_dad_update_mac(link); - if (r < 0) - return log_link_debug_errno(link, r, "Could not update MAC address in IPv4 ACD client: %m"); - return 0; } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 28c2821ee6..4077ccaf09 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -104,6 +104,7 @@ typedef struct Link { Set *addresses; Set *addresses_foreign; + Set *addresses_ipv4acd; Set *pool_addresses; Set *static_addresses; Set *neighbors; @@ -119,11 +120,9 @@ typedef struct Link { Set *dhcp_routes, *dhcp_routes_old; char *lease_file; unsigned dhcp4_messages; - sd_ipv4acd *dhcp_acd; bool dhcp4_route_failed:1; bool dhcp4_route_retrying:1; bool dhcp4_configured:1; - bool dhcp4_address_bind:1; sd_ipv4ll *ipv4ll; bool ipv4ll_address_configured:1; |