summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2020-10-04 02:27:42 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2020-10-06 19:59:34 +0200
commitd93d655c406554f53e2c80e1aceee1440adfd4d6 (patch)
tree6a9b566940cf8112004311513d072ee2b701f6f8 /src
parentnetwork: configure IPv4 DAD per link address (diff)
downloadsystemd-d93d655c406554f53e2c80e1aceee1440adfd4d6.tar.xz
systemd-d93d655c406554f53e2c80e1aceee1440adfd4d6.zip
network: update MAC address in IPv4 ACD clients
When the MAC address of a link is updated, an address on the link may be under checking address duplication. Or, (currently such code is not implemented yet, but) address duplication check may be restarted later. For that case, the IPv4 ACD clients must use the new updated MAC address.
Diffstat (limited to 'src')
-rw-r--r--src/network/networkd-address.c45
-rw-r--r--src/network/networkd-address.h1
-rw-r--r--src/network/networkd-link.c4
3 files changed, 50 insertions, 0 deletions
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 0d2fa60edd..000f8cfa93 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -1402,6 +1402,51 @@ static int ipv4_dad_configure(Address *address) {
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);
+
+ if (running) {
+ r = sd_ipv4acd_stop(address->acd);
+ if (r < 0)
+ return r;
+ }
+
+ r = sd_ipv4acd_set_mac(address->acd, &address->link->mac);
+ 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;
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index 816e84550b..88dbefc126 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -66,6 +66,7 @@ int link_serialize_addresses(Link *link, FILE *f);
int link_deserialize_addresses(Link *link, const char *addresses);
int ipv4_dad_stop(Link *link);
+int ipv4_dad_update_mac(Link *link);
int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index ce708edabb..b32a436be5 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2697,6 +2697,10 @@ int link_update(Link *link, sd_netlink_message *m) {
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC for NDisc: %m");
}
+
+ r = ipv4_dad_update_mac(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not update MAC address in IPv4 ACD client: %m");
}
old_master = link->master_ifindex;