]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
networkd: dhcp-server - default to manage the whole subnet
[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
TG
744 /* use the server address' subnet as the pool */
745 r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen, 0, 0);
d4cdbea5
TG
746 if (r < 0)
747 return r;
748
749 /* TODO:
750 r = sd_dhcp_server_set_router(link->dhcp_server,
751 &main_address->in_addr.in);
752 if (r < 0)
753 return r;
d4cdbea5
TG
754 */
755
586ac6f7
LP
756 if (link->network->dhcp_server_max_lease_time_usec > 0) {
757 r = sd_dhcp_server_set_max_lease_time(
758 link->dhcp_server,
759 DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC));
760 if (r < 0)
761 return r;
762 }
763
764 if (link->network->dhcp_server_default_lease_time_usec > 0) {
765 r = sd_dhcp_server_set_default_lease_time(
766 link->dhcp_server,
767 DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC));
768 if (r < 0)
769 return r;
770 }
771
1a04db0f
LP
772 if (link->network->dhcp_server_emit_dns) {
773
4f5f911e 774 if (link->network->n_dhcp_server_dns > 0)
1a04db0f 775 r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns);
4f5f911e
LP
776 else {
777 uplink = manager_find_uplink(link->manager, link);
778 acquired_uplink = true;
779
780 if (!uplink) {
781 log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink.");
782 r = 0;
783 } else
784 r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server);
785 }
786 if (r < 0)
787 log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m");
1a04db0f
LP
788 }
789
790
791 if (link->network->dhcp_server_emit_ntp) {
792
4f5f911e 793 if (link->network->n_dhcp_server_ntp > 0)
1a04db0f 794 r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp);
4f5f911e
LP
795 else {
796 if (!acquired_uplink)
797 uplink = manager_find_uplink(link->manager, link);
798
799 if (!uplink) {
800 log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink.");
801 r = 0;
802 } else
803 r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server);
804
805 }
806 if (r < 0)
807 log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m");
1a04db0f
LP
808 }
809
8eb9058d
LP
810 if (link->network->dhcp_server_emit_timezone) {
811 _cleanup_free_ char *buffer = NULL;
0ab8a1b6 812 const char *tz = NULL;
8eb9058d
LP
813
814 if (link->network->dhcp_server_timezone)
815 tz = link->network->dhcp_server_timezone;
816 else {
817 r = get_timezone(&buffer);
818 if (r < 0)
819 log_warning_errno(r, "Failed to determine timezone: %m");
820 else
821 tz = buffer;
822 }
823
824 if (tz) {
825 r = sd_dhcp_server_set_timezone(link->dhcp_server, tz);
826 if (r < 0)
827 return r;
828 }
829 }
830
d4cdbea5
TG
831 r = sd_dhcp_server_start(link->dhcp_server);
832 if (r < 0) {
6a7a4e4d 833 log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m");
d4cdbea5
TG
834
835 link_enter_failed(link);
836
837 return 0;
838 }
839
6a7a4e4d 840 log_link_debug(link, "Offering DHCPv4 leases");
d4cdbea5
TG
841 }
842
6a7a4e4d 843 if (link->link_messages == 0)
431ca2ce 844 link_enter_set_routes(link);
6a7a4e4d
LP
845 else
846 log_link_debug(link, "Setting addresses");
431ca2ce 847
f882c247
TG
848 return 0;
849}
850
1c4baffc 851int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 852 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
853 int r;
854
855 assert(m);
856 assert(link);
857 assert(link->ifname);
858
5da8149f 859 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
860 return 1;
861
1c4baffc 862 r = sd_netlink_message_get_errno(m);
b90b025a 863 if (r < 0 && r != -EADDRNOTAVAIL)
6a7a4e4d 864 log_link_warning_errno(link, r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
ff254138 865
5bdd314c 866 return 1;
ff254138
TG
867}
868
a245ced0 869static int link_set_bridge_fdb(Link *const link) {
b98b483b
AR
870 FdbEntry *fdb_entry;
871 int r = 0;
872
873 LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
ea6ec096 874 r = fdb_entry_configure(link, fdb_entry);
b98b483b 875 if(r < 0) {
6a7a4e4d 876 log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
b98b483b
AR
877 break;
878 }
879 }
880
881 return r;
882}
883
1c4baffc 884static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
e1853b00
SS
885 _cleanup_link_unref_ Link *link = userdata;
886 int r;
887
6a7a4e4d 888 log_link_debug(link, "Set link");
e1853b00 889
1c4baffc 890 r = sd_netlink_message_get_errno(m);
e1853b00 891 if (r < 0 && r != -EEXIST) {
f2341e0a 892 log_link_error_errno(link, r, "Could not join netdev: %m");
e1853b00
SS
893 link_enter_failed(link);
894 return 1;
895 }
896
897 return 0;
898}
899
19070062 900static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
5da8149f 901 _cleanup_link_unref_ Link *link = userdata;
21b80ad1 902 const sd_bus_error *e;
1346b1f0 903
19070062 904 assert(m);
b226d99b
TG
905 assert(link);
906
5da8149f 907 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 908 return 1;
370e9930 909
21b80ad1
LP
910 e = sd_bus_message_get_error(m);
911 if (e)
912 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
1346b1f0
TG
913
914 return 1;
915}
916
3c9b8860 917int link_set_hostname(Link *link, const char *hostname) {
21b80ad1 918 int r;
1346b1f0 919
b226d99b
TG
920 assert(link);
921 assert(link->manager);
1346b1f0 922
dce391e7 923 log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));
1346b1f0 924
3c9b8860
TG
925 if (!link->manager->bus) {
926 /* TODO: replace by assert when we can rely on kdbus */
6a7a4e4d 927 log_link_info(link, "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
928 return 0;
929 }
930
9c34154a 931 r = sd_bus_call_method_async(
b226d99b 932 link->manager->bus,
9c34154a 933 NULL,
1346b1f0
TG
934 "org.freedesktop.hostname1",
935 "/org/freedesktop/hostname1",
936 "org.freedesktop.hostname1",
9c34154a
UTL
937 "SetHostname",
938 set_hostname_handler,
939 link,
940 "sb",
941 hostname,
942 false);
1346b1f0 943
6a7a4e4d
LP
944 if (r < 0)
945 return log_link_error_errno(link, r, "Could not set transient hostname: %m");
b226d99b
TG
946
947 link_ref(link);
1346b1f0 948
5da8149f 949 return 0;
1346b1f0
TG
950}
951
21b80ad1
LP
952static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
953 _cleanup_link_unref_ Link *link = userdata;
954 const sd_bus_error *e;
955
956 assert(m);
957 assert(link);
958
959 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
960 return 1;
961
962 e = sd_bus_message_get_error(m);
963 if (e)
964 log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
965
966 return 1;
967}
968
969int link_set_timezone(Link *link, const char *timezone) {
970 int r;
971
972 assert(link);
973 assert(link->manager);
974 assert(timezone);
975
976 log_link_debug(link, "Setting system timezone: '%s'", timezone);
977
978 if (!link->manager->bus) {
979 log_link_info(link, "Not connected to system bus, ignoring timezone.");
980 return 0;
981 }
982
983 r = sd_bus_call_method_async(
984 link->manager->bus,
985 NULL,
986 "org.freedesktop.timedate1",
987 "/org/freedesktop/timedate1",
988 "org.freedesktop.timedate1",
989 "SetTimezone",
990 set_timezone_handler,
991 link,
992 "sb",
993 timezone,
994 false);
995 if (r < 0)
996 return log_link_error_errno(link, r, "Could not set timezone: %m");
997
998 link_ref(link);
999
1000 return 0;
1001}
1002
1c4baffc 1003static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1004 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
1005 int r;
1006
1007 assert(m);
1008 assert(link);
1009 assert(link->ifname);
1010
5da8149f 1011 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
1012 return 1;
1013
1c4baffc 1014 r = sd_netlink_message_get_errno(m);
c9ccc19f 1015 if (r < 0)
6a7a4e4d 1016 log_link_warning_errno(link, r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
4f882b2a
TG
1017
1018 return 1;
1019}
1020
3c9b8860 1021int link_set_mtu(Link *link, uint32_t mtu) {
1c4baffc 1022 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f882b2a
TG
1023 int r;
1024
1025 assert(link);
1026 assert(link->manager);
1027 assert(link->manager->rtnl);
1028
6a7a4e4d 1029 log_link_debug(link, "Setting MTU: %" PRIu32, mtu);
4f882b2a 1030
6a7a4e4d
LP
1031 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1032 if (r < 0)
1033 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
4f882b2a 1034
1c4baffc 1035 r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu);
6a7a4e4d
LP
1036 if (r < 0)
1037 return log_link_error_errno(link, r, "Could not append MTU: %m");
4f882b2a 1038
1c4baffc 1039 r = sd_netlink_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
6a7a4e4d
LP
1040 if (r < 0)
1041 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
4f882b2a 1042
ae941762 1043 link_ref(link);
b226d99b 1044
4f882b2a
TG
1045 return 0;
1046}
1047
e1853b00 1048static int link_set_bridge(Link *link) {
1c4baffc 1049 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
e1853b00
SS
1050 int r;
1051
1052 assert(link);
1053 assert(link->network);
1054
6a7a4e4d
LP
1055 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1056 if (r < 0)
1057 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
e1853b00
SS
1058
1059 r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
6a7a4e4d
LP
1060 if (r < 0)
1061 return log_link_error_errno(link, r, "Could not set message family: %m");
e1853b00 1062
1c4baffc 1063 r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
6a7a4e4d
LP
1064 if (r < 0)
1065 return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
e1853b00 1066
84c34096 1067 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
eb7ff4dd
SS
1068 if (r < 0)
1069 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
1070
1071 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
1072 if (r < 0)
1073 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
1074
1075 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
1076 if (r < 0)
1077 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
1078
23da66bb 1079 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
eb7ff4dd
SS
1080 if (r < 0)
1081 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
1082
1083 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
1084 if (r < 0)
1085 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
1086
e1853b00 1087 if(link->network->cost != 0) {
1c4baffc 1088 r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
6a7a4e4d
LP
1089 if (r < 0)
1090 return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
e1853b00
SS
1091 }
1092
1c4baffc 1093 r = sd_netlink_message_close_container(req);
6a7a4e4d
LP
1094 if (r < 0)
1095 return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
e1853b00 1096
1c4baffc 1097 r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
6a7a4e4d
LP
1098 if (r < 0)
1099 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
e1853b00
SS
1100
1101 link_ref(link);
1102
1103 return r;
1104}
1105
49699bac
SS
1106static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
1107 Link *link = userdata;
1108 int r;
1109
1110 assert(link);
1111 assert(link->network);
1112 assert(link->manager);
1113
1114 if (event != UPDATE_INFO)
1115 return;
1116
1117 r = sd_lldp_save(link->lldp, link->lldp_file);
1118 if (r < 0)
6a7a4e4d 1119 log_link_warning_errno(link, r, "Could not save LLDP: %m");
49699bac
SS
1120
1121}
1122
ff254138
TG
1123static int link_acquire_conf(Link *link) {
1124 int r;
1125
1126 assert(link);
1127 assert(link->network);
ff254138
TG
1128 assert(link->manager);
1129 assert(link->manager->event);
1130
78c958f8 1131 if (link_ipv4ll_enabled(link)) {
eb34d4af 1132 assert(link->ipv4ll);
ff254138 1133
6a7a4e4d 1134 log_link_debug(link, "Acquiring IPv4 link-local address");
5c1d3fc9
UTL
1135
1136 r = sd_ipv4ll_start(link->ipv4ll);
6a7a4e4d
LP
1137 if (r < 0)
1138 return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
5c1d3fc9
UTL
1139 }
1140
78c958f8 1141 if (link_dhcp4_enabled(link)) {
eb34d4af 1142 assert(link->dhcp_client);
ff254138 1143
6a7a4e4d 1144 log_link_debug(link, "Acquiring DHCPv4 lease");
ab47d620 1145
5c1d3fc9 1146 r = sd_dhcp_client_start(link->dhcp_client);
6a7a4e4d
LP
1147 if (r < 0)
1148 return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
5c1d3fc9 1149 }
ff254138 1150
78c958f8 1151 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
1152 assert(link->icmp6_router_discovery);
1153
6a7a4e4d 1154 log_link_debug(link, "Discovering IPv6 routers");
4138fb2c
PF
1155
1156 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
6a7a4e4d
LP
1157 if (r < 0)
1158 return log_link_warning_errno(link, r, "Could not start IPv6 router discovery: %m");
4138fb2c
PF
1159 }
1160
ce43e484
SS
1161 if (link_lldp_enabled(link)) {
1162 assert(link->lldp);
1163
1164 log_link_debug(link, "Starting LLDP");
1165
1166 r = sd_lldp_start(link->lldp);
6a7a4e4d
LP
1167 if (r < 0)
1168 return log_link_warning_errno(link, r, "Could not start LLDP: %m");
ce43e484
SS
1169 }
1170
ff254138
TG
1171 return 0;
1172}
1173
a61bb41c 1174bool link_has_carrier(Link *link) {
deb2e523
TG
1175 /* see Documentation/networking/operstates.txt in the kernel sources */
1176
a61bb41c 1177 if (link->kernel_operstate == IF_OPER_UP)
deb2e523
TG
1178 return true;
1179
a61bb41c 1180 if (link->kernel_operstate == IF_OPER_UNKNOWN)
deb2e523 1181 /* operstate may not be implemented, so fall back to flags */
a61bb41c 1182 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
deb2e523
TG
1183 return true;
1184
1185 return false;
1186}
1187
1c4baffc 1188static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1189 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
1190 int r;
1191
1746cf2a
TG
1192 assert(link);
1193
5da8149f 1194 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
1195 return 1;
1196
1c4baffc 1197 r = sd_netlink_message_get_errno(m);
6a7a4e4d
LP
1198 if (r < 0)
1199 /* we warn but don't fail the link, as it may be
1200 brought up later */
1201 log_link_warning_errno(link, r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
45ad2c13 1202
f882c247
TG
1203 return 1;
1204}
1205
1206static int link_up(Link *link) {
1c4baffc 1207 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
5c3072ea 1208 uint8_t ipv6ll_mode;
f579559b
TG
1209 int r;
1210
f882c247 1211 assert(link);
c106cc36 1212 assert(link->network);
f882c247
TG
1213 assert(link->manager);
1214 assert(link->manager->rtnl);
1215
6a7a4e4d 1216 log_link_debug(link, "Bringing link up");
449f7554 1217
6a7a4e4d
LP
1218 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1219 if (r < 0)
1220 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
f579559b 1221
5d4795f3 1222 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
6a7a4e4d
LP
1223 if (r < 0)
1224 return log_link_error_errno(link, r, "Could not set link flags: %m");
fc25d7f8 1225
c106cc36 1226 if (link->network->mac) {
1c4baffc 1227 r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
6a7a4e4d
LP
1228 if (r < 0)
1229 return log_link_error_errno(link, r, "Could not set MAC address: %m");
c106cc36
TG
1230 }
1231
1232 if (link->network->mtu) {
1c4baffc 1233 r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu);
6a7a4e4d
LP
1234 if (r < 0)
1235 return log_link_error_errno(link, r, "Could not set MTU: %m");
c106cc36
TG
1236 }
1237
1c4baffc 1238 r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
6a7a4e4d
LP
1239 if (r < 0)
1240 return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
d0d6a4cd 1241
01d28f81
TG
1242 if (socket_ipv6_is_supported()) {
1243 /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
1c4baffc 1244 r = sd_netlink_message_open_container(req, AF_INET6);
01d28f81
TG
1245 if (r < 0)
1246 return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
d0d6a4cd 1247
01d28f81 1248 ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE;
1c4baffc 1249 r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
01d28f81
TG
1250 if (r < 0)
1251 return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
d0d6a4cd 1252
01d28f81 1253 if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
1c4baffc 1254 r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
01d28f81
TG
1255 if (r < 0)
1256 return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
1257 }
1258
1c4baffc 1259 r = sd_netlink_message_close_container(req);
6a7a4e4d 1260 if (r < 0)
01d28f81 1261 return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
7f77697a 1262 }
d0d6a4cd 1263
1c4baffc 1264 r = sd_netlink_message_close_container(req);
6a7a4e4d
LP
1265 if (r < 0)
1266 return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
d0d6a4cd 1267
1c4baffc 1268 r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
6a7a4e4d
LP
1269 if (r < 0)
1270 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
f579559b 1271
b226d99b
TG
1272 link_ref(link);
1273
f882c247
TG
1274 return 0;
1275}
1276
1c4baffc 1277static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
0d4ad91d
AR
1278 _cleanup_link_unref_ Link *link = userdata;
1279 int r;
1280
1281 assert(link);
1282
1283 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1284 return 1;
1285
1c4baffc 1286 r = sd_netlink_message_get_errno(m);
0d4ad91d 1287 if (r < 0)
6a7a4e4d 1288 log_link_warning_errno(link, r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname);
0d4ad91d
AR
1289
1290 return 1;
1291}
1292
1293static int link_down(Link *link) {
1c4baffc 1294 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
0d4ad91d
AR
1295 int r;
1296
1297 assert(link);
1298 assert(link->manager);
1299 assert(link->manager->rtnl);
1300
6a7a4e4d 1301 log_link_debug(link, "Bringing link down");
0d4ad91d
AR
1302
1303 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1304 RTM_SETLINK, link->ifindex);
6a7a4e4d
LP
1305 if (r < 0)
1306 return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
0d4ad91d
AR
1307
1308 r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
6a7a4e4d
LP
1309 if (r < 0)
1310 return log_link_error_errno(link, r, "Could not set link flags: %m");
0d4ad91d 1311
1c4baffc 1312 r = sd_netlink_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL);
6a7a4e4d
LP
1313 if (r < 0)
1314 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
0d4ad91d
AR
1315
1316 link_ref(link);
1317
1318 return 0;
1319}
1320
1321static int link_handle_bound_to_list(Link *link) {
1322 Link *l;
1323 Iterator i;
1324 int r;
1325 bool required_up = false;
1326 bool link_is_up = false;
1327
1328 assert(link);
1329
1330 if (hashmap_isempty(link->bound_to_links))
1331 return 0;
1332
1333 if (link->flags & IFF_UP)
1334 link_is_up = true;
1335
1336 HASHMAP_FOREACH (l, link->bound_to_links, i)
1337 if (link_has_carrier(l)) {
1338 required_up = true;
1339 break;
1340 }
1341
1342 if (!required_up && link_is_up) {
1343 r = link_down(link);
1344 if (r < 0)
1345 return r;
1346 } else if (required_up && !link_is_up) {
1347 r = link_up(link);
1348 if (r < 0)
1349 return r;
1350 }
1351
1352 return 0;
1353}
1354
1355static int link_handle_bound_by_list(Link *link) {
1356 Iterator i;
1357 Link *l;
1358 int r;
1359
1360 assert(link);
1361
1362 if (hashmap_isempty(link->bound_by_links))
1363 return 0;
1364
1365 HASHMAP_FOREACH (l, link->bound_by_links, i) {
1366 r = link_handle_bound_to_list(l);
1367 if (r < 0)
1368 return r;
1369 }
1370
1371 return 0;
1372}
1373
1374static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) {
1375 int r;
1376
1377 assert(link);
1378 assert(carrier);
1379
1380 if (link == carrier)
1381 return 0;
1382
1383 if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex)))
1384 return 0;
1385
1386 r = hashmap_ensure_allocated(h, NULL);
1387 if (r < 0)
1388 return r;
1389
1390 r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier);
1391 if (r < 0)
1392 return r;
1393
1394 return 0;
1395}
1396
1397static int link_new_bound_by_list(Link *link) {
1398 Manager *m;
1399 Link *carrier;
1400 Iterator i;
1401 int r;
1402 bool list_updated = false;
1403
1404 assert(link);
1405 assert(link->manager);
1406
1407 m = link->manager;
1408
1409 HASHMAP_FOREACH (carrier, m->links, i) {
1410 if (!carrier->network)
1411 continue;
1412
1413 if (strv_isempty(carrier->network->bind_carrier))
1414 continue;
1415
1416 if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) {
1417 r = link_put_carrier(link, carrier, &link->bound_by_links);
1418 if (r < 0)
1419 return r;
1420
1421 list_updated = true;
1422 }
1423 }
1424
1425 if (list_updated)
1426 link_save(link);
1427
1428 HASHMAP_FOREACH (carrier, link->bound_by_links, i) {
1429 r = link_put_carrier(carrier, link, &carrier->bound_to_links);
1430 if (r < 0)
1431 return r;
1432
1433 link_save(carrier);
1434 }
1435
1436 return 0;
1437}
1438
1439static int link_new_bound_to_list(Link *link) {
1440 Manager *m;
1441 Link *carrier;
1442 Iterator i;
1443 int r;
1444 bool list_updated = false;
1445
1446 assert(link);
1447 assert(link->manager);
1448
1449 if (!link->network)
1450 return 0;
1451
1452 if (strv_isempty(link->network->bind_carrier))
1453 return 0;
1454
1455 m = link->manager;
1456
1457 HASHMAP_FOREACH (carrier, m->links, i) {
1458 if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) {
1459 r = link_put_carrier(link, carrier, &link->bound_to_links);
1460 if (r < 0)
1461 return r;
1462
1463 list_updated = true;
1464 }
1465 }
1466
1467 if (list_updated)
1468 link_save(link);
1469
1470 HASHMAP_FOREACH (carrier, link->bound_to_links, i) {
1471 r = link_put_carrier(carrier, link, &carrier->bound_by_links);
1472 if (r < 0)
1473 return r;
1474
1475 link_save(carrier);
1476 }
1477
1478 return 0;
1479}
1480
1481static int link_new_carrier_maps(Link *link) {
1482 int r;
1483
1484 r = link_new_bound_by_list(link);
1485 if (r < 0)
1486 return r;
1487
1488 r = link_handle_bound_by_list(link);
1489 if (r < 0)
1490 return r;
1491
1492 r = link_new_bound_to_list(link);
1493 if (r < 0)
1494 return r;
1495
1496 r = link_handle_bound_to_list(link);
1497 if (r < 0)
1498 return r;
1499
1500 return 0;
1501}
1502
1503static void link_free_bound_to_list(Link *link) {
1504 Link *bound_to;
1505 Iterator i;
1506
1507 HASHMAP_FOREACH (bound_to, link->bound_to_links, i) {
1508 hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex));
1509
1510 if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex)))
1511 link_save(bound_to);
1512 }
1513
1514 return;
1515}
1516
1517static void link_free_bound_by_list(Link *link) {
1518 Link *bound_by;
1519 Iterator i;
1520
1521 HASHMAP_FOREACH (bound_by, link->bound_by_links, i) {
1522 hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex));
1523
1524 if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) {
1525 link_save(bound_by);
1526 link_handle_bound_to_list(bound_by);
1527 }
1528 }
1529
1530 return;
1531}
1532
1533static void link_free_carrier_maps(Link *link) {
1534 bool list_updated = false;
1535
1536 assert(link);
1537
1538 if (!hashmap_isempty(link->bound_to_links)) {
1539 link_free_bound_to_list(link);
1540 list_updated = true;
1541 }
1542
1543 if (!hashmap_isempty(link->bound_by_links)) {
1544 link_free_bound_by_list(link);
1545 list_updated = true;
1546 }
1547
1548 if (list_updated)
1549 link_save(link);
1550
1551 return;
1552}
1553
1554void link_drop(Link *link) {
1555 if (!link || link->state == LINK_STATE_LINGER)
1556 return;
1557
1558 link_set_state(link, LINK_STATE_LINGER);
1559
1560 link_free_carrier_maps(link);
1561
6a7a4e4d 1562 log_link_debug(link, "Link removed");
0d4ad91d
AR
1563
1564 link_unref(link);
1565
1566 return;
1567}
1568
3f265037 1569static int link_joined(Link *link) {
f882c247
TG
1570 int r;
1571
ef1ba606 1572 assert(link);
f5be5601 1573 assert(link->network);
dd3efc09 1574
0d4ad91d
AR
1575 if (!hashmap_isempty(link->bound_to_links)) {
1576 r = link_handle_bound_to_list(link);
1577 if (r < 0)
1578 return r;
1579 } else if (!(link->flags & IFF_UP)) {
505f8da7
TG
1580 r = link_up(link);
1581 if (r < 0) {
1582 link_enter_failed(link);
1583 return r;
1584 }
ef1ba606 1585 }
f882c247 1586
e1853b00
SS
1587 if(link->network->bridge) {
1588 r = link_set_bridge(link);
6a7a4e4d
LP
1589 if (r < 0)
1590 log_link_error_errno(link, r, "Could not set bridge message: %m");
e1853b00
SS
1591 }
1592
fb6730c4 1593 return link_enter_set_addresses(link);
02b59d57
TG
1594}
1595
62e2d5bb 1596static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
5da8149f 1597 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1598 int r;
1599
1746cf2a 1600 assert(link);
ef1ba606 1601 assert(link->network);
02b59d57 1602
52433f6b
TG
1603 link->enslaving --;
1604
5da8149f 1605 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1606 return 1;
1607
1c4baffc 1608 r = sd_netlink_message_get_errno(m);
856f962c 1609 if (r < 0 && r != -EEXIST) {
6a7a4e4d 1610 log_link_error_errno(link, r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
ef1ba606
TG
1611 link_enter_failed(link);
1612 return 1;
ba179154 1613 } else
6a7a4e4d 1614 log_link_debug(link, "Joined netdev");
02b59d57 1615
856f962c 1616 if (link->enslaving <= 0)
3f265037 1617 link_joined(link);
02b59d57
TG
1618
1619 return 1;
1620}
1621
3f265037 1622static int link_enter_join_netdev(Link *link) {
6a0a2f86 1623 NetDev *netdev;
672682a6 1624 Iterator i;
02b59d57
TG
1625 int r;
1626
1627 assert(link);
1628 assert(link->network);
8434fd5c 1629 assert(link->state == LINK_STATE_PENDING);
02b59d57 1630
e331e246 1631 link_set_state(link, LINK_STATE_ENSLAVING);
02b59d57 1632
fe8db0c5
TG
1633 link_save(link);
1634
7951dea2
SS
1635 if (!link->network->bridge &&
1636 !link->network->bond &&
6a0a2f86 1637 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1638 return link_joined(link);
02b59d57 1639
d9c67ea1 1640 if (link->network->bond) {
f2341e0a
LP
1641 log_struct(LOG_DEBUG,
1642 LOG_LINK_INTERFACE(link),
1643 LOG_NETDEV_INTERFACE(link->network->bond),
1644 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname),
1645 NULL);
1646
1647 r = netdev_join(link->network->bond, link, netdev_join_handler);
52433f6b 1648 if (r < 0) {
f2341e0a
LP
1649 log_struct_errno(LOG_WARNING, r,
1650 LOG_LINK_INTERFACE(link),
1651 LOG_NETDEV_INTERFACE(link->network->bond),
1652 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname),
1653 NULL);
1654
52433f6b
TG
1655 link_enter_failed(link);
1656 return r;
1657 }
1658
0ad6148e
MO
1659 link->enslaving ++;
1660 }
1661
d9c67ea1 1662 if (link->network->bridge) {
f2341e0a
LP
1663 log_struct(LOG_DEBUG,
1664 LOG_LINK_INTERFACE(link),
1665 LOG_NETDEV_INTERFACE(link->network->bridge),
1666 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname),
1667 NULL);
1668
1669 r = netdev_join(link->network->bridge, link, netdev_join_handler);
0ad6148e 1670 if (r < 0) {
f2341e0a
LP
1671 log_struct_errno(LOG_WARNING, r,
1672 LOG_LINK_INTERFACE(link),
1673 LOG_NETDEV_INTERFACE(link->network->bridge),
1674 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname),
1675 NULL),
0ad6148e
MO
1676 link_enter_failed(link);
1677 return r;
1678 }
1679
52433f6b
TG
1680 link->enslaving ++;
1681 }
1682
6a0a2f86 1683 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
7951dea2 1684
f2341e0a
LP
1685 log_struct(LOG_DEBUG,
1686 LOG_LINK_INTERFACE(link),
1687 LOG_NETDEV_INTERFACE(netdev),
1688 LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname),
1689 NULL);
1690
1691 r = netdev_join(netdev, link, netdev_join_handler);
7951dea2 1692 if (r < 0) {
f2341e0a
LP
1693 log_struct_errno(LOG_WARNING, r,
1694 LOG_LINK_INTERFACE(link),
1695 LOG_NETDEV_INTERFACE(netdev),
1696 LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname),
1697 NULL);
326cb406
SS
1698 link_enter_failed(link);
1699 return r;
1700 }
1701
326cb406
SS
1702 link->enslaving ++;
1703 }
1704
ef1ba606
TG
1705 return 0;
1706}
1707
769d324c 1708static int link_set_ipv4_forward(Link *link) {
15dee3f0 1709 const char *p = NULL, *v;
5a8bcb67
LP
1710 int r;
1711
15dee3f0
LP
1712 if (link->flags & IFF_LOOPBACK)
1713 return 0;
1714
8add5f79
NO
1715 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1716 return 0;
1717
63c372cb 1718 p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1719 v = one_zero(link_ipv4_forward_enabled(link));
1720
4c1fc3e4 1721 r = write_string_file(p, v, 0);
15dee3f0
LP
1722 if (r < 0) {
1723 /* If the right value is set anyway, don't complain */
1724 if (verify_one_line_file(p, v) > 0)
1725 return 0;
1726
43c6d5ab 1727 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
15dee3f0 1728 }
43c6d5ab 1729
769d324c
LP
1730 return 0;
1731}
1732
1733static int link_set_ipv6_forward(Link *link) {
15dee3f0 1734 const char *p = NULL, *v = NULL;
769d324c
LP
1735 int r;
1736
fe027299
LP
1737 /* Make this a NOP if IPv6 is not available */
1738 if (!socket_ipv6_is_supported())
1739 return 0;
1740
15dee3f0
LP
1741 if (link->flags & IFF_LOOPBACK)
1742 return 0;
1743
8add5f79
NO
1744 if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
1745 return 0;
1746
63c372cb 1747 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
15dee3f0
LP
1748 v = one_zero(link_ipv6_forward_enabled(link));
1749
4c1fc3e4 1750 r = write_string_file(p, v, 0);
15dee3f0
LP
1751 if (r < 0) {
1752 /* If the right value is set anyway, don't complain */
1753 if (verify_one_line_file(p, v) > 0)
1754 return 0;
1755
769d324c 1756 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
15dee3f0 1757 }
5a8bcb67
LP
1758
1759 return 0;
1760}
1761
49092e22 1762static int link_set_ipv6_privacy_extensions(Link *link) {
1f0d9695
LP
1763 char buf[DECIMAL_STR_MAX(unsigned) + 1];
1764 IPv6PrivacyExtensions s;
49092e22
SS
1765 const char *p = NULL;
1766 int r;
1767
1768 /* Make this a NOP if IPv6 is not available */
1769 if (!socket_ipv6_is_supported())
1770 return 0;
1771
1f0d9695
LP
1772 s = link_ipv6_privacy_extensions(link);
1773 if (s == _IPV6_PRIVACY_EXTENSIONS_INVALID)
49092e22
SS
1774 return 0;
1775
1776 p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
1777 xsprintf(buf, "%u", link->network->ipv6_privacy_extensions);
1778
4c1fc3e4 1779 r = write_string_file(p, buf, 0);
1f0d9695
LP
1780 if (r < 0) {
1781 /* If the right value is set anyway, don't complain */
1782 if (verify_one_line_file(p, buf) > 0)
1783 return 0;
1784
49092e22 1785 log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
1f0d9695 1786 }
49092e22
SS
1787
1788 return 0;
1789}
1790
a748b692 1791static int link_configure(Link *link) {
02b59d57
TG
1792 int r;
1793
ef1ba606 1794 assert(link);
b22d8a00 1795 assert(link->network);
8434fd5c 1796 assert(link->state == LINK_STATE_PENDING);
a748b692 1797
b98b483b
AR
1798 r = link_set_bridge_fdb(link);
1799 if (r < 0)
1800 return r;
1801
769d324c
LP
1802 r = link_set_ipv4_forward(link);
1803 if (r < 0)
1804 return r;
1805
1806 r = link_set_ipv6_forward(link);
5a8bcb67
LP
1807 if (r < 0)
1808 return r;
1809
49092e22
SS
1810 r = link_set_ipv6_privacy_extensions(link);
1811 if (r < 0)
1812 return r;
1813
78c958f8 1814 if (link_ipv4ll_enabled(link)) {
b22d8a00 1815 r = ipv4ll_configure(link);
eb34d4af
TG
1816 if (r < 0)
1817 return r;
1818 }
1819
78c958f8 1820 if (link_dhcp4_enabled(link)) {
3c9b8860 1821 r = dhcp4_configure(link);
eb34d4af
TG
1822 if (r < 0)
1823 return r;
eb34d4af
TG
1824 }
1825
78c958f8 1826 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1827 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1828 if (r < 0)
1829 return r;
1830
1831 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1832 if (r < 0)
1833 return r;
dd43110f
TG
1834 }
1835
78c958f8 1836 if (link_dhcp6_enabled(link)) {
5c79bd79 1837 r = icmp6_configure(link);
4138fb2c
PF
1838 if (r < 0)
1839 return r;
1840 }
1841
ce43e484
SS
1842 if (link_lldp_enabled(link)) {
1843 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
1844 if (r < 0)
1845 return r;
1846
1847 r = sd_lldp_attach_event(link->lldp, NULL, 0);
1848 if (r < 0)
1849 return r;
49699bac
SS
1850
1851 r = sd_lldp_set_callback(link->lldp,
1852 lldp_handler, link);
1853 if (r < 0)
1854 return r;
ce43e484
SS
1855 }
1856
a61bb41c 1857 if (link_has_carrier(link)) {
1e9be60b
TG
1858 r = link_acquire_conf(link);
1859 if (r < 0)
1860 return r;
cc544d5f 1861 }
1e9be60b 1862
3f265037 1863 return link_enter_join_netdev(link);
505f8da7
TG
1864}
1865
1c4baffc 1866static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m,
3c9b8860 1867 void *userdata) {
5da8149f 1868 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1869 Network *network;
505f8da7
TG
1870 int r;
1871
1872 assert(link);
1873 assert(link->ifname);
1874 assert(link->manager);
1875
8434fd5c 1876 if (link->state != LINK_STATE_PENDING)
5da8149f 1877 return 1;
505f8da7 1878
6a7a4e4d 1879 log_link_debug(link, "Link state is up-to-date");
505f8da7 1880
0d4ad91d
AR
1881 r = link_new_bound_by_list(link);
1882 if (r < 0)
1883 return r;
1884
1885 r = link_handle_bound_by_list(link);
1886 if (r < 0)
1887 return r;
1888
3c9b8860
TG
1889 r = network_get(link->manager, link->udev_device, link->ifname,
1890 &link->mac, &network);
57bd6899
TG
1891 if (r == -ENOENT) {
1892 link_enter_unmanaged(link);
5da8149f 1893 return 1;
57bd6899
TG
1894 } else if (r < 0)
1895 return r;
505f8da7 1896
bd2efe92 1897 if (link->flags & IFF_LOOPBACK) {
d0d6a4cd 1898 if (network->link_local != ADDRESS_FAMILY_NO)
6a7a4e4d 1899 log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link");
78c958f8 1900
cb9fc36a 1901 if (network->dhcp != ADDRESS_FAMILY_NO)
6a7a4e4d 1902 log_link_debug(link, "Ignoring DHCP clients for loopback link");
78c958f8
TG
1903
1904 if (network->dhcp_server)
6a7a4e4d 1905 log_link_debug(link, "Ignoring DHCP server for loopback link");
bd2efe92
TG
1906 }
1907
505f8da7
TG
1908 r = network_apply(link->manager, network, link);
1909 if (r < 0)
1910 return r;
1911
0d4ad91d
AR
1912 r = link_new_bound_to_list(link);
1913 if (r < 0)
1914 return r;
1915
a748b692
TG
1916 r = link_configure(link);
1917 if (r < 0)
1918 return r;
1919
5da8149f 1920 return 1;
505f8da7
TG
1921}
1922
4f561e8e 1923int link_initialized(Link *link, struct udev_device *device) {
1c4baffc 1924 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
4f561e8e
TG
1925 int r;
1926
1927 assert(link);
1928 assert(link->manager);
1929 assert(link->manager->rtnl);
1930 assert(device);
1931
8434fd5c 1932 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1933 return 0;
1934
679b3605
TG
1935 if (link->udev_device)
1936 return 0;
1937
79008bdd 1938 log_link_debug(link, "udev initialized link");
4f561e8e
TG
1939
1940 link->udev_device = udev_device_ref(device);
1941
3c9b8860
TG
1942 /* udev has initialized the link, but we don't know if we have yet
1943 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1944 * when it returns we know that the pending NEWLINKs have already been
1945 * processed and that we are up-to-date */
4f561e8e 1946
3c9b8860
TG
1947 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1948 link->ifindex);
4f561e8e
TG
1949 if (r < 0)
1950 return r;
1951
1c4baffc 1952 r = sd_netlink_call_async(link->manager->rtnl, req,
3c9b8860 1953 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1954 if (r < 0)
1955 return r;
1956
5da8149f
TG
1957 link_ref(link);
1958
4f561e8e
TG
1959 return 0;
1960}
1961
5a8bcb67
LP
1962static Address* link_get_equal_address(Link *link, Address *needle) {
1963 Address *i;
1964
1965 assert(link);
1966 assert(needle);
1967
1968 LIST_FOREACH(addresses, i, link->addresses)
1969 if (address_equal(i, needle))
1970 return i;
1971
1972 return NULL;
1973}
1974
1c4baffc 1975int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
fbbeb65a
TG
1976 Manager *m = userdata;
1977 Link *link = NULL;
1978 uint16_t type;
1979 _cleanup_address_free_ Address *address = NULL;
851c9f82 1980 unsigned char flags;
5a8bcb67
LP
1981 Address *existing;
1982 char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
c6d3b303 1983 const char *valid_str = NULL;
fbbeb65a
TG
1984 int r, ifindex;
1985
1986 assert(rtnl);
1987 assert(message);
1988 assert(m);
1989
1c4baffc
TG
1990 if (sd_netlink_message_is_error(message)) {
1991 r = sd_netlink_message_get_errno(message);
45af44d4
TG
1992 if (r < 0)
1993 log_warning_errno(r, "rtnl: failed to receive address: %m");
1994
1995 return 0;
1996 }
1997
1c4baffc 1998 r = sd_netlink_message_get_type(message, &type);
fbbeb65a 1999 if (r < 0) {
6a7a4e4d 2000 log_warning_errno(r, "rtnl: could not get message type: %m");
fbbeb65a 2001 return 0;
cdfee943
TG
2002 } else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
2003 log_warning("rtnl: received unexpected message type when processing address");
2004 return 0;
fbbeb65a
TG
2005 }
2006
2007 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
45af44d4 2008 if (r < 0) {
cdfee943 2009 log_warning_errno(r, "rtnl: could not get ifindex from address: %m");
45af44d4
TG
2010 return 0;
2011 } else if (ifindex <= 0) {
2012 log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
fbbeb65a
TG
2013 return 0;
2014 } else {
2015 r = link_get(m, ifindex, &link);
2016 if (r < 0 || !link) {
6a24f148
TG
2017 /* when enumerating we might be out of sync, but we will
2018 * get the address again, so just ignore it */
2019 if (!m->enumerating)
2020 log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
fbbeb65a
TG
2021 return 0;
2022 }
2023 }
2024
2025 r = address_new_dynamic(&address);
2026 if (r < 0)
393c0c5e 2027 return r;
fbbeb65a
TG
2028
2029 r = sd_rtnl_message_addr_get_family(message, &address->family);
2030 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
6a7a4e4d 2031 log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
fbbeb65a
TG
2032 return 0;
2033 }
2034
2035 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
2036 if (r < 0) {
6a7a4e4d 2037 log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
e375dcde
TG
2038 return 0;
2039 }
2040
2041 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
2042 if (r < 0) {
6a7a4e4d 2043 log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
fbbeb65a
TG
2044 return 0;
2045 }
2046
851c9f82 2047 r = sd_rtnl_message_addr_get_flags(message, &flags);
81163121 2048 if (r < 0) {
6a7a4e4d 2049 log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
81163121
TG
2050 return 0;
2051 }
851c9f82 2052 address->flags = flags;
81163121 2053
fbbeb65a
TG
2054 switch (address->family) {
2055 case AF_INET:
1c4baffc 2056 r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
fbbeb65a 2057 if (r < 0) {
6a7a4e4d 2058 log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
fbbeb65a
TG
2059 return 0;
2060 }
2061
2062 break;
2063
2064 case AF_INET6:
1c4baffc 2065 r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
fbbeb65a 2066 if (r < 0) {
6a7a4e4d 2067 log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
fbbeb65a
TG
2068 return 0;
2069 }
2070
2071 break;
2072
2073 default:
2074 assert_not_reached("invalid address family");
2075 }
2076
5a8bcb67 2077 if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
6a7a4e4d 2078 log_link_warning(link, "Could not print address");
fbbeb65a
TG
2079 return 0;
2080 }
2081
1c4baffc 2082 r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
c6d3b303
TG
2083 if (r >= 0) {
2084 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
2085 valid_str = "ever";
2086 else
2087 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
2088 address->cinfo.ifa_valid * USEC_PER_SEC,
2089 USEC_PER_SEC);
2090 }
2091
5a8bcb67
LP
2092 existing = link_get_equal_address(link, address);
2093
2094 switch (type) {
2095 case RTM_NEWADDR:
2096 if (existing) {
2097 log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 2098
428fd0a7 2099
5a8bcb67
LP
2100 existing->scope = address->scope;
2101 existing->flags = address->flags;
2102 existing->cinfo = address->cinfo;
428fd0a7 2103
5a8bcb67
LP
2104 } else {
2105 log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 2106
5a8bcb67
LP
2107 LIST_PREPEND(addresses, link->addresses, address);
2108 address_establish(address, link);
fbbeb65a 2109
5a8bcb67 2110 address = NULL;
428fd0a7 2111
5a8bcb67
LP
2112 link_save(link);
2113 }
f5602be9 2114
428fd0a7 2115 break;
5a8bcb67 2116
fbbeb65a 2117 case RTM_DELADDR:
428fd0a7 2118
5a8bcb67
LP
2119 if (existing) {
2120 log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
2121 address_release(existing, link);
2122 LIST_REMOVE(addresses, link->addresses, existing);
2123 address_free(existing);
393c0c5e 2124 } else
5a8bcb67 2125 log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
f5602be9 2126
fbbeb65a
TG
2127 break;
2128 default:
2129 assert_not_reached("Received invalid RTNL message type");
2130 }
2131
2132 return 1;
2133}
2134
1c4baffc 2135int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
505f8da7
TG
2136 Link *link;
2137 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
2138 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
2139 int r;
2140
2141 assert(m);
fbbeb65a 2142 assert(m->rtnl);
505f8da7
TG
2143 assert(message);
2144 assert(ret);
2145
2146 r = link_new(m, message, ret);
2147 if (r < 0)
2148 return r;
2149
2150 link = *ret;
2151
6a7a4e4d 2152 log_link_debug(link, "Link %d added", link->ifindex);
505f8da7
TG
2153
2154 if (detect_container(NULL) <= 0) {
2155 /* not in a container, udev will be around */
ae06ab10 2156 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7 2157 device = udev_device_new_from_device_id(m->udev, ifindex_str);
6a7a4e4d
LP
2158 if (!device)
2159 return log_link_warning_errno(link, errno, "Could not find udev device: %m");
505f8da7 2160
3c4cb064 2161 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 2162 /* not yet ready */
79008bdd 2163 log_link_debug(link, "link pending udev initialization...");
505f8da7 2164 return 0;
3c4cb064 2165 }
505f8da7 2166
4f561e8e
TG
2167 r = link_initialized(link, device);
2168 if (r < 0)
2169 return r;
2170 } else {
5da8149f
TG
2171 /* we are calling a callback directly, so must take a ref */
2172 link_ref(link);
2173
4f561e8e
TG
2174 r = link_initialized_and_synced(m->rtnl, NULL, link);
2175 if (r < 0)
2176 return r;
2177 }
505f8da7 2178
a748b692
TG
2179 return 0;
2180}
2181
9c0a72f9
TG
2182static int link_carrier_gained(Link *link) {
2183 int r;
2184
2185 assert(link);
2186
2187 if (link->network) {
2188 r = link_acquire_conf(link);
2189 if (r < 0) {
2190 link_enter_failed(link);
2191 return r;
2192 }
2193 }
2194
0d4ad91d
AR
2195 r = link_handle_bound_by_list(link);
2196 if (r < 0)
2197 return r;
2198
9c0a72f9
TG
2199 return 0;
2200}
2201
2202static int link_carrier_lost(Link *link) {
2203 int r;
2204
2205 assert(link);
2206
2207 r = link_stop_clients(link);
2208 if (r < 0) {
2209 link_enter_failed(link);
2210 return r;
2211 }
2212
0d4ad91d
AR
2213 r = link_handle_bound_by_list(link);
2214 if (r < 0)
2215 return r;
2216
9c0a72f9
TG
2217 return 0;
2218}
2219
2220int link_carrier_reset(Link *link) {
2221 int r;
2222
2223 assert(link);
2224
2225 if (link_has_carrier(link)) {
2226 r = link_carrier_lost(link);
2227 if (r < 0)
2228 return r;
2229
2230 r = link_carrier_gained(link);
2231 if (r < 0)
2232 return r;
2233
6a7a4e4d 2234 log_link_info(link, "Reset carrier");
9c0a72f9
TG
2235 }
2236
2237 return 0;
2238}
2239
2240
1c4baffc 2241int link_update(Link *link, sd_netlink_message *m) {
c49b33ac 2242 struct ether_addr mac;
ca4e095a 2243 const char *ifname;
afe7fd56 2244 uint32_t mtu;
a61bb41c 2245 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
2246 int r;
2247
dd3efc09 2248 assert(link);
b8941f74 2249 assert(link->ifname);
22936833
TG
2250 assert(m);
2251
7619683b
TG
2252 if (link->state == LINK_STATE_LINGER) {
2253 link_ref(link);
6a7a4e4d 2254 log_link_info(link, "Link readded");
e331e246 2255 link_set_state(link, LINK_STATE_ENSLAVING);
0d4ad91d
AR
2256
2257 r = link_new_carrier_maps(link);
2258 if (r < 0)
2259 return r;
7619683b
TG
2260 }
2261
1c4baffc 2262 r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname);
b8941f74 2263 if (r >= 0 && !streq(ifname, link->ifname)) {
6a7a4e4d 2264 log_link_info(link, "Renamed to %s", ifname);
b8941f74 2265
0d4ad91d
AR
2266 link_free_carrier_maps(link);
2267
2fc09a9c
DM
2268 r = free_and_strdup(&link->ifname, ifname);
2269 if (r < 0)
2270 return r;
0d4ad91d
AR
2271
2272 r = link_new_carrier_maps(link);
2273 if (r < 0)
2274 return r;
b8941f74
TG
2275 }
2276
1c4baffc 2277 r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
afe7fd56
TG
2278 if (r >= 0 && mtu > 0) {
2279 link->mtu = mtu;
2280 if (!link->original_mtu) {
2281 link->original_mtu = mtu;
6a7a4e4d 2282 log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
afe7fd56
TG
2283 }
2284
2285 if (link->dhcp_client) {
3c9b8860
TG
2286 r = sd_dhcp_client_set_mtu(link->dhcp_client,
2287 link->mtu);
afe7fd56 2288 if (r < 0) {
6a7a4e4d 2289 log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m");
afe7fd56
TG
2290 return r;
2291 }
2292 }
9842de0d 2293 }
69629de9 2294
e9189a1f
TG
2295 /* The kernel may broadcast NEWLINK messages without the MAC address
2296 set, simply ignore them. */
1c4baffc 2297 r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 2298 if (r >= 0) {
3c9b8860
TG
2299 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
2300 ETH_ALEN)) {
c49b33ac 2301
3c9b8860
TG
2302 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
2303 ETH_ALEN);
c49b33ac 2304
79008bdd 2305 log_link_debug(link, "MAC address: "
20861203
TG
2306 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
2307 mac.ether_addr_octet[0],
2308 mac.ether_addr_octet[1],
2309 mac.ether_addr_octet[2],
2310 mac.ether_addr_octet[3],
2311 mac.ether_addr_octet[4],
2312 mac.ether_addr_octet[5]);
c49b33ac 2313
20861203
TG
2314 if (link->ipv4ll) {
2315 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
6a7a4e4d
LP
2316 if (r < 0)
2317 return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m");
c49b33ac 2318 }
c49b33ac 2319
20861203 2320 if (link->dhcp_client) {
3c9b8860 2321 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
2322 (const uint8_t *) &link->mac,
2323 sizeof (link->mac),
2324 ARPHRD_ETHER);
6a7a4e4d
LP
2325 if (r < 0)
2326 return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m");
c49b33ac 2327 }
4138fb2c
PF
2328
2329 if (link->dhcp6_client) {
2330 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
2331 (const uint8_t *) &link->mac,
2332 sizeof (link->mac),
2333 ARPHRD_ETHER);
6a7a4e4d
LP
2334 if (r < 0)
2335 return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m");
4138fb2c 2336 }
c49b33ac 2337 }
4f882b2a
TG
2338 }
2339
a61bb41c
TG
2340 had_carrier = link_has_carrier(link);
2341
2342 r = link_update_flags(link, m);
2343 if (r < 0)
2344 return r;
2345
2346 carrier_gained = !had_carrier && link_has_carrier(link);
2347 carrier_lost = had_carrier && !link_has_carrier(link);
2348
2349 if (carrier_gained) {
6a7a4e4d 2350 log_link_info(link, "Gained carrier");
a61bb41c 2351
9c0a72f9
TG
2352 r = link_carrier_gained(link);
2353 if (r < 0)
2354 return r;
a61bb41c 2355 } else if (carrier_lost) {
6a7a4e4d 2356 log_link_info(link, "Lost carrier");
a61bb41c 2357
9c0a72f9
TG
2358 r = link_carrier_lost(link);
2359 if (r < 0)
a61bb41c 2360 return r;
9c0a72f9 2361
a61bb41c
TG
2362 }
2363
2364 return 0;
dd3efc09 2365}
fe8db0c5 2366
e375dcde 2367static void link_update_operstate(Link *link) {
e331e246 2368 LinkOperationalState operstate;
e375dcde
TG
2369 assert(link);
2370
2371 if (link->kernel_operstate == IF_OPER_DORMANT)
e331e246 2372 operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 2373 else if (link_has_carrier(link)) {
e375dcde
TG
2374 Address *address;
2375 uint8_t scope = RT_SCOPE_NOWHERE;
2376
2377 /* if we have carrier, check what addresses we have */
2378 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
2379 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
2380 continue;
2381
e375dcde
TG
2382 if (address->scope < scope)
2383 scope = address->scope;
2384 }
2385
2386 if (scope < RT_SCOPE_SITE)
2387 /* universally accessible addresses found */
e331e246 2388 operstate = LINK_OPERSTATE_ROUTABLE;
e375dcde
TG
2389 else if (scope < RT_SCOPE_HOST)
2390 /* only link or site local addresses found */
e331e246 2391 operstate = LINK_OPERSTATE_DEGRADED;
e375dcde
TG
2392 else
2393 /* no useful addresses found */
e331e246 2394 operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 2395 } else if (link->flags & IFF_UP)
e331e246 2396 operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 2397 else
e331e246
TG
2398 operstate = LINK_OPERSTATE_OFF;
2399
2400 if (link->operstate != operstate) {
2401 link->operstate = operstate;
2402 link_send_changed(link, "OperationalState", NULL);
2403 }
e375dcde
TG
2404}
2405
fe8db0c5 2406int link_save(Link *link) {
68a8723c 2407 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 2408 _cleanup_fclose_ FILE *f = NULL;
e375dcde 2409 const char *admin_state, *oper_state;
fe8db0c5
TG
2410 int r;
2411
2412 assert(link);
2413 assert(link->state_file);
68a8723c 2414 assert(link->lease_file);
bbf7c048
TG
2415 assert(link->manager);
2416
e375dcde
TG
2417 link_update_operstate(link);
2418
bbf7c048
TG
2419 r = manager_save(link->manager);
2420 if (r < 0)
2421 return r;
fe8db0c5 2422
370e9930
TG
2423 if (link->state == LINK_STATE_LINGER) {
2424 unlink(link->state_file);
2425 return 0;
2426 }
2427
deb2e523
TG
2428 admin_state = link_state_to_string(link->state);
2429 assert(admin_state);
2430
e375dcde
TG
2431 oper_state = link_operstate_to_string(link->operstate);
2432 assert(oper_state);
deb2e523 2433
fe8db0c5
TG
2434 r = fopen_temporary(link->state_file, &f, &temp_path);
2435 if (r < 0)
6a7a4e4d 2436 goto fail;
fe8db0c5
TG
2437
2438 fchmod(fileno(f), 0644);
2439
2440 fprintf(f,
2441 "# This is private data. Do not parse.\n"
deb2e523 2442 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
2443 "OPER_STATE=%s\n",
2444 admin_state, oper_state);
fe8db0c5 2445
bcb7a07e 2446 if (link->network) {
ea352b40
LP
2447 char **address, **domain;
2448 bool space;
07bdc70d
PF
2449 sd_dhcp6_lease *dhcp6_lease = NULL;
2450
2451 if (link->dhcp6_client) {
2452 r = sd_dhcp6_client_get_lease(link->dhcp6_client,
2453 &dhcp6_lease);
2454 if (r < 0)
2455 log_link_debug(link, "No DHCPv6 lease");
2456 }
b0e39c82 2457
adc5b2e2
TG
2458 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
2459
b0e39c82 2460 fputs("DNS=", f);
ea352b40
LP
2461 space = false;
2462 STRV_FOREACH(address, link->network->dns) {
2463 if (space)
2464 fputc(' ', f);
2465 fputs(*address, f);
2466 space = true;
2467 }
d5314fff 2468
b0e39c82
TG
2469 if (link->network->dhcp_dns &&
2470 link->dhcp_lease) {
2471 const struct in_addr *addresses;
2472
2473 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
2474 if (r > 0) {
ea352b40
LP
2475 if (space)
2476 fputc(' ', f);
b0e39c82 2477 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2478 space = true;
2479 }
2480 }
2481
2482 if (link->network->dhcp_dns && dhcp6_lease) {
2483 struct in6_addr *in6_addrs;
2484
2485 r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
2486 if (r > 0) {
2487 if (space)
2488 fputc(' ', f);
2489 serialize_in6_addrs(f, in6_addrs, r);
2490 space = true;
b0e39c82
TG
2491 }
2492 }
2493
b0e39c82
TG
2494 fputs("\n", f);
2495
2496 fprintf(f, "NTP=");
ea352b40
LP
2497 space = false;
2498 STRV_FOREACH(address, link->network->ntp) {
2499 if (space)
2500 fputc(' ', f);
2501 fputs(*address, f);
2502 space = true;
2503 }
d5314fff 2504
b0e39c82
TG
2505 if (link->network->dhcp_ntp &&
2506 link->dhcp_lease) {
2507 const struct in_addr *addresses;
2508
2509 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
2510 if (r > 0) {
ea352b40
LP
2511 if (space)
2512 fputc(' ', f);
b0e39c82 2513 serialize_in_addrs(f, addresses, r);
07bdc70d
PF
2514 space = true;
2515 }
2516 }
2517
2518 if (link->network->dhcp_ntp && dhcp6_lease) {
2519 struct in6_addr *in6_addrs;
2520 char **hosts;
2521 char **hostname;
2522
2523 r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
2524 &in6_addrs);
2525 if (r > 0) {
2526 if (space)
2527 fputc(' ', f);
2528 serialize_in6_addrs(f, in6_addrs, r);
2529 space = true;
2530 }
2531
2532 r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
2533 if (r > 0) {
2534 STRV_FOREACH(hostname, hosts) {
2535 if (space)
2536 fputc(' ', f);
2537 fputs(*hostname, f);
2538 space = true;
2539 }
b0e39c82
TG
2540 }
2541 }
2542
b0e39c82 2543 fputs("\n", f);
bd8f6538 2544
6192b846 2545 fprintf(f, "DOMAINS=");
ea352b40
LP
2546 space = false;
2547 STRV_FOREACH(domain, link->network->domains) {
2548 if (space)
2549 fputc(' ', f);
2550 fputs(*domain, f);
2551 space = true;
2552 }
d5314fff 2553
ad0734e8 2554 if (link->network->dhcp_domains &&
9b4d1882
TG
2555 link->dhcp_lease) {
2556 const char *domainname;
2557
2558 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 2559 if (r >= 0) {
ea352b40
LP
2560 if (space)
2561 fputc(' ', f);
6192b846 2562 fputs(domainname, f);
07bdc70d
PF
2563 space = true;
2564 }
2565 }
2566
2567 if (link->network->dhcp_domains && dhcp6_lease) {
2568 char **domains;
2569
2570 r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
2571 if (r >= 0) {
2572 STRV_FOREACH(domain, domains) {
2573 if (space)
2574 fputc(' ', f);
2575 fputs(*domain, f);
2576 space = true;
2577 }
6192b846 2578 }
9b4d1882
TG
2579 }
2580
6192b846
TG
2581 fputs("\n", f);
2582
67272d15
TG
2583 fprintf(f, "WILDCARD_DOMAIN=%s\n",
2584 yes_no(link->network->wildcard_domain));
2585
3c9b8860 2586 fprintf(f, "LLMNR=%s\n",
a7e5da6e 2587 resolve_support_to_string(link->network->llmnr));
bcb7a07e 2588 }
7374f9d8 2589
0d4ad91d
AR
2590 if (!hashmap_isempty(link->bound_to_links)) {
2591 Link *carrier;
2592 Iterator i;
2593 bool space = false;
2594
2595 fputs("CARRIER_BOUND_TO=", f);
2596 HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
2597 if (space)
2598 fputc(' ', f);
2599 fputs(carrier->ifname, f);
2600 space = true;
2601 }
2602
2603 fputs("\n", f);
2604 }
2605
2606 if (!hashmap_isempty(link->bound_by_links)) {
2607 Link *carrier;
2608 Iterator i;
2609 bool space = false;
2610
2611 fputs("CARRIER_BOUND_BY=", f);
0d4ad91d
AR
2612 HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
2613 if (space)
2614 fputc(' ', f);
2615 fputs(carrier->ifname, f);
2616 space = true;
2617 }
2618
2619 fputs("\n", f);
2620 }
2621
8eb9058d
LP
2622 if (link->dhcp_lease) {
2623 const char *tz = NULL;
2624
2625 r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
2626 if (r >= 0)
2627 fprintf(f, "TIMEZONE=%s\n", tz);
2628 }
2629
fe8db0c5 2630 if (link->dhcp_lease) {
d9876a52
TG
2631 assert(link->network);
2632
bd91b83e 2633 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 2634 if (r < 0)
c2d6bd61 2635 goto fail;
fe8db0c5 2636
7374f9d8 2637 fprintf(f,
b0e39c82
TG
2638 "DHCP_LEASE=%s\n",
2639 link->lease_file);
deb2e523 2640 } else
68a8723c 2641 unlink(link->lease_file);
fe8db0c5 2642
49699bac
SS
2643 if (link->lldp) {
2644 assert(link->network);
2645
2646 r = sd_lldp_save(link->lldp, link->lldp_file);
2647 if (r < 0)
2648 goto fail;
2649
2650 fprintf(f,
2651 "LLDP_FILE=%s\n",
2652 link->lldp_file);
2653 } else
2654 unlink(link->lldp_file);
2655
c2d6bd61
LP
2656 r = fflush_and_check(f);
2657 if (r < 0)
2658 goto fail;
fe8db0c5 2659
c2d6bd61 2660 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 2661 r = -errno;
c2d6bd61 2662 goto fail;
fe8db0c5
TG
2663 }
2664
c2d6bd61 2665 return 0;
dacd6cee 2666
c2d6bd61 2667fail:
6a7a4e4d 2668 (void) unlink(link->state_file);
6a7a4e4d
LP
2669 if (temp_path)
2670 (void) unlink(temp_path);
2671
dacd6cee 2672 return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
fe8db0c5
TG
2673}
2674
2675static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 2676 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
2677 [LINK_STATE_ENSLAVING] = "configuring",
2678 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
2679 [LINK_STATE_SETTING_ROUTES] = "configuring",
2680 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 2681 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 2682 [LINK_STATE_FAILED] = "failed",
370e9930 2683 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
2684};
2685
2686DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
2687
2688static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
2689 [LINK_OPERSTATE_OFF] = "off",
2690 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
2691 [LINK_OPERSTATE_DORMANT] = "dormant",
2692 [LINK_OPERSTATE_CARRIER] = "carrier",
2693 [LINK_OPERSTATE_DEGRADED] = "degraded",
2694 [LINK_OPERSTATE_ROUTABLE] = "routable",
2695};
2696
2697DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);