]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
Merge pull request #1225 from mbiebl/remove-sphinx-leftover2
[thirdparty/systemd.git] / src / network / networkd-link.c
CommitLineData
f579559b
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <netinet/ether.h>
23#include <linux/if.h>
4cc7a82c 24#include <unistd.h>
f579559b 25
f579559b 26#include "util.h"
505f8da7 27#include "virt.h"
5a8bcb67 28#include "fileio.h"
fe027299 29#include "socket-util.h"
1346b1f0 30#include "bus-util.h"
5a8bcb67 31#include "udev-util.h"
fc2f9534 32#include "netlink-util.h"
bd91b83e 33#include "dhcp-lease-internal.h"
c6f7c917 34#include "network-internal.h"
fc2f9534 35
5a8bcb67
LP
36#include "networkd-link.h"
37#include "networkd-netdev.h"
fe8db0c5 38
a97dcc12 39bool link_dhcp6_enabled(Link *link) {
78c958f8
TG
40 if (link->flags & IFF_LOOPBACK)
41 return false;
42
43 if (!link->network)
44 return false;
45
e0ee46f2 46 return link->network->dhcp & ADDRESS_FAMILY_IPV6;
78c958f8
TG
47}
48
a97dcc12 49bool link_dhcp4_enabled(Link *link) {
78c958f8
TG
50 if (link->flags & IFF_LOOPBACK)
51 return false;
52
53 if (!link->network)
54 return false;
55
e0ee46f2 56 return link->network->dhcp & ADDRESS_FAMILY_IPV4;
78c958f8
TG
57}
58
a97dcc12 59bool link_dhcp4_server_enabled(Link *link) {
78c958f8
TG
60 if (link->flags & IFF_LOOPBACK)
61 return false;
62
63 if (!link->network)
64 return false;
65
66 return link->network->dhcp_server;
67}
68
a97dcc12 69bool link_ipv4ll_enabled(Link *link) {
78c958f8
TG
70 if (link->flags & IFF_LOOPBACK)
71 return false;
72
73 if (!link->network)
74 return false;
75
e0ee46f2 76 return link->network->link_local & ADDRESS_FAMILY_IPV4;
d0d6a4cd
TG
77}
78
79bool link_ipv6ll_enabled(Link *link) {
80 if (link->flags & IFF_LOOPBACK)
81 return false;
82
83 if (!link->network)
84 return false;
85
e0ee46f2 86 return link->network->link_local & ADDRESS_FAMILY_IPV6;
78c958f8
TG
87}
88
a97dcc12 89bool link_lldp_enabled(Link *link) {
ce43e484
SS
90 if (link->flags & IFF_LOOPBACK)
91 return false;
92
93 if (!link->network)
94 return false;
95
5a8bcb67 96 if (link->network->bridge)
ce43e484
SS
97 return false;
98
99 return link->network->lldp;
100}
101
769d324c 102static bool link_ipv4_forward_enabled(Link *link) {
5a8bcb67
LP
103 if (link->flags & IFF_LOOPBACK)
104 return false;
105
106 if (!link->network)
107 return false;
108
e0ee46f2 109 return link->network->ip_forward & ADDRESS_FAMILY_IPV4;
769d324c
LP
110}
111
112static bool link_ipv6_forward_enabled(Link *link) {
113 if (link->flags & IFF_LOOPBACK)
114 return false;
115
116 if (!link->network)
117 return false;
118
e0ee46f2 119 return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
5a8bcb67
LP
120}
121
1f0d9695 122static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
49092e22 123 if (link->flags & IFF_LOOPBACK)
1f0d9695 124 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
49092e22
SS
125
126 if (!link->network)
1f0d9695 127 return _IPV6_PRIVACY_EXTENSIONS_INVALID;
49092e22
SS
128
129 return link->network->ipv6_privacy_extensions;
130}
131
51d18171
TG
132#define FLAG_STRING(string, flag, old, new) \
133 (((old ^ new) & flag) \
134 ? ((old & flag) ? (" -" string) : (" +" string)) \
135 : "")
136
1c4baffc 137static int link_update_flags(Link *link, sd_netlink_message *m) {
51d18171
TG
138 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
139 uint8_t operstate;
140 int r;
141
142 assert(link);
143
144 r = sd_rtnl_message_link_get_flags(m, &flags);
6a7a4e4d
LP
145 if (r < 0)
146 return log_link_warning_errno(link, r, "Could not get link flags: %m");
51d18171 147
1c4baffc 148 r = sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &operstate);
51d18171
TG
149 if (r < 0)
150 /* if we got a message without operstate, take it to mean
151 the state was unchanged */
152 operstate = link->kernel_operstate;
153
154 if ((link->flags == flags) && (link->kernel_operstate == operstate))
155 return 0;
156
157 if (link->flags != flags) {
6a7a4e4d 158 log_link_debug(link, "Flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
51d18171
TG
159 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
160 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
161 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
162 FLAG_STRING("UP", IFF_UP, link->flags, flags),
163 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
164 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
165 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
166 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
167 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
168 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
169 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
170 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
171 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
172 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
173 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
174 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
175 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
176 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
177 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
178
179 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
180 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
181 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
182 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
183 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
184 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
185 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
186 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
187
188 /* link flags are currently at most 18 bits, let's align to
189 * printing 20 */
190 if (unknown_flags_added)
79008bdd 191 log_link_debug(link,
6a7a4e4d 192 "Unknown link flags gained: %#.5x (ignoring)",
51d18171
TG
193 unknown_flags_added);
194
195 if (unknown_flags_removed)
79008bdd 196 log_link_debug(link,
6a7a4e4d 197 "Unknown link flags lost: %#.5x (ignoring)",
51d18171
TG
198 unknown_flags_removed);
199 }
200
201 link->flags = flags;
202 link->kernel_operstate = operstate;
203
204 link_save(link);
205
206 return 0;
207}
208
1c4baffc 209static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
14b746f7 210 _cleanup_link_unref_ Link *link = NULL;
505f8da7 211 uint16_t type;
ca4e095a 212 const char *ifname;
505f8da7 213 int r, ifindex;
f579559b 214
0c2f9b84 215 assert(manager);
505f8da7 216 assert(message);
f579559b
TG
217 assert(ret);
218
1c4baffc 219 r = sd_netlink_message_get_type(message, &type);
505f8da7
TG
220 if (r < 0)
221 return r;
222 else if (type != RTM_NEWLINK)
223 return -EINVAL;
224
225 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
226 if (r < 0)
227 return r;
228 else if (ifindex <= 0)
229 return -EINVAL;
230
1c4baffc 231 r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
505f8da7
TG
232 if (r < 0)
233 return r;
234
f579559b
TG
235 link = new0(Link, 1);
236 if (!link)
237 return -ENOMEM;
238
14b746f7 239 link->n_ref = 1;
5a3eb5a7 240 link->manager = manager;
8434fd5c 241 link->state = LINK_STATE_PENDING;
be3a09b7 242 link->rtnl_extended_attrs = true;
505f8da7
TG
243 link->ifindex = ifindex;
244 link->ifname = strdup(ifname);
245 if (!link->ifname)
246 return -ENOMEM;
f579559b 247
1c4baffc 248 r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
512922f8 249 if (r < 0)
79008bdd 250 log_link_debug(link, "MAC address not found for new device, continuing without");
512922f8 251
3c9b8860
TG
252 r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
253 link->ifindex);
fe8db0c5 254 if (r < 0)
315db1a8 255 return -ENOMEM;
fe8db0c5 256
3c9b8860
TG
257 r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
258 link->ifindex);
68a8723c
TG
259 if (r < 0)
260 return -ENOMEM;
261
49699bac
SS
262 r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d",
263 link->ifindex);
264 if (r < 0)
265 return -ENOMEM;
266
267
d5099efc 268 r = hashmap_ensure_allocated(&manager->links, NULL);
ae06ab10
TG
269 if (r < 0)
270 return r;
271
272 r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
f579559b
TG
273 if (r < 0)
274 return r;
275
51d18171
TG
276 r = link_update_flags(link, message);
277 if (r < 0)
278 return r;
279
f579559b
TG
280 *ret = link;
281 link = NULL;
282
283 return 0;
284}
285
14b746f7 286static void link_free(Link *link) {
428fd0a7 287 Address *address;
0d4ad91d
AR
288 Iterator i;
289 Link *carrier;
428fd0a7 290
f579559b
TG
291 if (!link)
292 return;
293
428fd0a7
TG
294 while ((address = link->addresses)) {
295 LIST_REMOVE(addresses, link->addresses, address);
296 address_free(address);
297 }
298
11bf3cce
LP
299 while ((address = link->pool_addresses)) {
300 LIST_REMOVE(addresses, link->pool_addresses, address);
301 address_free(address);
302 }
303
bfcdba8d 304 sd_dhcp_server_unref(link->dhcp_server);
e5b04c8d 305 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 306 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 307
68a8723c
TG
308 free(link->lease_file);
309
07e10d1a
TG
310 sd_lldp_free(link->lldp);
311
49699bac
SS
312 free(link->lldp_file);
313
56cd007a 314 sd_ipv4ll_unref(link->ipv4ll);
4138fb2c 315 sd_dhcp6_client_unref(link->dhcp6_client);
6b66097b 316 sd_icmp6_nd_unref(link->icmp6_router_discovery);
4138fb2c 317
28aeb07f 318 if (link->manager)
ae06ab10 319 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
f579559b 320
c166a070 321 free(link->ifname);
68a8723c 322
fe8db0c5 323 free(link->state_file);
c166a070 324
b5db00e5
UTL
325 udev_device_unref(link->udev_device);
326
0d4ad91d
AR
327 HASHMAP_FOREACH (carrier, link->bound_to_links, i)
328 hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex));
329 hashmap_free(link->bound_to_links);
330
331 HASHMAP_FOREACH (carrier, link->bound_by_links, i)
332 hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
333 hashmap_free(link->bound_by_links);
334
f579559b
TG
335 free(link);
336}
337
14b746f7
TG
338Link *link_unref(Link *link) {
339 if (link && (-- link->n_ref <= 0))
340 link_free(link);
341
342 return NULL;
343}
344
345Link *link_ref(Link *link) {
346 if (link)
347 assert_se(++ link->n_ref >= 2);
348
349 return link;
350}
351
11a7f229
TG
352int link_get(Manager *m, int ifindex, Link **ret) {
353 Link *link;
11a7f229
TG
354
355 assert(m);
11a7f229
TG
356 assert(ifindex);
357 assert(ret);
358
ae06ab10 359 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
11a7f229
TG
360 if (!link)
361 return -ENODEV;
362
363 *ret = link;
364
365 return 0;
366}
367
e331e246
TG
368static void link_set_state(Link *link, LinkState state) {
369 assert(link);
370
371 if (link->state == state)
372 return;
373
374 link->state = state;
375
376 link_send_changed(link, "AdministrativeState", NULL);
377
378 return;
379}
380
57bd6899
TG
381static void link_enter_unmanaged(Link *link) {
382 assert(link);
383
6a7a4e4d 384 log_link_debug(link, "Unmanaged");
57bd6899 385
e331e246 386 link_set_state(link, LINK_STATE_UNMANAGED);
57bd6899
TG
387
388 link_save(link);
389}
390
111bb8f9
TG
391static int link_stop_clients(Link *link) {
392 int r = 0, k;
393
394 assert(link);
395 assert(link->manager);
396 assert(link->manager->event);
397
398 if (!link->network)
399 return 0;
400
ba179154 401 if (link->dhcp_client) {
111bb8f9 402 k = sd_dhcp_client_stop(link->dhcp_client);
6a7a4e4d
LP
403 if (k < 0)
404 r = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m");
111bb8f9
TG
405 }
406
ba179154 407 if (link->ipv4ll) {
111bb8f9 408 k = sd_ipv4ll_stop(link->ipv4ll);
6a7a4e4d
LP
409 if (k < 0)
410 r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
dd43110f
TG
411 }
412
ba179154 413 if(link->icmp6_router_discovery) {
1873a3d3
PF
414 if (link->dhcp6_client) {
415 k = sd_dhcp6_client_stop(link->dhcp6_client);
6a7a4e4d
LP
416 if (k < 0)
417 r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
1873a3d3 418 }
4138fb2c 419
1873a3d3 420 k = sd_icmp6_nd_stop(link->icmp6_router_discovery);
6a7a4e4d
LP
421 if (k < 0)
422 r = log_link_warning_errno(link, r, "Could not stop ICMPv6 router discovery: %m");
4138fb2c
PF
423 }
424
ce43e484 425 if (link->lldp) {
ce43e484 426 k = sd_lldp_stop(link->lldp);
6a7a4e4d
LP
427 if (k < 0)
428 r = log_link_warning_errno(link, r, "Could not stop LLDP: %m");
ce43e484
SS
429 }
430
111bb8f9
TG
431 return r;
432}
433
b22d8a00 434void link_enter_failed(Link *link) {
ef1ba606 435 assert(link);
f882c247 436
370e9930 437 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2139694e
TG
438 return;
439
6a7a4e4d 440 log_link_warning(link, "Failed");
449f7554 441
e331e246 442 link_set_state(link, LINK_STATE_FAILED);
fe8db0c5 443
111bb8f9
TG
444 link_stop_clients(link);
445
fe8db0c5 446 link_save(link);
f882c247
TG
447}
448
4f434938
LP
449static Address* link_find_dhcp_server_address(Link *link) {
450 Address *address;
451
452 assert(link);
453 assert(link->network);
454
d4cdbea5 455 /* The first statically configured address if there is any */
4f434938
LP
456 LIST_FOREACH(addresses, address, link->network->static_addresses) {
457
458 if (address->family != AF_INET)
459 continue;
460
af93291c 461 if (in_addr_is_null(address->family, &address->in_addr))
4f434938
LP
462 continue;
463
464 return address;
465 }
466
467 /* If that didn't work, find a suitable address we got from the pool */
468 LIST_FOREACH(addresses, address, link->pool_addresses) {
469 if (address->family != AF_INET)
470 continue;
471
472 return address;
473 }
474
475 return NULL;
476}
477
dd43110f 478static int link_enter_configured(Link *link) {
dd43110f
TG
479 assert(link);
480 assert(link->network);
481 assert(link->state == LINK_STATE_SETTING_ROUTES);
482
6a7a4e4d 483 log_link_info(link, "Configured");
dd43110f 484
e331e246 485 link_set_state(link, LINK_STATE_CONFIGURED);
dd43110f
TG
486
487 link_save(link);
488
489 return 0;
490}
491
3c9b8860
TG
492void link_client_handler(Link *link) {
493 assert(link);
494 assert(link->network);
495
496 if (!link->static_configured)
497 return;
498
78c958f8 499 if (link_ipv4ll_enabled(link))
3c9b8860
TG
500 if (!link->ipv4ll_address ||
501 !link->ipv4ll_route)
502 return;
503
78c958f8 504 if (link_dhcp4_enabled(link) && !link->dhcp4_configured)
3c9b8860
TG
505 return;
506
9fdaa992
TG
507 if (link->state != LINK_STATE_CONFIGURED)
508 link_enter_configured(link);
3c9b8860
TG
509
510 return;
511}
512
1c4baffc 513static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 514 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
515 int r;
516
3c9b8860 517 assert(link->link_messages > 0);
370e9930
TG
518 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
519 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
520 LINK_STATE_LINGER));
f882c247 521
3c9b8860 522 link->link_messages --;
f882c247 523
77a008c0 524 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
525 return 1;
526
1c4baffc 527 r = sd_netlink_message_get_errno(m);
c166a070 528 if (r < 0 && r != -EEXIST)
6a7a4e4d 529 log_link_warning_errno(link, r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname);
f882c247 530
3c9b8860 531 if (link->link_messages == 0) {
6a7a4e4d 532 log_link_debug(link, "Routes set");
3c9b8860
TG
533 link->static_configured = true;
534 link_client_handler(link);
dd3efc09 535 }
f882c247
TG
536
537 return 1;
538}
539
540static int link_enter_set_routes(Link *link) {
a6cc569e 541 Route *rt;
f882c247
TG
542 int r;
543
544 assert(link);
545 assert(link->network);
ef1ba606 546 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 547
e331e246 548 link_set_state(link, LINK_STATE_SETTING_ROUTES);
f882c247 549
3d3d4255 550 LIST_FOREACH(routes, rt, link->network->static_routes) {
a6cc569e 551 r = route_configure(rt, link, &route_handler);
dd3efc09 552 if (r < 0) {
6a7a4e4d 553 log_link_warning_errno(link, r, "Could not set routes: %m");
3c9b8860 554 link_enter_failed(link);
a6cc569e
TG
555 return r;
556 }
557
3c9b8860 558 link->link_messages ++;
8ddbeaa2 559 }
f5be5601 560
3c9b8860
TG
561 if (link->link_messages == 0) {
562 link->static_configured = true;
563 link_client_handler(link);
431ca2ce 564 } else
6a7a4e4d 565 log_link_debug(link, "Setting routes");
f882c247
TG
566
567 return 0;
568}
569
1c4baffc 570int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 571 _cleanup_link_unref_ Link *link = userdata;
5c1d3fc9
UTL
572 int r;
573
574 assert(m);
575 assert(link);
576 assert(link->ifname);
577
5da8149f 578 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c1d3fc9
UTL
579 return 1;
580
1c4baffc 581 r = sd_netlink_message_get_errno(m);
b90b025a 582 if (r < 0 && r != -ESRCH)
6a7a4e4d 583 log_link_warning_errno(link, r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname);
5c1d3fc9 584
5bdd314c 585 return 1;
5c1d3fc9
UTL
586}
587
1c4baffc 588static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 589 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
590 int r;
591
4958aee4 592 assert(rtnl);
f5be5601
TG
593 assert(m);
594 assert(link);
595 assert(link->ifname);
3c9b8860 596 assert(link->link_messages > 0);
370e9930
TG
597 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
598 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 599
3c9b8860 600 link->link_messages --;
f882c247 601
5da8149f 602 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
603 return 1;
604
1c4baffc 605 r = sd_netlink_message_get_errno(m);
c166a070 606 if (r < 0 && r != -EEXIST)
6a7a4e4d 607 log_link_warning_errno(link, r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname);
45af44d4
TG
608 else if (r >= 0)
609 link_rtnl_process_address(rtnl, m, link->manager);
f882c247 610
3c9b8860 611 if (link->link_messages == 0) {
6a7a4e4d 612 log_link_debug(link, "Addresses set");
ef1ba606 613 link_enter_set_routes(link);
dd3efc09 614 }
f882c247
TG
615
616 return 1;
617}
618
4f5f911e
LP
619static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
620 _cleanup_free_ struct in_addr *addresses = NULL;
621 size_t n_addresses = 0, n_allocated = 0;
622 char **a;
623
624 log_debug("Copying DNS server information from %s", link->ifname);
625
626 if (!link->network)
627 return 0;
628
629 STRV_FOREACH(a, link->network->dns) {
630 struct in_addr ia;
631
632 /* Only look for IPv4 addresses */
633 if (inet_pton(AF_INET, *a, &ia) <= 0)
634 continue;
635
636 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
637 return log_oom();
638
639 addresses[n_addresses++] = ia;
640 }
641
642 if (link->network->dhcp_dns &&
643 link->dhcp_lease) {
644 const struct in_addr *da = NULL;
645 int n;
646
647 n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da);
648 if (n > 0) {
649
650 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
651 return log_oom();
652
653 memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
654 n_addresses += n;
655 }
656 }
657
658 if (n_addresses <= 0)
659 return 0;
660
661 return sd_dhcp_server_set_dns(s, addresses, n_addresses);
662}
663
664static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
665 _cleanup_free_ struct in_addr *addresses = NULL;
666 size_t n_addresses = 0, n_allocated = 0;
667 char **a;
668
669 if (!link->network)
670 return 0;
671
672 log_debug("Copying NTP server information from %s", link->ifname);
673
674 STRV_FOREACH(a, link->network->ntp) {
675 struct in_addr ia;
676
677 /* Only look for IPv4 addresses */
678 if (inet_pton(AF_INET, *a, &ia) <= 0)
679 continue;
680
681 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
682 return log_oom();
683
684 addresses[n_addresses++] = ia;
685 }
686
687 if (link->network->dhcp_ntp &&
688 link->dhcp_lease) {
689 const struct in_addr *da = NULL;
690 int n;
691
692 n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da);
693 if (n > 0) {
694
695 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n))
696 return log_oom();
697
698 memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr));
699 n_addresses += n;
700 }
701 }
702
703 if (n_addresses <= 0)
704 return 0;
705
706 return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
707}
708
f882c247 709static int link_enter_set_addresses(Link *link) {
a6cc569e 710 Address *ad;
f882c247
TG
711 int r;
712
713 assert(link);
714 assert(link->network);
f5be5601 715 assert(link->state != _LINK_STATE_INVALID);
f882c247 716
e331e246 717 link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
f882c247 718
3d3d4255 719 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
a6cc569e 720 r = address_configure(ad, link, &address_handler);
dd3efc09 721 if (r < 0) {
5a8bcb67 722 log_link_warning_errno(link, r, "Could not set addresses: %m");
f5be5601
TG
723 link_enter_failed(link);
724 return r;
725 }
726
3c9b8860 727 link->link_messages ++;
f882c247
TG
728 }
729
d4cdbea5
TG
730 /* now that we can figure out a default address for the dhcp server,
731 start it */
732 if (link_dhcp4_server_enabled(link)) {
d4cdbea5 733 Address *address;
4f5f911e
LP
734 Link *uplink = NULL;
735 bool acquired_uplink = false;
d4cdbea5
TG
736
737 address = link_find_dhcp_server_address(link);
738 if (!address) {
6a7a4e4d 739 log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance.");
d4cdbea5
TG
740 link_enter_failed(link);
741 return 0;
742 }
743
61986155 744 /* use the server address' subnet as the pool */
9b3a67c5
TG
745 r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen,
746 link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size);
d4cdbea5
TG
747 if (r < 0)
748 return r;
749
750 /* TODO:
751 r = sd_dhcp_server_set_router(link->dhcp_server,
752 &main_address->in_addr.in);
753 if (r < 0)
754 return r;
d4cdbea5
TG
755 */
756
586ac6f7
LP
757 if (link->network->dhcp_server_max_lease_time_usec > 0) {
758 r = sd_dhcp_server_set_max_lease_time(
759 link->dhcp_server,
760 DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
761 if (r < 0)
762 return r;
763 }
764
765 if (link->network->dhcp_server_default_lease_time_usec > 0) {
766 r = sd_dhcp_server_set_default_lease_time(
767 link->dhcp_server,
768 DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
769 if (r < 0)
770 return r;
771 }
772
1a04db0f
LP
773 if (link->network->dhcp_server_emit_dns) {
774
4f5f911e 775 if (link->network->n_dhcp_server_dns > 0)
1a04db0f 776 r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
4f5f911e
LP
777 else {
778 uplink = manager_find_uplink(link->manager, link);
779 acquired_uplink = true;
780
781 if (!uplink) {
782 log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
783 r = 0;
784 } else
785 r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server);
786 }
787 if (r < 0)
788 log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
1a04db0f
LP
789 }
790
791
792 if (link->network->dhcp_server_emit_ntp) {
793
4f5f911e 794 if (link->network->n_dhcp_server_ntp > 0)
1a04db0f 795 r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
4f5f911e
LP
796 else {
797 if (!acquired_uplink)
798 uplink = manager_find_uplink(link->manager, link);
799
800 if (!uplink) {
801 log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
802 r = 0;
803 } else
804 r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server);
805
806 }
807 if (r < 0)
808 log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
1a04db0f
LP
809 }
810
8eb9058d
LP
811 if (link->network->dhcp_server_emit_timezone) {
812 _cleanup_free_ char *buffer = NULL;
0ab8a1b6 813 const char *tz = NULL;
8eb9058d
LP
814
815 if (link->network->dhcp_server_timezone)
816 tz = link->network->dhcp_server_timezone;
817 else {
818 r = get_timezone(&buffer);
819 if (r < 0)
820 log_warning_errno(r, "Failed to determine timezone: %m");
821 else
822 tz = buffer;
823 }
824
825 if (tz) {
826 r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
827 if (r < 0)
828 return r;
829 }
830 }
831
d4cdbea5
TG
832 r = sd_dhcp_server_start(link->dhcp_server);
833 if (r < 0) {
6a7a4e4d 834 log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
d4cdbea5
TG
835
836 link_enter_failed(link);
837
838 return 0;
839 }
840
6a7a4e4d 841 log_link_debug(link, "Offering DHCPv4 leases");
d4cdbea5
TG
842 }
843
6a7a4e4d 844 if (link->link_messages == 0)
431ca2ce 845 link_enter_set_routes(link);
6a7a4e4d
LP
846 else
847 log_link_debug(link, "Setting addresses");
431ca2ce 848
f882c247
TG
849 return 0;
850}
851
1c4baffc 852int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 853 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
854 int r;
855
856 assert(m);
857 assert(link);
858 assert(link->ifname);
859
5da8149f 860 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
861 return 1;
862
1c4baffc 863 r = sd_netlink_message_get_errno(m);
b90b025a 864 if (r < 0 && r != -EADDRNOTAVAIL)
6a7a4e4d 865 log_link_warning_errno(link, r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
ff254138 866
5bdd314c 867 return 1;
ff254138
TG
868}
869
a245ced0 870static int link_set_bridge_fdb(Link *const link) {
b98b483b
AR
871 FdbEntry *fdb_entry;
872 int r = 0;
873
874 LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
ea6ec096 875 r = fdb_entry_configure(link, fdb_entry);
b98b483b 876 if(r < 0) {
6a7a4e4d 877 log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
b98b483b
AR
878 break;
879 }
880 }
881
882 return r;
883}
884
1c4baffc 885static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
e1853b00
SS
886 _cleanup_link_unref_ Link *link = userdata;
887 int r;
888
6a7a4e4d 889 log_link_debug(link, "Set link");
e1853b00 890
1c4baffc 891 r = sd_netlink_message_get_errno(m);
e1853b00 892 if (r < 0 && r != -EEXIST) {
f2341e0a 893 log_link_error_errno(link, r, "Could not join netdev: %m");
e1853b00
SS
894 link_enter_failed(link);
895 return 1;
896 }
897
898 return 0;
899}
900
19070062 901static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
5da8149f 902 _cleanup_link_unref_ Link *link = userdata;
21b80ad1 903 const sd_bus_error *e;
1346b1f0 904
19070062 905 assert(m);
b226d99b
TG
906 assert(link);
907
5da8149f 908 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 909 return 1;
370e9930 910
21b80ad1
LP
911 e = sd_bus_message_get_error(m);
912 if (e)
913 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
1346b1f0
TG
914
915 return 1;
916}
917
3c9b8860 918int link_set_hostname(Link *link, const char *hostname) {
21b80ad1 919 int r;
1346b1f0 920
b226d99b
TG
921 assert(link);
922 assert(link->manager);
1346b1f0 923
dce391e7 924 log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));
1346b1f0 925
3c9b8860
TG
926 if (!link->manager->bus) {
927 /* TODO: replace by assert when we can rely on kdbus */
6a7a4e4d 928 log_link_info(link, "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
929 return 0;
930 }
931
9c34154a 932 r = sd_bus_call_method_async(
b226d99b 933 link->manager->bus,
9c34154a 934 NULL,
1346b1f0
TG
935 "org.freedesktop.hostname1",
936 "/org/freedesktop/hostname1",
937 "org.freedesktop.hostname1",
9c34154a
UTL
938 "SetHostname",
939 set_hostname_handler,
940 link,
941 "sb",
942 hostname,
943 false);
1346b1f0 944
6a7a4e4d
LP
945 if (r < 0)
946 return log_link_error_errno(link, r, "Could not set transient hostname: %m");
b226d99b
TG
947
948 link_ref(link);
1346b1f0 949
5da8149f 950 return 0;
1346b1f0
TG
951}
952
21b80ad1
LP
953static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
954 _cleanup_link_unref_ Link *link = userdata;
955 const sd_bus_error *e;
956
957 assert(m);
958 assert(link);
959
960 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
961 return 1;
962
963 e = sd_bus_message_get_error(m);
964 if (e)
965 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
966
967 return 1;
968}
969
64d6c229 970int link_set_timezone(Link *link, const char *tz) {
21b80ad1
LP
971 int r;
972
973 assert(link);
974 assert(link->manager);
64d6c229 975 assert(tz);
21b80ad1 976
64d6c229 977 log_link_debug(link, "Setting system timezone: '%s'", tz);
21b80ad1
LP
978
979 if (!link->manager->bus) {
980 log_link_info(link, "Not connected to system bus, ignoring timezone.");
981 return 0;
982 }
983
984 r = sd_bus_call_method_async(
985 link->manager->bus,
986 NULL,
987 "org.freedesktop.timedate1",
988 "/org/freedesktop/timedate1",
989 "org.freedesktop.timedate1",
990 "SetTimezone",
991 set_timezone_handler,
992 link,
993 "sb",
64d6c229 994 tz,
21b80ad1
LP
995 false);
996 if (r < 0)
997 return log_link_error_errno(link, r, "Could not set timezone: %m");
998
999 link_ref(link);
1000
1001 return 0;
1002}
1003
1c4baffc 1004static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1005 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
1006 int r;
1007
1008 assert(m);
1009 assert(link);
1010 assert(link->ifname);
1011
5da8149f 1012 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
1013 return 1;
1014
1c4baffc 1015 r = sd_netlink_message_get_errno(m);
c9ccc19f 1016 if (r < 0)
6a7a4e4d 1017 log_link_warning_errno(link, r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
4f882b2a
TG
1018
1019 return 1;
1020}
1021
3c9b8860 1022int link_set_mtu(Link *link, uint32_t mtu) {
1c4baffc 1023 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f882b2a
TG
1024 int r;
1025
1026 assert(link);
1027 assert(link->manager);
1028 assert(link->manager->rtnl);
1029
6a7a4e4d 1030 log_link_debug(link, "Setting MTU: %" PRIu32, mtu);
4f882b2a 1031
6a7a4e4d
LP
1032 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1033 if (r < 0)
1034 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
4f882b2a 1035
1c4baffc 1036 r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu);
6a7a4e4d
LP
1037 if (r < 0)
1038 return log_link_error_errno(link, r, "Could not append MTU: %m");
4f882b2a 1039
1c4baffc 1040 r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
6a7a4e4d
LP
1041 if (r < 0)
1042 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
4f882b2a 1043
ae941762 1044 link_ref(link);
b226d99b 1045
4f882b2a
TG
1046 return 0;
1047}
1048
e1853b00 1049static int link_set_bridge(Link *link) {
1c4baffc 1050 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
e1853b00
SS
1051 int r;
1052
1053 assert(link);
1054 assert(link->network);
1055
6a7a4e4d
LP
1056 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1057 if (r < 0)
1058 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
e1853b00
SS
1059
1060 r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
6a7a4e4d
LP
1061 if (r < 0)
1062 return log_link_error_errno(link, r, "Could not set message family: %m");
e1853b00 1063
1c4baffc 1064 r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
6a7a4e4d
LP
1065 if (r < 0)
1066 return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
e1853b00 1067
84c34096 1068 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
eb7ff4dd
SS
1069 if (r < 0)
1070 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
1071
1072 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
1073 if (r < 0)
1074 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
1075
1076 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
1077 if (r < 0)
1078 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
1079
23da66bb 1080 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
eb7ff4dd
SS
1081 if (r < 0)
1082 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
1083
1084 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
1085 if (r < 0)
1086 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
1087
e1853b00 1088 if(link->network->cost != 0) {
1c4baffc 1089 r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
6a7a4e4d
LP
1090 if (r < 0)
1091 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
e1853b00
SS
1092 }
1093
1c4baffc 1094 r = sd_netlink_message_close_container(req);
6a7a4e4d
LP
1095 if (r < 0)
1096 return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
e1853b00 1097
1c4baffc 1098 r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
6a7a4e4d
LP
1099 if (r < 0)
1100 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
e1853b00
SS
1101
1102 link_ref(link);
1103
1104 return r;
1105}
1106
49699bac
SS
1107static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
1108 Link *link = userdata;
1109 int r;
1110
1111 assert(link);
1112 assert(link->network);
1113 assert(link->manager);
1114
1115 if (event != UPDATE_INFO)
1116 return;
1117
1118 r = sd_lldp_save(link->lldp, link->lldp_file);
1119 if (r < 0)
6a7a4e4d 1120 log_link_warning_errno(link, r, "Could not save LLDP: %m");
49699bac
SS
1121
1122}
1123
ff254138
TG
1124static int link_acquire_conf(Link *link) {
1125 int r;
1126
1127 assert(link);
1128 assert(link->network);
ff254138
TG
1129 assert(link->manager);
1130 assert(link->manager->event);
1131
78c958f8 1132 if (link_ipv4ll_enabled(link)) {
eb34d4af 1133 assert(link->ipv4ll);
ff254138 1134
6a7a4e4d 1135 log_link_debug(link, "Acquiring IPv4 link-local address");
5c1d3fc9
UTL
1136
1137 r = sd_ipv4ll_start(link->ipv4ll);
6a7a4e4d
LP
1138 if (r < 0)
1139 return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
5c1d3fc9
UTL
1140 }
1141
78c958f8 1142 if (link_dhcp4_enabled(link)) {
eb34d4af 1143 assert(link->dhcp_client);
ff254138 1144
6a7a4e4d 1145 log_link_debug(link, "Acquiring DHCPv4 lease");
ab47d620 1146
5c1d3fc9 1147 r = sd_dhcp_client_start(link->dhcp_client);
6a7a4e4d
LP
1148 if (r < 0)
1149 return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
5c1d3fc9 1150 }
ff254138 1151
78c958f8 1152 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
1153 assert(link->icmp6_router_discovery);
1154
6a7a4e4d 1155 log_link_debug(link, "Discovering IPv6 routers");
4138fb2c
PF
1156
1157 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
6a7a4e4d
LP
1158 if (r < 0)
1159 return log_link_warning_errno(link, r, "Could not start IPv6 router discovery: %m");
4138fb2c
PF
1160 }
1161
ce43e484
SS
1162 if (link_lldp_enabled(link)) {
1163 assert(link->lldp);
1164
1165 log_link_debug(link, "Starting LLDP");
1166
1167 r = sd_lldp_start(link->lldp);
6a7a4e4d
LP
1168 if (r < 0)
1169 return log_link_warning_errno(link, r, "Could not start LLDP: %m");
ce43e484
SS
1170 }
1171
ff254138
TG
1172 return 0;
1173}
1174
a61bb41c 1175bool link_has_carrier(Link *link) {
deb2e523
TG
1176 /* see Documentation/networking/operstates.txt in the kernel sources */
1177
a61bb41c 1178 if (link->kernel_operstate == IF_OPER_UP)
deb2e523
TG
1179 return true;
1180
a61bb41c 1181 if (link->kernel_operstate == IF_OPER_UNKNOWN)
deb2e523 1182 /* operstate may not be implemented, so fall back to flags */
a61bb41c 1183 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
deb2e523
TG
1184 return true;
1185
1186 return false;
1187}
1188
1c4baffc 1189static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1190 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
1191 int r;
1192
1746cf2a
TG
1193 assert(link);
1194
5da8149f 1195 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
1196 return 1;
1197
1c4baffc 1198 r = sd_netlink_message_get_errno(m);
6a7a4e4d
LP
1199 if (r < 0)
1200 /* we warn but don't fail the link, as it may be
1201 brought up later */
1202 log_link_warning_errno(link, r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
45ad2c13 1203
f882c247
TG
1204 return 1;
1205}
1206
1207static int link_up(Link *link) {
1c4baffc 1208 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
5c3072ea 1209 uint8_t ipv6ll_mode;
f579559b
TG
1210 int r;
1211
f882c247 1212 assert(link);
c106cc36 1213 assert(link->network);
f882c247
TG
1214 assert(link->manager);
1215 assert(link->manager->rtnl);
1216
6a7a4e4d 1217 log_link_debug(link, "Bringing link up");
449f7554 1218
6a7a4e4d
LP
1219 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1220 if (r < 0)
1221 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
f579559b 1222
5d4795f3 1223 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
6a7a4e4d
LP
1224 if (r < 0)
1225 return log_link_error_errno(link, r, "Could not set link flags: %m");
fc25d7f8 1226
c106cc36 1227 if (link->network->mac) {
1c4baffc 1228 r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
6a7a4e4d
LP
1229 if (r < 0)
1230 return log_link_error_errno(link, r, "Could not set MAC address: %m");
c106cc36
TG
1231 }
1232
1233 if (link->network->mtu) {
1c4baffc 1234 r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
6a7a4e4d
LP
1235 if (r < 0)
1236 return log_link_error_errno(link, r, "Could not set MTU: %m");
c106cc36
TG
1237 }
1238
1c4baffc 1239 r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
6a7a4e4d
LP
1240 if (r < 0)
1241 return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
d0d6a4cd 1242
01d28f81
TG
1243 if (socket_ipv6_is_supported()) {
1244 /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
1c4baffc 1245 r = sd_netlink_message_open_container(req, AF_INET6);
01d28f81
TG
1246 if (r < 0)
1247 return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
d0d6a4cd 1248
01d28f81 1249 ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE;
1c4baffc 1250 r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
01d28f81
TG
1251 if (r < 0)
1252 return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
d0d6a4cd 1253
01d28f81 1254 if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
1c4baffc 1255 r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
01d28f81
TG
1256 if (r < 0)
1257 return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
1258 }
1259
1c4baffc 1260 r = sd_netlink_message_close_container(req);
6a7a4e4d 1261 if (r < 0)
01d28f81 1262 return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
7f77697a 1263 }
d0d6a4cd 1264
1c4baffc 1265 r = sd_netlink_message_close_container(req);
6a7a4e4d
LP
1266 if (r < 0)
1267 return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
d0d6a4cd 1268
1c4baffc 1269 r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
6a7a4e4d
LP
1270 if (r < 0)
1271 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
f579559b 1272
b226d99b
TG
1273 link_ref(link);
1274
f882c247
TG
1275 return 0;
1276}
1277
1c4baffc 1278static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
0d4ad91d
AR
1279 _cleanup_link_unref_ Link *link = userdata;
1280 int r;
1281
1282 assert(link);
1283
1284 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1285 return 1;
1286
1c4baffc 1287 r = sd_netlink_message_get_errno(m);
0d4ad91d 1288 if (r < 0)
6a7a4e4d 1289 log_link_warning_errno(link, r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname);
0d4ad91d
AR
1290
1291 return 1;
1292}
1293
1294static int link_down(Link *link) {
1c4baffc 1295 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
0d4ad91d
AR
1296 int r;
1297
1298 assert(link);
1299 assert(link->manager);
1300 assert(link->manager->rtnl);
1301
6a7a4e4d 1302 log_link_debug(link, "Bringing link down");
0d4ad91d
AR
1303
1304 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1305 RTM_SETLINK, link->ifindex);
6a7a4e4d
LP
1306 if (r < 0)
1307 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
0d4ad91d
AR
1308
1309 r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
6a7a4e4d
LP
1310 if (r < 0)
1311 return log_link_error_errno(link, r, "Could not set link flags: %m");
0d4ad91d 1312
1c4baffc 1313 r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL);
6a7a4e4d
LP
1314 if (r < 0)
1315 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
0d4ad91d
AR
1316
1317 link_ref(link);
1318
1319 return 0;
1320}
1321
1322static int link_handle_bound_to_list(Link *link) {
1323 Link *l;
1324 Iterator i;
1325 int r;
1326 bool required_up = false;
1327 bool link_is_up = false;
1328
1329 assert(link);
1330
1331 if (hashmap_isempty(link->bound_to_links))
1332 return 0;
1333
1334 if (link->flags & IFF_UP)
1335 link_is_up = true;
1336
1337 HASHMAP_FOREACH (l, link->bound_to_links, i)
1338 if (link_has_carrier(l)) {
1339 required_up = true;
1340 break;
1341 }
1342
1343 if (!required_up && link_is_up) {
1344 r = link_down(link);
1345 if (r < 0)
1346 return r;
1347 } else if (required_up && !link_is_up) {
1348 r = link_up(link);
1349 if (r < 0)
1350 return r;
1351 }
1352
1353 return 0;
1354}
1355
1356static int link_handle_bound_by_list(Link *link) {
1357 Iterator i;
1358 Link *l;
1359 int r;
1360
1361 assert(link);
1362
1363 if (hashmap_isempty(link->bound_by_links))
1364 return 0;
1365
1366 HASHMAP_FOREACH (l, link->bound_by_links, i) {
1367 r = link_handle_bound_to_list(l);
1368 if (r < 0)
1369 return r;
1370 }
1371
1372 return 0;
1373}
1374
1375static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) {
1376 int r;
1377
1378 assert(link);
1379 assert(carrier);
1380
1381 if (link == carrier)
1382 return 0;
1383
1384 if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex)))
1385 return 0;
1386
1387 r = hashmap_ensure_allocated(h, NULL);
1388 if (r < 0)
1389 return r;
1390
1391 r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier);
1392 if (r < 0)
1393 return r;
1394
1395 return 0;
1396}
1397
1398static int link_new_bound_by_list(Link *link) {
1399 Manager *m;
1400 Link *carrier;
1401 Iterator i;
1402 int r;
1403 bool list_updated = false;
1404
1405 assert(link);
1406 assert(link->manager);
1407
1408 m = link->manager;
1409
1410 HASHMAP_FOREACH (carrier, m->links, i) {
1411 if (!carrier->network)
1412 continue;
1413
1414 if (strv_isempty(carrier->network->bind_carrier))
1415 continue;
1416
1417 if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) {
1418 r = link_put_carrier(link, carrier, &link->bound_by_links);
1419 if (r < 0)
1420 return r;
1421
1422 list_updated = true;
1423 }
1424 }
1425
1426 if (list_updated)
1427 link_save(link);
1428
1429 HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
1430 r = link_put_carrier(carrier, link, &carrier->bound_to_links);
1431 if (r < 0)
1432 return r;
1433
1434 link_save(carrier);
1435 }
1436
1437 return 0;
1438}
1439
1440static int link_new_bound_to_list(Link *link) {
1441 Manager *m;
1442 Link *carrier;
1443 Iterator i;
1444 int r;
1445 bool list_updated = false;
1446
1447 assert(link);
1448 assert(link->manager);
1449
1450 if (!link->network)
1451 return 0;
1452
1453 if (strv_isempty(link->network->bind_carrier))
1454 return 0;
1455
1456 m = link->manager;
1457
1458 HASHMAP_FOREACH (carrier, m->links, i) {
1459 if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) {
1460 r = link_put_carrier(link, carrier, &link->bound_to_links);
1461 if (r < 0)
1462 return r;
1463
1464 list_updated = true;
1465 }
1466 }
1467
1468 if (list_updated)
1469 link_save(link);
1470
1471 HASHMAP_FOREACH (carrier, link->bound_to_links, i) {
1472 r = link_put_carrier(carrier, link, &carrier->bound_by_links);
1473 if (r < 0)
1474 return r;
1475
1476 link_save(carrier);
1477 }
1478
1479 return 0;
1480}
1481
1482static int link_new_carrier_maps(Link *link) {
1483 int r;
1484
1485 r = link_new_bound_by_list(link);
1486 if (r < 0)
1487 return r;
1488
1489 r = link_handle_bound_by_list(link);
1490 if (r < 0)
1491 return r;
1492
1493 r = link_new_bound_to_list(link);
1494 if (r < 0)
1495 return r;
1496
1497 r = link_handle_bound_to_list(link);
1498 if (r < 0)
1499 return r;
1500
1501 return 0;
1502}
1503
1504static void link_free_bound_to_list(Link *link) {
1505 Link *bound_to;
1506 Iterator i;
1507
1508 HASHMAP_FOREACH (bound_to, link->bound_to_links, i) {
1509 hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex));
1510
1511 if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex)))
1512 link_save(bound_to);
1513 }
1514
1515 return;
1516}
1517
1518static void link_free_bound_by_list(Link *link) {
1519 Link *bound_by;
1520 Iterator i;
1521
1522 HASHMAP_FOREACH (bound_by, link->bound_by_links, i) {
1523 hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex));
1524
1525 if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) {
1526 link_save(bound_by);
1527 link_handle_bound_to_list(bound_by);
1528 }
1529 }
1530
1531 return;
1532}
1533
1534static void link_free_carrier_maps(Link *link) {
1535 bool list_updated = false;
1536
1537 assert(link);
1538
1539 if (!hashmap_isempty(link->bound_to_links)) {
1540 link_free_bound_to_list(link);
1541 list_updated = true;
1542 }
1543
1544 if (!hashmap_isempty(link->bound_by_links)) {
1545 link_free_bound_by_list(link);
1546 list_updated = true;
1547 }
1548
1549 if (list_updated)
1550 link_save(link);
1551
1552 return;
1553}
1554
1555void link_drop(Link *link) {
1556 if (!link || link->state == LINK_STATE_LINGER)
1557 return;
1558
1559 link_set_state(link, LINK_STATE_LINGER);
1560
1561 link_free_carrier_maps(link);
1562
6a7a4e4d 1563 log_link_debug(link, "Link removed");
0d4ad91d
AR
1564
1565 link_unref(link);
1566
1567 return;
1568}
1569
3f265037 1570static int link_joined(Link *link) {
f882c247
TG
1571 int r;
1572
ef1ba606 1573 assert(link);
f5be5601 1574 assert(link->network);
dd3efc09 1575
0d4ad91d
AR
1576 if (!hashmap_isempty(link->bound_to_links)) {
1577 r = link_handle_bound_to_list(link);
1578 if (r < 0)
1579 return r;
1580 } else if (!(link->flags & IFF_UP)) {
505f8da7
TG
1581 r = link_up(link);
1582 if (r < 0) {
1583 link_enter_failed(link);
1584 return r;
1585 }
ef1ba606 1586 }
f882c247 1587
e1853b00
SS
1588 if(link->network->bridge) {
1589 r = link_set_bridge(link);
6a7a4e4d
LP
1590 if (r < 0)
1591 log_link_error_errno(link, r, "Could not set bridge message: %m");
e1853b00
SS
1592 }
1593
fb6730c4 1594 return link_enter_set_addresses(link);
02b59d57
TG
1595}
1596
62e2d5bb 1597static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1598 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1599 int r;
1600
1746cf2a 1601 assert(link);
ef1ba606 1602 assert(link->network);
02b59d57 1603
52433f6b
TG
1604 link->enslaving --;
1605
5da8149f 1606 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1607 return 1;
1608
1c4baffc 1609 r = sd_netlink_message_get_errno(m);
856f962c 1610 if (r < 0 && r != -EEXIST) {
6a7a4e4d 1611 log_link_error_errno(link, r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
ef1ba606
TG
1612 link_enter_failed(link);
1613 return 1;
ba179154 1614 } else
6a7a4e4d 1615 log_link_debug(link, "Joined netdev");
02b59d57 1616
856f962c 1617 if (link->enslaving <= 0)
3f265037 1618 link_joined(link);
02b59d57
TG
1619
1620 return 1;
1621}
1622
3f265037 1623static int link_enter_join_netdev(Link *link) {
6a0a2f86 1624 NetDev *netdev;
672682a6 1625 Iterator i;
02b59d57
TG
1626 int r;
1627
1628 assert(link);
1629 assert(link->network);
8434fd5c 1630 assert(link->state == LINK_STATE_PENDING);
02b59d57 1631
e331e246 1632 link_set_state(link, LINK_STATE_ENSLAVING);
02b59d57 1633
fe8db0c5
TG
1634 link_save(link);
1635
7951dea2
SS
1636 if (!link->network->bridge &&
1637 !link->network->bond &&
6a0a2f86 1638 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1639 return link_joined(link);
02b59d57 1640
d9c67ea1 1641 if (link->network->bond) {
f2341e0a
LP
1642 log_struct(LOG_DEBUG,
1643 LOG_LINK_INTERFACE(link),
1644 LOG_NETDEV_INTERFACE(link->network->bond),
1645 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname),
1646 NULL);
1647
1648 r = netdev_join(link->network->bond, link, netdev_join_handler);
52433f6b 1649 if (r < 0) {
f2341e0a
LP
1650 log_struct_errno(LOG_WARNING, r,
1651 LOG_LINK_INTERFACE(link),
1652 LOG_NETDEV_INTERFACE(link->network->bond),
1653 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname),
1654 NULL);
1655
52433f6b
TG
1656 link_enter_failed(link);
1657 return r;
1658 }
1659
0ad6148e
MO
1660 link->enslaving ++;
1661 }
1662
d9c67ea1 1663 if (link->network->bridge) {
f2341e0a
LP
1664 log_struct(LOG_DEBUG,
1665 LOG_LINK_INTERFACE(link),
1666 LOG_NETDEV_INTERFACE(link->network->bridge),
1667 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname),
1668 NULL);
1669
1670 r = netdev_join(link->network->bridge, link, netdev_join_handler);
0ad6148e 1671 if (r < 0) {
f2341e0a
LP
1672 log_struct_errno(LOG_WARNING, r,
1673 LOG_LINK_INTERFACE(link),
1674 LOG_NETDEV_INTERFACE(link->network->bridge),
1675 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname),
1676 NULL),
0ad6148e
MO
1677 link_enter_failed(link);
1678 return r;
1679 }
1680
52433f6b
TG
1681 link->enslaving ++;
1682 }
1683
6a0a2f86 1684 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
7951dea2 1685
f2341e0a
LP
1686 log_struct(LOG_DEBUG,
1687 LOG_LINK_INTERFACE(link),
1688 LOG_NETDEV_INTERFACE(netdev),
1689 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname),
1690 NULL);
1691
1692 r = netdev_join(netdev, link, netdev_join_handler);
7951dea2 1693 if (r < 0) {
f2341e0a
LP
1694 log_struct_errno(LOG_WARNING, r,
1695 LOG_LINK_INTERFACE(link),
1696 LOG_NETDEV_INTERFACE(netdev),
1697 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname),
1698 NULL);
326cb406
SS
1699 link_enter_failed(link);
1700 return r;
1701 }
1702
326cb406
SS
1703 link->enslaving ++;
1704 }
1705
ef1ba606
TG
1706 return 0;
1707}
1708
769d324c 1709static int link_set_ipv4_forward(Link *link) {
15dee3f0 1710 const char *p = NULL, *v;
5a8bcb67
LP
1711 int r;
1712
15dee3f0
LP
1713 if (link->flags & IFF_LOOPBACK)
1714 return 0;
1715
8add5f79
NO
1716 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1717 return 0;
1718
63c372cb 1719 p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1720 v = one_zero(link_ipv4_forward_enabled(link));
1721
4c1fc3e4 1722 r = write_string_file(p, v, 0);
15dee3f0
LP
1723 if (r < 0) {
1724 /* If the right value is set anyway, don't complain */
1725 if (verify_one_line_file(p, v) > 0)
1726 return 0;
1727
43c6d5ab 1728 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
15dee3f0 1729 }
43c6d5ab 1730
769d324c
LP
1731 return 0;
1732}
1733
1734static int link_set_ipv6_forward(Link *link) {
15dee3f0 1735 const char *p = NULL, *v = NULL;
769d324c
LP
1736 int r;
1737
fe027299
LP
1738 /* Make this a NOP if IPv6 is not available */
1739 if (!socket_ipv6_is_supported())
1740 return 0;
1741
15dee3f0
LP
1742 if (link->flags & IFF_LOOPBACK)
1743 return 0;
1744
8add5f79
NO
1745 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1746 return 0;
1747
63c372cb 1748 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1749 v = one_zero(link_ipv6_forward_enabled(link));
1750
4c1fc3e4 1751 r = write_string_file(p, v, 0);
15dee3f0
LP
1752 if (r < 0) {
1753 /* If the right value is set anyway, don't complain */
1754 if (verify_one_line_file(p, v) > 0)
1755 return 0;
1756
769d324c 1757 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
15dee3f0 1758 }
5a8bcb67
LP
1759
1760 return 0;
1761}
1762
49092e22 1763static int link_set_ipv6_privacy_extensions(Link *link) {
1f0d9695
LP
1764 char buf[DECIMAL_STR_MAX(unsigned) + 1];
1765 IPv6PrivacyExtensions s;
49092e22
SS
1766 const char *p = NULL;
1767 int r;
1768
1769 /* Make this a NOP if IPv6 is not available */
1770 if (!socket_ipv6_is_supported())
1771 return 0;
1772
1f0d9695
LP
1773 s = link_ipv6_privacy_extensions(link);
1774 if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID)
49092e22
SS
1775 return 0;
1776
1777 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
1778 xsprintf(buf, "%u", link->network->ipv6_privacy_extensions);
1779
4c1fc3e4 1780 r = write_string_file(p, buf, 0);
1f0d9695
LP
1781 if (r < 0) {
1782 /* If the right value is set anyway, don't complain */
1783 if (verify_one_line_file(p, buf) > 0)
1784 return 0;
1785
49092e22 1786 log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
1f0d9695 1787 }
49092e22
SS
1788
1789 return 0;
1790}
1791
a748b692 1792static int link_configure(Link *link) {
02b59d57
TG
1793 int r;
1794
ef1ba606 1795 assert(link);
b22d8a00 1796 assert(link->network);
8434fd5c 1797 assert(link->state == LINK_STATE_PENDING);
a748b692 1798
b98b483b
AR
1799 r = link_set_bridge_fdb(link);
1800 if (r < 0)
1801 return r;
1802
769d324c
LP
1803 r = link_set_ipv4_forward(link);
1804 if (r < 0)
1805 return r;
1806
1807 r = link_set_ipv6_forward(link);
5a8bcb67
LP
1808 if (r < 0)
1809 return r;
1810
49092e22
SS
1811 r = link_set_ipv6_privacy_extensions(link);
1812 if (r < 0)
1813 return r;
1814
78c958f8 1815 if (link_ipv4ll_enabled(link)) {
b22d8a00 1816 r = ipv4ll_configure(link);
eb34d4af
TG
1817 if (r < 0)
1818 return r;
1819 }
1820
78c958f8 1821 if (link_dhcp4_enabled(link)) {
3c9b8860 1822 r = dhcp4_configure(link);
eb34d4af
TG
1823 if (r < 0)
1824 return r;
eb34d4af
TG
1825 }
1826
78c958f8 1827 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1828 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1829 if (r < 0)
1830 return r;
1831
1832 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1833 if (r < 0)
1834 return r;
dd43110f
TG
1835 }
1836
78c958f8 1837 if (link_dhcp6_enabled(link)) {
5c79bd79 1838 r = icmp6_configure(link);
4138fb2c
PF
1839 if (r < 0)
1840 return r;
1841 }
1842
ce43e484
SS
1843 if (link_lldp_enabled(link)) {
1844 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
1845 if (r < 0)
1846 return r;
1847
1848 r = sd_lldp_attach_event(link->lldp, NULL, 0);
1849 if (r < 0)
1850 return r;
49699bac
SS
1851
1852 r = sd_lldp_set_callback(link->lldp,
1853 lldp_handler, link);
1854 if (r < 0)
1855 return r;
ce43e484
SS
1856 }
1857
a61bb41c 1858 if (link_has_carrier(link)) {
1e9be60b
TG
1859 r = link_acquire_conf(link);
1860 if (r < 0)
1861 return r;
cc544d5f 1862 }
1e9be60b 1863
3f265037 1864 return link_enter_join_netdev(link);
505f8da7
TG
1865}
1866
1c4baffc 1867static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
3c9b8860 1868 void *userdata) {
5da8149f 1869 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1870 Network *network;
505f8da7
TG
1871 int r;
1872
1873 assert(link);
1874 assert(link->ifname);
1875 assert(link->manager);
1876
8434fd5c 1877 if (link->state != LINK_STATE_PENDING)
5da8149f 1878 return 1;
505f8da7 1879
6a7a4e4d 1880 log_link_debug(link, "Link state is up-to-date");
505f8da7 1881
0d4ad91d
AR
1882 r = link_new_bound_by_list(link);
1883 if (r < 0)
1884 return r;
1885
1886 r = link_handle_bound_by_list(link);
1887 if (r < 0)
1888 return r;
1889
3c9b8860
TG
1890 r = network_get(link->manager, link->udev_device, link->ifname,
1891 &link->mac, &network);
57bd6899
TG
1892 if (r == -ENOENT) {
1893 link_enter_unmanaged(link);
5da8149f 1894 return 1;
57bd6899
TG
1895 } else if (r < 0)
1896 return r;
505f8da7 1897
bd2efe92 1898 if (link->flags & IFF_LOOPBACK) {
d0d6a4cd 1899 if (network->link_local != ADDRESS_FAMILY_NO)
6a7a4e4d 1900 log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
78c958f8 1901
cb9fc36a 1902 if (network->dhcp != ADDRESS_FAMILY_NO)
6a7a4e4d 1903 log_link_debug(link, "Ignoring DHCP clients for loopback link");
78c958f8
TG
1904
1905 if (network->dhcp_server)
6a7a4e4d 1906 log_link_debug(link, "Ignoring DHCP server for loopback link");
bd2efe92
TG
1907 }
1908
505f8da7
TG
1909 r = network_apply(link->manager, network, link);
1910 if (r < 0)
1911 return r;
1912
0d4ad91d
AR
1913 r = link_new_bound_to_list(link);
1914 if (r < 0)
1915 return r;
1916
a748b692
TG
1917 r = link_configure(link);
1918 if (r < 0)
1919 return r;
1920
5da8149f 1921 return 1;
505f8da7
TG
1922}
1923
4f561e8e 1924int link_initialized(Link *link, struct udev_device *device) {
1c4baffc 1925 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f561e8e
TG
1926 int r;
1927
1928 assert(link);
1929 assert(link->manager);
1930 assert(link->manager->rtnl);
1931 assert(device);
1932
8434fd5c 1933 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1934 return 0;
1935
679b3605
TG
1936 if (link->udev_device)
1937 return 0;
1938
79008bdd 1939 log_link_debug(link, "udev initialized link");
4f561e8e
TG
1940
1941 link->udev_device = udev_device_ref(device);
1942
3c9b8860
TG
1943 /* udev has initialized the link, but we don't know if we have yet
1944 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1945 * when it returns we know that the pending NEWLINKs have already been
1946 * processed and that we are up-to-date */
4f561e8e 1947
3c9b8860
TG
1948 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1949 link->ifindex);
4f561e8e
TG
1950 if (r < 0)
1951 return r;
1952
1c4baffc 1953 r = sd_netlink_call_async(link->manager->rtnl, req,
3c9b8860 1954 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1955 if (r < 0)
1956 return r;
1957
5da8149f
TG
1958 link_ref(link);
1959
4f561e8e
TG
1960 return 0;
1961}
1962
5a8bcb67
LP
1963static Address* link_get_equal_address(Link *link, Address *needle) {
1964 Address *i;
1965
1966 assert(link);
1967 assert(needle);
1968
1969 LIST_FOREACH(addresses, i, link->addresses)
1970 if (address_equal(i, needle))
1971 return i;
1972
1973 return NULL;
1974}
1975
1c4baffc 1976int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
fbbeb65a
TG
1977 Manager *m = userdata;
1978 Link *link = NULL;
1979 uint16_t type;
1980 _cleanup_address_free_ Address *address = NULL;
851c9f82 1981 unsigned char flags;
5a8bcb67
LP
1982 Address *existing;
1983 char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
c6d3b303 1984 const char *valid_str = NULL;
fbbeb65a
TG
1985 int r, ifindex;
1986
1987 assert(rtnl);
1988 assert(message);
1989 assert(m);
1990
1c4baffc
TG
1991 if (sd_netlink_message_is_error(message)) {
1992 r = sd_netlink_message_get_errno(message);
45af44d4
TG
1993 if (r < 0)
1994 log_warning_errno(r, "rtnl: failed to receive address: %m");
1995
1996 return 0;
1997 }
1998
1c4baffc 1999 r = sd_netlink_message_get_type(message, &type);
fbbeb65a 2000 if (r < 0) {
6a7a4e4d 2001 log_warning_errno(r, "rtnl: could not get message type: %m");
fbbeb65a 2002 return 0;
cdfee943
TG
2003 } else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
2004 log_warning("rtnl: received unexpected message type when processing address");
2005 return 0;
fbbeb65a
TG
2006 }
2007
2008 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
45af44d4 2009 if (r < 0) {
cdfee943 2010 log_warning_errno(r, "rtnl: could not get ifindex from address: %m");
45af44d4
TG
2011 return 0;
2012 } else if (ifindex <= 0) {
2013 log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
fbbeb65a
TG
2014 return 0;
2015 } else {
2016 r = link_get(m, ifindex, &link);
2017 if (r < 0 || !link) {
6a24f148
TG
2018 /* when enumerating we might be out of sync, but we will
2019 * get the address again, so just ignore it */
2020 if (!m->enumerating)
2021 log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
fbbeb65a
TG
2022 return 0;
2023 }
2024 }
2025
2026 r = address_new_dynamic(&address);
2027 if (r < 0)
393c0c5e 2028 return r;
fbbeb65a
TG
2029
2030 r = sd_rtnl_message_addr_get_family(message, &address->family);
2031 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
6a7a4e4d 2032 log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
fbbeb65a
TG
2033 return 0;
2034 }
2035
2036 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
2037 if (r < 0) {
6a7a4e4d 2038 log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
e375dcde
TG
2039 return 0;
2040 }
2041
2042 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
2043 if (r < 0) {
6a7a4e4d 2044 log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
fbbeb65a
TG
2045 return 0;
2046 }
2047
851c9f82 2048 r = sd_rtnl_message_addr_get_flags(message, &flags);
81163121 2049 if (r < 0) {
6a7a4e4d 2050 log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
81163121
TG
2051 return 0;
2052 }
851c9f82 2053 address->flags = flags;
81163121 2054
fbbeb65a
TG
2055 switch (address->family) {
2056 case AF_INET:
1c4baffc 2057 r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
fbbeb65a 2058 if (r < 0) {
6a7a4e4d 2059 log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
fbbeb65a
TG
2060 return 0;
2061 }
2062
2063 break;
2064
2065 case AF_INET6:
1c4baffc 2066 r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
fbbeb65a 2067 if (r < 0) {
6a7a4e4d 2068 log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
fbbeb65a
TG
2069 return 0;
2070 }
2071
2072 break;
2073
2074 default:
2075 assert_not_reached("invalid address family");
2076 }
2077
5a8bcb67 2078 if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
6a7a4e4d 2079 log_link_warning(link, "Could not print address");
fbbeb65a
TG
2080 return 0;
2081 }
2082
1c4baffc 2083 r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
c6d3b303
TG
2084 if (r >= 0) {
2085 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
2086 valid_str = "ever";
2087 else
2088 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
2089 address->cinfo.ifa_valid * USEC_PER_SEC,
2090 USEC_PER_SEC);
2091 }
2092
5a8bcb67
LP
2093 existing = link_get_equal_address(link, address);
2094
2095 switch (type) {
2096 case RTM_NEWADDR:
2097 if (existing) {
2098 log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 2099
428fd0a7 2100
5a8bcb67
LP
2101 existing->scope = address->scope;
2102 existing->flags = address->flags;
2103 existing->cinfo = address->cinfo;
428fd0a7 2104
5a8bcb67
LP
2105 } else {
2106 log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 2107
5a8bcb67
LP
2108 LIST_PREPEND(addresses, link->addresses, address);
2109 address_establish(address, link);
fbbeb65a 2110
5a8bcb67 2111 address = NULL;
428fd0a7 2112
5a8bcb67
LP
2113 link_save(link);
2114 }
f5602be9 2115
428fd0a7 2116 break;
5a8bcb67 2117
fbbeb65a 2118 case RTM_DELADDR:
428fd0a7 2119
5a8bcb67
LP
2120 if (existing) {
2121 log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
2122 address_release(existing, link);
2123 LIST_REMOVE(addresses, link->addresses, existing);
2124 address_free(existing);
393c0c5e 2125 } else
5a8bcb67 2126 log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
f5602be9 2127
fbbeb65a
TG
2128 break;
2129 default:
2130 assert_not_reached("Received invalid RTNL message type");
2131 }
2132
2133 return 1;
2134}
2135
1c4baffc 2136int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
505f8da7
TG
2137 Link *link;
2138 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
2139 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
2140 int r;
2141
2142 assert(m);
fbbeb65a 2143 assert(m->rtnl);
505f8da7
TG
2144 assert(message);
2145 assert(ret);
2146
2147 r = link_new(m, message, ret);
2148 if (r < 0)
2149 return r;
2150
2151 link = *ret;
2152
6a7a4e4d 2153 log_link_debug(link, "Link %d added", link->ifindex);
505f8da7 2154
75f86906 2155 if (detect_container() <= 0) {
505f8da7 2156 /* not in a container, udev will be around */
ae06ab10 2157 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7 2158 device = udev_device_new_from_device_id(m->udev, ifindex_str);
6a7a4e4d
LP
2159 if (!device)
2160 return log_link_warning_errno(link, errno, "Could not find udev device: %m");
505f8da7 2161
3c4cb064 2162 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 2163 /* not yet ready */
79008bdd 2164 log_link_debug(link, "link pending udev initialization...");
505f8da7 2165 return 0;
3c4cb064 2166 }
505f8da7 2167
4f561e8e
TG
2168 r = link_initialized(link, device);
2169 if (r < 0)
2170 return r;
2171 } else {
5da8149f
TG
2172 /* we are calling a callback directly, so must take a ref */
2173 link_ref(link);
2174
4f561e8e
TG
2175 r = link_initialized_and_synced(m->rtnl, NULL, link);
2176 if (r < 0)
2177 return r;
2178 }
505f8da7 2179
a748b692
TG
2180 return 0;
2181}
2182
9c0a72f9
TG
2183static int link_carrier_gained(Link *link) {
2184 int r;
2185
2186 assert(link);
2187
2188 if (link->network) {
2189 r = link_acquire_conf(link);
2190 if (r < 0) {
2191 link_enter_failed(link);
2192 return r;
2193 }
2194 }
2195
0d4ad91d
AR
2196 r = link_handle_bound_by_list(link);
2197 if (r < 0)
2198 return r;
2199
9c0a72f9
TG
2200 return 0;
2201}
2202
2203static int link_carrier_lost(Link *link) {
2204 int r;
2205
2206 assert(link);
2207
2208 r = link_stop_clients(link);
2209 if (r < 0) {
2210 link_enter_failed(link);
2211 return r;
2212 }
2213
0d4ad91d
AR
2214 r = link_handle_bound_by_list(link);
2215 if (r < 0)
2216 return r;
2217
9c0a72f9
TG
2218 return 0;
2219}
2220
2221int link_carrier_reset(Link *link) {
2222 int r;
2223
2224 assert(link);
2225
2226 if (link_has_carrier(link)) {
2227 r = link_carrier_lost(link);
2228 if (r < 0)
2229 return r;
2230
2231 r = link_carrier_gained(link);
2232 if (r < 0)
2233 return r;
2234
6a7a4e4d 2235 log_link_info(link, "Reset carrier");
9c0a72f9
TG
2236 }
2237
2238 return 0;
2239}
2240
2241
1c4baffc 2242int link_update(Link *link, sd_netlink_message *m) {
c49b33ac 2243 struct ether_addr mac;
ca4e095a 2244 const char *ifname;
afe7fd56 2245 uint32_t mtu;
a61bb41c 2246 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
2247 int r;
2248
dd3efc09 2249 assert(link);
b8941f74 2250 assert(link->ifname);
22936833
TG
2251 assert(m);
2252
7619683b
TG
2253 if (link->state == LINK_STATE_LINGER) {
2254 link_ref(link);
6a7a4e4d 2255 log_link_info(link, "Link readded");
e331e246 2256 link_set_state(link, LINK_STATE_ENSLAVING);
0d4ad91d
AR
2257
2258 r = link_new_carrier_maps(link);
2259 if (r < 0)
2260 return r;
7619683b
TG
2261 }
2262
1c4baffc 2263 r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
b8941f74 2264 if (r >= 0 && !streq(ifname, link->ifname)) {
6a7a4e4d 2265 log_link_info(link, "Renamed to %s", ifname);
b8941f74 2266
0d4ad91d
AR
2267 link_free_carrier_maps(link);
2268
2fc09a9c
DM
2269 r = free_and_strdup(&link->ifname, ifname);
2270 if (r < 0)
2271 return r;
0d4ad91d
AR
2272
2273 r = link_new_carrier_maps(link);
2274 if (r < 0)
2275 return r;
b8941f74
TG
2276 }
2277
1c4baffc 2278 r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
afe7fd56
TG
2279 if (r >= 0 && mtu > 0) {
2280 link->mtu = mtu;
2281 if (!link->original_mtu) {
2282 link->original_mtu = mtu;
6a7a4e4d 2283 log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
afe7fd56
TG
2284 }
2285
2286 if (link->dhcp_client) {
3c9b8860
TG
2287 r = sd_dhcp_client_set_mtu(link->dhcp_client,
2288 link->mtu);
afe7fd56 2289 if (r < 0) {
6a7a4e4d 2290 log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m");
afe7fd56
TG
2291 return r;
2292 }
2293 }
9842de0d 2294 }
69629de9 2295
e9189a1f
TG
2296 /* The kernel may broadcast NEWLINK messages without the MAC address
2297 set, simply ignore them. */
1c4baffc 2298 r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 2299 if (r >= 0) {
3c9b8860
TG
2300 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
2301 ETH_ALEN)) {
c49b33ac 2302
3c9b8860
TG
2303 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
2304 ETH_ALEN);
c49b33ac 2305
79008bdd 2306 log_link_debug(link, "MAC address: "
20861203
TG
2307 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2308 mac.ether_addr_octet[0],
2309 mac.ether_addr_octet[1],
2310 mac.ether_addr_octet[2],
2311 mac.ether_addr_octet[3],
2312 mac.ether_addr_octet[4],
2313 mac.ether_addr_octet[5]);
c49b33ac 2314
20861203
TG
2315 if (link->ipv4ll) {
2316 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
6a7a4e4d
LP
2317 if (r < 0)
2318 return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
c49b33ac 2319 }
c49b33ac 2320
20861203 2321 if (link->dhcp_client) {
3c9b8860 2322 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
2323 (const uint8_t *) &link->mac,
2324 sizeof (link->mac),
2325 ARPHRD_ETHER);
6a7a4e4d
LP
2326 if (r < 0)
2327 return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
c49b33ac 2328 }
4138fb2c
PF
2329
2330 if (link->dhcp6_client) {
2331 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
2332 (const uint8_t *) &link->mac,
2333 sizeof (link->mac),
2334 ARPHRD_ETHER);
6a7a4e4d
LP
2335 if (r < 0)
2336 return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
4138fb2c 2337 }
c49b33ac 2338 }
4f882b2a
TG
2339 }
2340
a61bb41c
TG
2341 had_carrier = link_has_carrier(link);
2342
2343 r = link_update_flags(link, m);
2344 if (r < 0)
2345 return r;
2346
2347 carrier_gained = !had_carrier && link_has_carrier(link);
2348 carrier_lost = had_carrier && !link_has_carrier(link);
2349
2350 if (carrier_gained) {
6a7a4e4d 2351 log_link_info(link, "Gained carrier");
a61bb41c 2352
9c0a72f9
TG
2353 r = link_carrier_gained(link);
2354 if (r < 0)
2355 return r;
a61bb41c 2356 } else if (carrier_lost) {
6a7a4e4d 2357 log_link_info(link, "Lost carrier");
a61bb41c 2358
9c0a72f9
TG
2359 r = link_carrier_lost(link);
2360 if (r < 0)
a61bb41c 2361 return r;
9c0a72f9 2362
a61bb41c
TG
2363 }
2364
2365 return 0;
dd3efc09 2366}
fe8db0c5 2367
e375dcde 2368static void link_update_operstate(Link *link) {
e331e246 2369 LinkOperationalState operstate;
e375dcde
TG
2370 assert(link);
2371
2372 if (link->kernel_operstate == IF_OPER_DORMANT)
e331e246 2373 operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 2374 else if (link_has_carrier(link)) {
e375dcde
TG
2375 Address *address;
2376 uint8_t scope = RT_SCOPE_NOWHERE;
2377
2378 /* if we have carrier, check what addresses we have */
2379 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
2380 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
2381 continue;
2382
e375dcde
TG
2383 if (address->scope < scope)
2384 scope = address->scope;
2385 }
2386
2387 if (scope < RT_SCOPE_SITE)
2388 /* universally accessible addresses found */
e331e246 2389 operstate = LINK_OPERSTATE_ROUTABLE;
e375dcde
TG
2390 else if (scope < RT_SCOPE_HOST)
2391 /* only link or site local addresses found */
e331e246 2392 operstate = LINK_OPERSTATE_DEGRADED;
e375dcde
TG
2393 else
2394 /* no useful addresses found */
e331e246 2395 operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 2396 } else if (link->flags & IFF_UP)
e331e246 2397 operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 2398 else
e331e246
TG
2399 operstate = LINK_OPERSTATE_OFF;
2400
2401 if (link->operstate != operstate) {
2402 link->operstate = operstate;
2403 link_send_changed(link, "OperationalState", NULL);
2404 }
e375dcde
TG
2405}
2406
fe8db0c5 2407int link_save(Link *link) {
68a8723c 2408 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 2409 _cleanup_fclose_ FILE *f = NULL;
e375dcde 2410 const char *admin_state, *oper_state;
fe8db0c5
TG
2411 int r;
2412
2413 assert(link);
2414 assert(link->state_file);
68a8723c 2415 assert(link->lease_file);
bbf7c048
TG
2416 assert(link->manager);
2417
e375dcde
TG
2418 link_update_operstate(link);
2419
bbf7c048
TG
2420 r = manager_save(link->manager);
2421 if (r < 0)
2422 return r;
fe8db0c5 2423
370e9930
TG
2424 if (link->state == LINK_STATE_LINGER) {
2425 unlink(link->state_file);
2426 return 0;
2427 }
2428
deb2e523
TG
2429 admin_state = link_state_to_string(link->state);
2430 assert(admin_state);
2431
e375dcde
TG
2432 oper_state = link_operstate_to_string(link->operstate);
2433 assert(oper_state);
deb2e523 2434
fe8db0c5
TG
2435 r = fopen_temporary(link->state_file, &f, &temp_path);
2436 if (r < 0)
6a7a4e4d 2437 goto fail;
fe8db0c5
TG
2438
2439 fchmod(fileno(f), 0644);
2440
2441 fprintf(f,
2442 "# This is private data. Do not parse.\n"
deb2e523 2443 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
2444 "OPER_STATE=%s\n",
2445 admin_state, oper_state);
fe8db0c5 2446
bcb7a07e 2447 if (link->network) {
ea352b40
LP
2448 char **address, **domain;
2449 bool space;
07bdc70d
PF
2450 sd_dhcp6_lease *dhcp6_lease = NULL;
2451
2452 if (link->dhcp6_client) {
2453 r = sd_dhcp6_client_get_lease(link->dhcp6_client,
2454 &dhcp6_lease);
2455 if (r < 0)
2456 log_link_debug(link, "No DHCPv6 lease");
2457 }
b0e39c82 2458
adc5b2e2
TG
2459 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
2460
b0e39c82 2461 fputs("DNS=", f);
ea352b40
LP
2462 space = false;
2463 STRV_FOREACH(address, link->network->dns) {
2464 if (space)
2465 fputc(' ', f);
2466 fputs(*address, f);
2467 space = true;
2468 }
d5314fff 2469
b0e39c82
TG
2470 if (link->network->dhcp_dns &&
2471 link->dhcp_lease) {
2472 const struct in_addr *addresses;
2473
2474 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
2475 if (r > 0) {
ea352b40
LP
2476 if (space)
2477 fputc(' ', f);
b0e39c82 2478 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2479 space = true;
2480 }
2481 }
2482
2483 if (link->network->dhcp_dns && dhcp6_lease) {
2484 struct in6_addr *in6_addrs;
2485
2486 r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
2487 if (r > 0) {
2488 if (space)
2489 fputc(' ', f);
2490 serialize_in6_addrs(f, in6_addrs, r);
2491 space = true;
b0e39c82
TG
2492 }
2493 }
2494
b0e39c82
TG
2495 fputs("\n", f);
2496
2497 fprintf(f, "NTP=");
ea352b40
LP
2498 space = false;
2499 STRV_FOREACH(address, link->network->ntp) {
2500 if (space)
2501 fputc(' ', f);
2502 fputs(*address, f);
2503 space = true;
2504 }
d5314fff 2505
b0e39c82
TG
2506 if (link->network->dhcp_ntp &&
2507 link->dhcp_lease) {
2508 const struct in_addr *addresses;
2509
2510 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
2511 if (r > 0) {
ea352b40
LP
2512 if (space)
2513 fputc(' ', f);
b0e39c82 2514 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2515 space = true;
2516 }
2517 }
2518
2519 if (link->network->dhcp_ntp && dhcp6_lease) {
2520 struct in6_addr *in6_addrs;
2521 char **hosts;
2522 char **hostname;
2523
2524 r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
2525 &in6_addrs);
2526 if (r > 0) {
2527 if (space)
2528 fputc(' ', f);
2529 serialize_in6_addrs(f, in6_addrs, r);
2530 space = true;
2531 }
2532
2533 r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
2534 if (r > 0) {
2535 STRV_FOREACH(hostname, hosts) {
2536 if (space)
2537 fputc(' ', f);
2538 fputs(*hostname, f);
2539 space = true;
2540 }
b0e39c82
TG
2541 }
2542 }
2543
b0e39c82 2544 fputs("\n", f);
bd8f6538 2545
6192b846 2546 fprintf(f, "DOMAINS=");
ea352b40
LP
2547 space = false;
2548 STRV_FOREACH(domain, link->network->domains) {
2549 if (space)
2550 fputc(' ', f);
2551 fputs(*domain, f);
2552 space = true;
2553 }
d5314fff 2554
ad0734e8 2555 if (link->network->dhcp_domains &&
9b4d1882
TG
2556 link->dhcp_lease) {
2557 const char *domainname;
2558
2559 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 2560 if (r >= 0) {
ea352b40
LP
2561 if (space)
2562 fputc(' ', f);
6192b846 2563 fputs(domainname, f);
07bdc70d
PF
2564 space = true;
2565 }
2566 }
2567
2568 if (link->network->dhcp_domains && dhcp6_lease) {
2569 char **domains;
2570
2571 r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
2572 if (r >= 0) {
2573 STRV_FOREACH(domain, domains) {
2574 if (space)
2575 fputc(' ', f);
2576 fputs(*domain, f);
2577 space = true;
2578 }
6192b846 2579 }
9b4d1882
TG
2580 }
2581
6192b846
TG
2582 fputs("\n", f);
2583
67272d15
TG
2584 fprintf(f, "WILDCARD_DOMAIN=%s\n",
2585 yes_no(link->network->wildcard_domain));
2586
3c9b8860 2587 fprintf(f, "LLMNR=%s\n",
a7e5da6e 2588 resolve_support_to_string(link->network->llmnr));
bcb7a07e 2589 }
7374f9d8 2590
0d4ad91d
AR
2591 if (!hashmap_isempty(link->bound_to_links)) {
2592 Link *carrier;
2593 Iterator i;
2594 bool space = false;
2595
2596 fputs("CARRIER_BOUND_TO=", f);
2597 HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
2598 if (space)
2599 fputc(' ', f);
2600 fputs(carrier->ifname, f);
2601 space = true;
2602 }
2603
2604 fputs("\n", f);
2605 }
2606
2607 if (!hashmap_isempty(link->bound_by_links)) {
2608 Link *carrier;
2609 Iterator i;
2610 bool space = false;
2611
2612 fputs("CARRIER_BOUND_BY=", f);
0d4ad91d
AR
2613 HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
2614 if (space)
2615 fputc(' ', f);
2616 fputs(carrier->ifname, f);
2617 space = true;
2618 }
2619
2620 fputs("\n", f);
2621 }
2622
8eb9058d
LP
2623 if (link->dhcp_lease) {
2624 const char *tz = NULL;
2625
2626 r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
2627 if (r >= 0)
2628 fprintf(f, "TIMEZONE=%s\n", tz);
2629 }
2630
fe8db0c5 2631 if (link->dhcp_lease) {
d9876a52
TG
2632 assert(link->network);
2633
bd91b83e 2634 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 2635 if (r < 0)
c2d6bd61 2636 goto fail;
fe8db0c5 2637
7374f9d8 2638 fprintf(f,
b0e39c82
TG
2639 "DHCP_LEASE=%s\n",
2640 link->lease_file);
deb2e523 2641 } else
68a8723c 2642 unlink(link->lease_file);
fe8db0c5 2643
49699bac
SS
2644 if (link->lldp) {
2645 assert(link->network);
2646
2647 r = sd_lldp_save(link->lldp, link->lldp_file);
2648 if (r < 0)
2649 goto fail;
2650
2651 fprintf(f,
2652 "LLDP_FILE=%s\n",
2653 link->lldp_file);
2654 } else
2655 unlink(link->lldp_file);
2656
c2d6bd61
LP
2657 r = fflush_and_check(f);
2658 if (r < 0)
2659 goto fail;
fe8db0c5 2660
c2d6bd61 2661 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 2662 r = -errno;
c2d6bd61 2663 goto fail;
fe8db0c5
TG
2664 }
2665
c2d6bd61 2666 return 0;
dacd6cee 2667
c2d6bd61 2668fail:
6a7a4e4d 2669 (void) unlink(link->state_file);
6a7a4e4d
LP
2670 if (temp_path)
2671 (void) unlink(temp_path);
2672
dacd6cee 2673 return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
fe8db0c5
TG
2674}
2675
2676static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 2677 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
2678 [LINK_STATE_ENSLAVING] = "configuring",
2679 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
2680 [LINK_STATE_SETTING_ROUTES] = "configuring",
2681 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 2682 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 2683 [LINK_STATE_FAILED] = "failed",
370e9930 2684 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
2685};
2686
2687DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
2688
2689static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
2690 [LINK_OPERSTATE_OFF] = "off",
2691 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
2692 [LINK_OPERSTATE_DORMANT] = "dormant",
2693 [LINK_OPERSTATE_CARRIER] = "carrier",
2694 [LINK_OPERSTATE_DEGRADED] = "degraded",
2695 [LINK_OPERSTATE_ROUTABLE] = "routable",
2696};
2697
2698DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);