]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
network: dhcp - split out dhcp_identifier_set_{iaid,duid_en} from dhcp6-client
[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"
1346b1f0 29#include "bus-util.h"
5a8bcb67
LP
30#include "udev-util.h"
31#include "libudev-private.h"
c6f7c917 32#include "network-internal.h"
5a8bcb67
LP
33#include "networkd-link.h"
34#include "networkd-netdev.h"
ed942a9e 35#include "conf-parser.h"
fe8db0c5
TG
36#include "dhcp-lease-internal.h"
37
78c958f8
TG
38static bool link_dhcp6_enabled(Link *link) {
39 if (link->flags & IFF_LOOPBACK)
40 return false;
41
42 if (!link->network)
43 return false;
44
cb9fc36a 45 return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES);
78c958f8
TG
46}
47
48static bool link_dhcp4_enabled(Link *link) {
49 if (link->flags & IFF_LOOPBACK)
50 return false;
51
52 if (!link->network)
53 return false;
54
cb9fc36a 55 return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES);
78c958f8
TG
56}
57
58static bool link_dhcp4_server_enabled(Link *link) {
59 if (link->flags & IFF_LOOPBACK)
60 return false;
61
62 if (!link->network)
63 return false;
64
65 return link->network->dhcp_server;
66}
67
68static bool link_ipv4ll_enabled(Link *link) {
69 if (link->flags & IFF_LOOPBACK)
70 return false;
71
72 if (!link->network)
73 return false;
74
75 return link->network->ipv4ll;
76}
77
ce43e484
SS
78static bool link_lldp_enabled(Link *link) {
79 if (link->flags & IFF_LOOPBACK)
80 return false;
81
82 if (!link->network)
83 return false;
84
5a8bcb67 85 if (link->network->bridge)
ce43e484
SS
86 return false;
87
88 return link->network->lldp;
89}
90
769d324c 91static bool link_ipv4_forward_enabled(Link *link) {
5a8bcb67
LP
92 if (link->flags & IFF_LOOPBACK)
93 return false;
94
95 if (!link->network)
96 return false;
97
769d324c
LP
98 return IN_SET(link->network->ip_forward, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES);
99}
100
101static bool link_ipv6_forward_enabled(Link *link) {
102 if (link->flags & IFF_LOOPBACK)
103 return false;
104
105 if (!link->network)
106 return false;
107
108 return IN_SET(link->network->ip_forward, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES);
5a8bcb67
LP
109}
110
51d18171
TG
111#define FLAG_STRING(string, flag, old, new) \
112 (((old ^ new) & flag) \
113 ? ((old & flag) ? (" -" string) : (" +" string)) \
114 : "")
115
116static int link_update_flags(Link *link, sd_rtnl_message *m) {
117 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
118 uint8_t operstate;
119 int r;
120
121 assert(link);
122
123 r = sd_rtnl_message_link_get_flags(m, &flags);
124 if (r < 0) {
79008bdd 125 log_link_warning(link, "Could not get link flags");
51d18171
TG
126 return r;
127 }
128
129 r = sd_rtnl_message_read_u8(m, IFLA_OPERSTATE, &operstate);
130 if (r < 0)
131 /* if we got a message without operstate, take it to mean
132 the state was unchanged */
133 operstate = link->kernel_operstate;
134
135 if ((link->flags == flags) && (link->kernel_operstate == operstate))
136 return 0;
137
138 if (link->flags != flags) {
79008bdd 139 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
140 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
141 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
142 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
143 FLAG_STRING("UP", IFF_UP, link->flags, flags),
144 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
145 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
146 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
147 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
148 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
149 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
150 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
151 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
152 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
153 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
154 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
155 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
156 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
157 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
158 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
159
160 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
161 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
162 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
163 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
164 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
165 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
166 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
167 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
168
169 /* link flags are currently at most 18 bits, let's align to
170 * printing 20 */
171 if (unknown_flags_added)
79008bdd 172 log_link_debug(link,
51d18171
TG
173 "unknown link flags gained: %#.5x (ignoring)",
174 unknown_flags_added);
175
176 if (unknown_flags_removed)
79008bdd 177 log_link_debug(link,
51d18171
TG
178 "unknown link flags lost: %#.5x (ignoring)",
179 unknown_flags_removed);
180 }
181
182 link->flags = flags;
183 link->kernel_operstate = operstate;
184
185 link_save(link);
186
187 return 0;
188}
189
505f8da7 190static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
14b746f7 191 _cleanup_link_unref_ Link *link = NULL;
505f8da7 192 uint16_t type;
ca4e095a 193 const char *ifname;
505f8da7 194 int r, ifindex;
f579559b 195
0c2f9b84 196 assert(manager);
505f8da7 197 assert(message);
f579559b
TG
198 assert(ret);
199
505f8da7
TG
200 r = sd_rtnl_message_get_type(message, &type);
201 if (r < 0)
202 return r;
203 else if (type != RTM_NEWLINK)
204 return -EINVAL;
205
206 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
207 if (r < 0)
208 return r;
209 else if (ifindex <= 0)
210 return -EINVAL;
211
212 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &ifname);
213 if (r < 0)
214 return r;
215
f579559b
TG
216 link = new0(Link, 1);
217 if (!link)
218 return -ENOMEM;
219
14b746f7 220 link->n_ref = 1;
5a3eb5a7 221 link->manager = manager;
8434fd5c 222 link->state = LINK_STATE_PENDING;
505f8da7
TG
223 link->ifindex = ifindex;
224 link->ifname = strdup(ifname);
225 if (!link->ifname)
226 return -ENOMEM;
f579559b 227
512922f8
TG
228 r = sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
229 if (r < 0)
79008bdd 230 log_link_debug(link, "MAC address not found for new device, continuing without");
512922f8 231
3c9b8860
TG
232 r = asprintf(&link->state_file, "/run/systemd/netif/links/%d",
233 link->ifindex);
fe8db0c5 234 if (r < 0)
315db1a8 235 return -ENOMEM;
fe8db0c5 236
3c9b8860
TG
237 r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d",
238 link->ifindex);
68a8723c
TG
239 if (r < 0)
240 return -ENOMEM;
241
49699bac
SS
242 r = asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d",
243 link->ifindex);
244 if (r < 0)
245 return -ENOMEM;
246
247
d5099efc 248 r = hashmap_ensure_allocated(&manager->links, NULL);
ae06ab10
TG
249 if (r < 0)
250 return r;
251
252 r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
f579559b
TG
253 if (r < 0)
254 return r;
255
51d18171
TG
256 r = link_update_flags(link, message);
257 if (r < 0)
258 return r;
259
f579559b
TG
260 *ret = link;
261 link = NULL;
262
263 return 0;
264}
265
14b746f7 266static void link_free(Link *link) {
428fd0a7
TG
267 Address *address;
268
f579559b
TG
269 if (!link)
270 return;
271
428fd0a7
TG
272 while ((address = link->addresses)) {
273 LIST_REMOVE(addresses, link->addresses, address);
274 address_free(address);
275 }
276
11bf3cce
LP
277 while ((address = link->pool_addresses)) {
278 LIST_REMOVE(addresses, link->pool_addresses, address);
279 address_free(address);
280 }
281
bfcdba8d 282 sd_dhcp_server_unref(link->dhcp_server);
e5b04c8d 283 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 284 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 285
68a8723c
TG
286 unlink(link->lease_file);
287 free(link->lease_file);
288
49699bac
SS
289 unlink(link->lldp_file);
290 free(link->lldp_file);
291
56cd007a 292 sd_ipv4ll_unref(link->ipv4ll);
4138fb2c 293 sd_dhcp6_client_unref(link->dhcp6_client);
6b66097b 294 sd_icmp6_nd_unref(link->icmp6_router_discovery);
4138fb2c 295
28aeb07f 296 if (link->manager)
ae06ab10 297 hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
f579559b 298
c166a070 299 free(link->ifname);
68a8723c
TG
300
301 unlink(link->state_file);
fe8db0c5 302 free(link->state_file);
c166a070 303
b5db00e5
UTL
304 udev_device_unref(link->udev_device);
305
f579559b
TG
306 free(link);
307}
308
14b746f7
TG
309Link *link_unref(Link *link) {
310 if (link && (-- link->n_ref <= 0))
311 link_free(link);
312
313 return NULL;
314}
315
316Link *link_ref(Link *link) {
317 if (link)
318 assert_se(++ link->n_ref >= 2);
319
320 return link;
321}
322
11a7f229
TG
323int link_get(Manager *m, int ifindex, Link **ret) {
324 Link *link;
11a7f229
TG
325
326 assert(m);
11a7f229
TG
327 assert(ifindex);
328 assert(ret);
329
ae06ab10 330 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
11a7f229
TG
331 if (!link)
332 return -ENODEV;
333
334 *ret = link;
335
336 return 0;
337}
338
370e9930
TG
339void link_drop(Link *link) {
340 if (!link || link->state == LINK_STATE_LINGER)
341 return;
342
343 link->state = LINK_STATE_LINGER;
344
79008bdd 345 log_link_debug(link, "link removed");
370e9930
TG
346
347 link_unref(link);
348
349 return;
350}
351
57bd6899
TG
352static void link_enter_unmanaged(Link *link) {
353 assert(link);
354
79008bdd 355 log_link_debug(link, "unmanaged");
57bd6899
TG
356
357 link->state = LINK_STATE_UNMANAGED;
358
359 link_save(link);
360}
361
111bb8f9
TG
362static int link_stop_clients(Link *link) {
363 int r = 0, k;
364
365 assert(link);
366 assert(link->manager);
367 assert(link->manager->event);
368
369 if (!link->network)
370 return 0;
371
ba179154 372 if (link->dhcp_client) {
111bb8f9
TG
373 k = sd_dhcp_client_stop(link->dhcp_client);
374 if (k < 0) {
79008bdd 375 log_link_warning(link, "Could not stop DHCPv4 client: %s",
3c9b8860 376 strerror(-r));
111bb8f9
TG
377 r = k;
378 }
379 }
380
ba179154 381 if (link->ipv4ll) {
111bb8f9
TG
382 k = sd_ipv4ll_stop(link->ipv4ll);
383 if (k < 0) {
79008bdd 384 log_link_warning(link, "Could not stop IPv4 link-local: %s",
3c9b8860 385 strerror(-r));
111bb8f9 386 r = k;
dd43110f
TG
387 }
388 }
389
ba179154 390 if(link->icmp6_router_discovery) {
1873a3d3
PF
391
392 if (link->dhcp6_client) {
393 k = sd_dhcp6_client_stop(link->dhcp6_client);
394 if (k < 0) {
79008bdd 395 log_link_warning(link, "Could not stop DHCPv6 client: %s",
3c9b8860 396 strerror(-r));
1873a3d3
PF
397 r = k;
398 }
399 }
4138fb2c 400
1873a3d3 401 k = sd_icmp6_nd_stop(link->icmp6_router_discovery);
4138fb2c 402 if (k < 0) {
79008bdd 403 log_link_warning(link,
3c9b8860
TG
404 "Could not stop ICMPv6 router discovery: %s",
405 strerror(-r));
4138fb2c
PF
406 r = k;
407 }
408 }
409
ce43e484
SS
410 if (link->lldp) {
411
412 k = sd_lldp_stop(link->lldp);
413 if (k < 0) {
414 log_link_warning(link, "Could not stop LLDP : %s",
415 strerror(-r));
416 r = k;
417 }
418 }
419
111bb8f9
TG
420 return r;
421}
422
b22d8a00 423void link_enter_failed(Link *link) {
ef1ba606 424 assert(link);
f882c247 425
370e9930 426 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2139694e
TG
427 return;
428
79008bdd 429 log_link_warning(link, "failed");
449f7554 430
ef1ba606 431 link->state = LINK_STATE_FAILED;
fe8db0c5 432
111bb8f9
TG
433 link_stop_clients(link);
434
fe8db0c5 435 link_save(link);
f882c247
TG
436}
437
4f434938
LP
438static Address* link_find_dhcp_server_address(Link *link) {
439 Address *address;
440
441 assert(link);
442 assert(link->network);
443
444 /* The the first statically configured address if there is any */
445 LIST_FOREACH(addresses, address, link->network->static_addresses) {
446
447 if (address->family != AF_INET)
448 continue;
449
af93291c 450 if (in_addr_is_null(address->family, &address->in_addr))
4f434938
LP
451 continue;
452
453 return address;
454 }
455
456 /* If that didn't work, find a suitable address we got from the pool */
457 LIST_FOREACH(addresses, address, link->pool_addresses) {
458 if (address->family != AF_INET)
459 continue;
460
461 return address;
462 }
463
464 return NULL;
465}
466
dd43110f
TG
467static int link_enter_configured(Link *link) {
468 int r;
469
470 assert(link);
471 assert(link->network);
472 assert(link->state == LINK_STATE_SETTING_ROUTES);
473
78c958f8 474 if (link_dhcp4_server_enabled(link) &&
7c16313f 475 !sd_dhcp_server_is_running(link->dhcp_server)) {
4f434938
LP
476 struct in_addr pool_start;
477 Address *address;
478
479 address = link_find_dhcp_server_address(link);
480 if (!address) {
79008bdd 481 log_link_warning(link,
3c9b8860 482 "Failed to find suitable address for DHCPv4 server instance.");
4f434938
LP
483 link_enter_failed(link);
484 return 0;
485 }
486
79008bdd 487 log_link_debug(link, "offering DHCPv4 leases");
dd43110f 488
3c9b8860
TG
489 r = sd_dhcp_server_set_address(link->dhcp_server,
490 &address->in_addr.in,
491 address->prefixlen);
4f434938
LP
492 if (r < 0)
493 return r;
494
495 /* offer 32 addresses starting from the address following the server address */
496 pool_start.s_addr = htobe32(be32toh(address->in_addr.in.s_addr) + 1);
497 r = sd_dhcp_server_set_lease_pool(link->dhcp_server,
498 &pool_start, 32);
499 if (r < 0)
500 return r;
501
502 /* TODO:
503 r = sd_dhcp_server_set_router(link->dhcp_server,
504 &main_address->in_addr.in);
505 if (r < 0)
506 return r;
507
508 r = sd_dhcp_server_set_prefixlen(link->dhcp_server,
509 main_address->prefixlen);
510 if (r < 0)
511 return r;
512 */
513
dd43110f
TG
514 r = sd_dhcp_server_start(link->dhcp_server);
515 if (r < 0) {
79008bdd 516 log_link_warning(link, "could not start DHCPv4 server "
dd43110f
TG
517 "instance: %s", strerror(-r));
518
519 link_enter_failed(link);
520
521 return 0;
522 }
523 }
524
79008bdd 525 log_link_info(link, "link configured");
dd43110f
TG
526
527 link->state = LINK_STATE_CONFIGURED;
528
529 link_save(link);
530
531 return 0;
532}
533
3c9b8860
TG
534void link_client_handler(Link *link) {
535 assert(link);
536 assert(link->network);
537
538 if (!link->static_configured)
539 return;
540
78c958f8 541 if (link_ipv4ll_enabled(link))
3c9b8860
TG
542 if (!link->ipv4ll_address ||
543 !link->ipv4ll_route)
544 return;
545
78c958f8 546 if (link_dhcp4_enabled(link) && !link->dhcp4_configured)
3c9b8860
TG
547 return;
548
9fdaa992
TG
549 if (link->state != LINK_STATE_CONFIGURED)
550 link_enter_configured(link);
3c9b8860
TG
551
552 return;
553}
554
f882c247 555static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 556 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
557 int r;
558
3c9b8860 559 assert(link->link_messages > 0);
370e9930
TG
560 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
561 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
562 LINK_STATE_LINGER));
f882c247 563
3c9b8860 564 link->link_messages --;
f882c247 565
77a008c0 566 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
567 return 1;
568
569 r = sd_rtnl_message_get_errno(m);
c166a070 570 if (r < 0 && r != -EEXIST)
6c861f0a 571 log_link_warning_errno(link, -r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname);
f882c247 572
3c9b8860 573 if (link->link_messages == 0) {
79008bdd 574 log_link_debug(link, "routes set");
3c9b8860
TG
575 link->static_configured = true;
576 link_client_handler(link);
dd3efc09 577 }
f882c247
TG
578
579 return 1;
580}
581
582static int link_enter_set_routes(Link *link) {
a6cc569e 583 Route *rt;
f882c247
TG
584 int r;
585
586 assert(link);
587 assert(link->network);
ef1ba606 588 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 589
ef1ba606 590 link->state = LINK_STATE_SETTING_ROUTES;
f882c247 591
3d3d4255 592 LIST_FOREACH(routes, rt, link->network->static_routes) {
a6cc569e 593 r = route_configure(rt, link, &route_handler);
dd3efc09 594 if (r < 0) {
79008bdd 595 log_link_warning(link,
3c9b8860 596 "could not set routes: %s",
b1666580 597 strerror(-r));
3c9b8860 598 link_enter_failed(link);
a6cc569e
TG
599 return r;
600 }
601
3c9b8860 602 link->link_messages ++;
8ddbeaa2 603 }
f5be5601 604
3c9b8860
TG
605 if (link->link_messages == 0) {
606 link->static_configured = true;
607 link_client_handler(link);
431ca2ce 608 } else
79008bdd 609 log_link_debug(link, "setting routes");
f882c247
TG
610
611 return 0;
612}
613
b22d8a00 614int link_route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 615 _cleanup_link_unref_ Link *link = userdata;
5c1d3fc9
UTL
616 int r;
617
618 assert(m);
619 assert(link);
620 assert(link->ifname);
621
5da8149f 622 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c1d3fc9
UTL
623 return 1;
624
625 r = sd_rtnl_message_get_errno(m);
b90b025a 626 if (r < 0 && r != -ESRCH)
6c861f0a 627 log_link_warning_errno(link, -r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname);
5c1d3fc9 628
5bdd314c 629 return 1;
5c1d3fc9
UTL
630}
631
f882c247 632static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 633 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
634 int r;
635
4958aee4 636 assert(rtnl);
f5be5601
TG
637 assert(m);
638 assert(link);
639 assert(link->ifname);
3c9b8860 640 assert(link->link_messages > 0);
370e9930
TG
641 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
642 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 643
3c9b8860 644 link->link_messages --;
f882c247 645
5da8149f 646 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
647 return 1;
648
649 r = sd_rtnl_message_get_errno(m);
c166a070 650 if (r < 0 && r != -EEXIST)
6c861f0a 651 log_link_warning_errno(link, -r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname);
45af44d4
TG
652 else if (r >= 0)
653 link_rtnl_process_address(rtnl, m, link->manager);
f882c247 654
3c9b8860 655 if (link->link_messages == 0) {
79008bdd 656 log_link_debug(link, "addresses set");
ef1ba606 657 link_enter_set_routes(link);
dd3efc09 658 }
f882c247
TG
659
660 return 1;
661}
662
663static int link_enter_set_addresses(Link *link) {
a6cc569e 664 Address *ad;
f882c247
TG
665 int r;
666
667 assert(link);
668 assert(link->network);
f5be5601 669 assert(link->state != _LINK_STATE_INVALID);
f882c247 670
ef1ba606 671 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 672
3d3d4255 673 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
a6cc569e 674 r = address_configure(ad, link, &address_handler);
dd3efc09 675 if (r < 0) {
5a8bcb67 676 log_link_warning_errno(link, r, "Could not set addresses: %m");
f5be5601
TG
677 link_enter_failed(link);
678 return r;
679 }
680
3c9b8860 681 link->link_messages ++;
f882c247
TG
682 }
683
3c9b8860 684 if (link->link_messages == 0) {
431ca2ce
TG
685 link_enter_set_routes(link);
686 } else
79008bdd 687 log_link_debug(link, "setting addresses");
431ca2ce 688
f882c247
TG
689 return 0;
690}
691
b22d8a00 692int link_address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 693 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
694 int r;
695
696 assert(m);
697 assert(link);
698 assert(link->ifname);
699
5da8149f 700 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
701 return 1;
702
703 r = sd_rtnl_message_get_errno(m);
b90b025a 704 if (r < 0 && r != -EADDRNOTAVAIL)
6c861f0a 705 log_link_warning_errno(link, -r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
ff254138 706
5bdd314c 707 return 1;
ff254138
TG
708}
709
b98b483b
AR
710static int link_set_bridge_fdb(const Link *const link) {
711 FdbEntry *fdb_entry;
712 int r = 0;
713
714 LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
715 r = fdb_entry_configure(link->manager->rtnl, fdb_entry, link->ifindex);
716 if(r < 0) {
717 log_link_error(link, "Failed to add MAC entry to static MAC table: %s", strerror(-r));
718 break;
719 }
720 }
721
722 return r;
723}
724
e1853b00
SS
725static int link_set_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
726 _cleanup_link_unref_ Link *link = userdata;
727 int r;
728
00e8d83a 729 log_link_debug(link, "set link");
e1853b00
SS
730
731 r = sd_rtnl_message_get_errno(m);
732 if (r < 0 && r != -EEXIST) {
00e8d83a 733 log_link_struct(link, LOG_ERR,
e1853b00
SS
734 "MESSAGE=%-*s: could not join netdev: %s",
735 IFNAMSIZ,
736 link->ifname, strerror(-r),
737 "ERRNO=%d", -r,
738 NULL);
739 link_enter_failed(link);
740 return 1;
741 }
742
743 return 0;
744}
745
3c9b8860
TG
746static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata,
747 sd_bus_error *ret_error) {
5da8149f 748 _cleanup_link_unref_ Link *link = userdata;
1346b1f0
TG
749 int r;
750
b226d99b
TG
751 assert(link);
752
5da8149f 753 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 754 return 1;
370e9930 755
1346b1f0 756 r = sd_bus_message_get_errno(m);
70b34f5d 757 if (r > 0)
79008bdd 758 log_link_warning(link, "Could not set hostname: %s",
3c9b8860 759 strerror(r));
1346b1f0
TG
760
761 return 1;
762}
763
3c9b8860 764int link_set_hostname(Link *link, const char *hostname) {
1346b1f0
TG
765 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
766 int r = 0;
767
b226d99b
TG
768 assert(link);
769 assert(link->manager);
1346b1f0
TG
770 assert(hostname);
771
79008bdd 772 log_link_debug(link, "Setting transient hostname: '%s'", hostname);
1346b1f0 773
3c9b8860
TG
774 if (!link->manager->bus) {
775 /* TODO: replace by assert when we can rely on kdbus */
79008bdd 776 log_link_info(link,
3c9b8860 777 "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
778 return 0;
779 }
780
1346b1f0 781 r = sd_bus_message_new_method_call(
b226d99b 782 link->manager->bus,
151b9b96 783 &m,
1346b1f0
TG
784 "org.freedesktop.hostname1",
785 "/org/freedesktop/hostname1",
786 "org.freedesktop.hostname1",
151b9b96 787 "SetHostname");
1346b1f0
TG
788 if (r < 0)
789 return r;
790
791 r = sd_bus_message_append(m, "sb", hostname, false);
792 if (r < 0)
793 return r;
794
3c9b8860
TG
795 r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler,
796 link, 0);
5da8149f 797 if (r < 0) {
79008bdd 798 log_link_error(link, "Could not set transient hostname: %s",
3c9b8860 799 strerror(-r));
5da8149f
TG
800 return r;
801 }
b226d99b
TG
802
803 link_ref(link);
1346b1f0 804
5da8149f 805 return 0;
1346b1f0
TG
806}
807
4f882b2a 808static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 809 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
810 int r;
811
812 assert(m);
813 assert(link);
814 assert(link->ifname);
815
5da8149f 816 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
817 return 1;
818
819 r = sd_rtnl_message_get_errno(m);
c9ccc19f 820 if (r < 0)
6c861f0a 821 log_link_warning_errno(link, -r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
4f882b2a
TG
822
823 return 1;
824}
825
3c9b8860 826int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 827 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
828 int r;
829
830 assert(link);
831 assert(link->manager);
832 assert(link->manager->rtnl);
833
79008bdd 834 log_link_debug(link, "setting MTU: %" PRIu32, mtu);
4f882b2a 835
151b9b96
LP
836 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
837 RTM_SETLINK, link->ifindex);
4f882b2a 838 if (r < 0) {
79008bdd 839 log_link_error(link, "Could not allocate RTM_SETLINK message");
4f882b2a
TG
840 return r;
841 }
842
843 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
844 if (r < 0) {
79008bdd 845 log_link_error(link, "Could not append MTU: %s", strerror(-r));
4f882b2a
TG
846 return r;
847 }
848
3c9b8860
TG
849 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link,
850 0, NULL);
4f882b2a 851 if (r < 0) {
79008bdd 852 log_link_error(link,
3c9b8860
TG
853 "Could not send rtnetlink message: %s",
854 strerror(-r));
4f882b2a
TG
855 return r;
856 }
857
ae941762 858 link_ref(link);
b226d99b 859
4f882b2a
TG
860 return 0;
861}
862
e1853b00
SS
863static int link_set_bridge(Link *link) {
864 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
865 int r;
866
867 assert(link);
868 assert(link->network);
869
870 if(link->network->cost == 0)
871 return 0;
872
873 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
874 RTM_SETLINK, link->ifindex);
875 if (r < 0) {
00e8d83a 876 log_link_error(link, "Could not allocate RTM_SETLINK message");
e1853b00
SS
877 return r;
878 }
879
880 r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
881 if (r < 0) {
00e8d83a 882 log_link_error(link,
e1853b00
SS
883 "Could not set message family %s", strerror(-r));
884 return r;
885 }
886
887 r = sd_rtnl_message_open_container(req, IFLA_PROTINFO);
888 if (r < 0) {
00e8d83a 889 log_link_error(link,
e1853b00
SS
890 "Could not append IFLA_PROTINFO attribute: %s",
891 strerror(-r));
892 return r;
893 }
894
895 if(link->network->cost != 0) {
896 r = sd_rtnl_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
897 if (r < 0) {
00e8d83a 898 log_link_error(link,
e1853b00
SS
899 "Could not append IFLA_BRPORT_COST attribute: %s",
900 strerror(-r));
901 return r;
902 }
903 }
904
905 r = sd_rtnl_message_close_container(req);
906 if (r < 0) {
00e8d83a 907 log_link_error(link,
e1853b00
SS
908 "Could not append IFLA_LINKINFO attribute: %s",
909 strerror(-r));
910 return r;
911 }
912
913 r = sd_rtnl_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL);
914 if (r < 0) {
00e8d83a 915 log_link_error(link,
e1853b00
SS
916 "Could not send rtnetlink message: %s",
917 strerror(-r));
918 return r;
919 }
920
921 link_ref(link);
922
923 return r;
924}
925
49699bac
SS
926static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
927 Link *link = userdata;
928 int r;
929
930 assert(link);
931 assert(link->network);
932 assert(link->manager);
933
934 if (event != UPDATE_INFO)
935 return;
936
937 r = sd_lldp_save(link->lldp, link->lldp_file);
938 if (r < 0)
939 log_link_warning(link, "could not save LLDP");
940
941}
942
ff254138
TG
943static int link_acquire_conf(Link *link) {
944 int r;
945
946 assert(link);
947 assert(link->network);
ff254138
TG
948 assert(link->manager);
949 assert(link->manager->event);
950
78c958f8 951 if (link_ipv4ll_enabled(link)) {
eb34d4af 952 assert(link->ipv4ll);
ff254138 953
79008bdd 954 log_link_debug(link, "acquiring IPv4 link-local address");
5c1d3fc9
UTL
955
956 r = sd_ipv4ll_start(link->ipv4ll);
124fa2c6 957 if (r < 0) {
79008bdd 958 log_link_warning(link, "could not acquire IPv4 "
124fa2c6 959 "link-local address");
ff254138 960 return r;
124fa2c6 961 }
5c1d3fc9
UTL
962 }
963
78c958f8 964 if (link_dhcp4_enabled(link)) {
eb34d4af 965 assert(link->dhcp_client);
ff254138 966
79008bdd 967 log_link_debug(link, "acquiring DHCPv4 lease");
ab47d620 968
5c1d3fc9 969 r = sd_dhcp_client_start(link->dhcp_client);
124fa2c6 970 if (r < 0) {
79008bdd 971 log_link_warning(link, "could not acquire DHCPv4 "
124fa2c6 972 "lease");
5c1d3fc9 973 return r;
124fa2c6 974 }
5c1d3fc9 975 }
ff254138 976
78c958f8 977 if (link_dhcp6_enabled(link)) {
4138fb2c
PF
978 assert(link->icmp6_router_discovery);
979
79008bdd 980 log_link_debug(link, "discovering IPv6 routers");
4138fb2c
PF
981
982 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
983 if (r < 0) {
79008bdd 984 log_link_warning(link,
3c9b8860 985 "could not start IPv6 router discovery");
4138fb2c
PF
986 return r;
987 }
988 }
989
ce43e484
SS
990 if (link_lldp_enabled(link)) {
991 assert(link->lldp);
992
993 log_link_debug(link, "Starting LLDP");
994
995 r = sd_lldp_start(link->lldp);
996 if (r < 0) {
997 log_link_warning(link, "could not start LLDP ");
998 return r;
999 }
1000 }
1001
ff254138
TG
1002 return 0;
1003}
1004
a61bb41c 1005bool link_has_carrier(Link *link) {
deb2e523
TG
1006 /* see Documentation/networking/operstates.txt in the kernel sources */
1007
a61bb41c 1008 if (link->kernel_operstate == IF_OPER_UP)
deb2e523
TG
1009 return true;
1010
a61bb41c 1011 if (link->kernel_operstate == IF_OPER_UNKNOWN)
deb2e523 1012 /* operstate may not be implemented, so fall back to flags */
a61bb41c 1013 if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
deb2e523
TG
1014 return true;
1015
1016 return false;
1017}
1018
dd3efc09 1019static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 1020 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
1021 int r;
1022
1746cf2a
TG
1023 assert(link);
1024
5da8149f 1025 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
1026 return 1;
1027
dd3efc09 1028 r = sd_rtnl_message_get_errno(m);
45ad2c13 1029 if (r < 0) {
9b86b393
TG
1030 /* we warn but don't fail the link, as it may
1031 be brought up later */
6c861f0a 1032 log_link_warning_errno(link, -r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
45ad2c13
TG
1033 }
1034
f882c247
TG
1035 return 1;
1036}
1037
1038static int link_up(Link *link) {
cf6a8911 1039 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1040 int r;
1041
f882c247 1042 assert(link);
c106cc36 1043 assert(link->network);
f882c247
TG
1044 assert(link->manager);
1045 assert(link->manager->rtnl);
1046
79008bdd 1047 log_link_debug(link, "bringing link up");
449f7554 1048
151b9b96
LP
1049 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1050 RTM_SETLINK, link->ifindex);
f579559b 1051 if (r < 0) {
79008bdd 1052 log_link_error(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1053 return r;
1054 }
1055
5d4795f3 1056 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1057 if (r < 0) {
79008bdd 1058 log_link_error(link, "Could not set link flags: %s",
3c9b8860 1059 strerror(-r));
fc25d7f8
TG
1060 return r;
1061 }
1062
c106cc36
TG
1063 if (link->network->mac) {
1064 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac);
1065 if (r < 0) {
1066 log_link_error(link, "Could not set MAC address: %s", strerror(-r));
1067 return r;
1068 }
1069 }
1070
1071 if (link->network->mtu) {
1072 r = sd_rtnl_message_append_u32(req, IFLA_MTU, link->network->mtu);
1073 if (r < 0) {
1074 log_link_error(link, "Could not set MTU: %s", strerror(-r));
1075 return r;
1076 }
1077 }
1078
3c9b8860
TG
1079 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link,
1080 0, NULL);
f579559b 1081 if (r < 0) {
79008bdd 1082 log_link_error(link,
3c9b8860
TG
1083 "Could not send rtnetlink message: %s",
1084 strerror(-r));
f579559b
TG
1085 return r;
1086 }
1087
b226d99b
TG
1088 link_ref(link);
1089
f882c247
TG
1090 return 0;
1091}
1092
3f265037 1093static int link_joined(Link *link) {
f882c247
TG
1094 int r;
1095
ef1ba606 1096 assert(link);
f5be5601 1097 assert(link->network);
dd3efc09 1098
505f8da7
TG
1099 if (!(link->flags & IFF_UP)) {
1100 r = link_up(link);
1101 if (r < 0) {
1102 link_enter_failed(link);
1103 return r;
1104 }
ef1ba606 1105 }
f882c247 1106
e1853b00
SS
1107 if(link->network->bridge) {
1108 r = link_set_bridge(link);
1109 if (r < 0) {
00e8d83a 1110 log_link_error(link,
e1853b00
SS
1111 "Could not set bridge message: %s",
1112 strerror(-r));
1113 }
1114 }
1115
fb6730c4 1116 return link_enter_set_addresses(link);
02b59d57
TG
1117}
1118
3c9b8860
TG
1119static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1120 void *userdata) {
5da8149f 1121 _cleanup_link_unref_ Link *link = userdata;
02b59d57
TG
1122 int r;
1123
1746cf2a 1124 assert(link);
ef1ba606 1125 assert(link->network);
02b59d57 1126
52433f6b
TG
1127 link->enslaving --;
1128
5da8149f 1129 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1130 return 1;
1131
1132 r = sd_rtnl_message_get_errno(m);
856f962c 1133 if (r < 0 && r != -EEXIST) {
6c861f0a 1134 log_link_error_errno(link, -r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
ef1ba606
TG
1135 link_enter_failed(link);
1136 return 1;
ba179154 1137 } else
79008bdd 1138 log_link_debug(link, "joined netdev");
02b59d57 1139
856f962c 1140 if (link->enslaving <= 0)
3f265037 1141 link_joined(link);
02b59d57
TG
1142
1143 return 1;
1144}
1145
3f265037 1146static int link_enter_join_netdev(Link *link) {
6a0a2f86 1147 NetDev *netdev;
672682a6 1148 Iterator i;
02b59d57
TG
1149 int r;
1150
1151 assert(link);
1152 assert(link->network);
8434fd5c 1153 assert(link->state == LINK_STATE_PENDING);
02b59d57 1154
52433f6b 1155 link->state = LINK_STATE_ENSLAVING;
02b59d57 1156
fe8db0c5
TG
1157 link_save(link);
1158
7951dea2
SS
1159 if (!link->network->bridge &&
1160 !link->network->bond &&
6a0a2f86 1161 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1162 return link_joined(link);
02b59d57 1163
d9c67ea1 1164 if (link->network->bond) {
6c861f0a 1165 log_link_struct(link, LOG_DEBUG,
97578344 1166 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1167 IFNAMSIZ,
af4e9e2c 1168 link->ifname, link->network->bond->ifname,
aa9f1140 1169 NETDEVIF(link->network->bond),
52433f6b 1170 NULL);
449f7554 1171
3f265037 1172 r = netdev_join(link->network->bond, link, &netdev_join_handler);
52433f6b 1173 if (r < 0) {
6c861f0a 1174 log_link_struct(link, LOG_WARNING,
3f265037 1175 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1176 IFNAMSIZ,
3c9b8860
TG
1177 link->ifname, link->network->bond->ifname,
1178 strerror(-r),
aa9f1140 1179 NETDEVIF(link->network->bond),
52433f6b
TG
1180 NULL);
1181 link_enter_failed(link);
1182 return r;
1183 }
1184
0ad6148e
MO
1185 link->enslaving ++;
1186 }
1187
d9c67ea1 1188 if (link->network->bridge) {
6c861f0a 1189 log_link_struct(link, LOG_DEBUG,
97578344 1190 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1191 IFNAMSIZ,
af4e9e2c 1192 link->ifname, link->network->bridge->ifname,
aa9f1140 1193 NETDEVIF(link->network->bridge),
0ad6148e
MO
1194 NULL);
1195
3c9b8860
TG
1196 r = netdev_join(link->network->bridge, link,
1197 &netdev_join_handler);
0ad6148e 1198 if (r < 0) {
6c861f0a 1199 log_link_struct(link, LOG_WARNING,
3f265037 1200 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1201 IFNAMSIZ,
3c9b8860
TG
1202 link->ifname, link->network->bridge->ifname,
1203 strerror(-r),
aa9f1140 1204 NETDEVIF(link->network->bridge),
0ad6148e
MO
1205 NULL);
1206 link_enter_failed(link);
1207 return r;
1208 }
1209
52433f6b
TG
1210 link->enslaving ++;
1211 }
1212
6a0a2f86 1213 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
6c861f0a 1214 log_link_struct(link, LOG_DEBUG,
97578344 1215 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1216 IFNAMSIZ,
3c9b8860
TG
1217 link->ifname, netdev->ifname, NETDEVIF(netdev),
1218 NULL);
7951dea2 1219
6a0a2f86 1220 r = netdev_join(netdev, link, &netdev_join_handler);
7951dea2 1221 if (r < 0) {
6c861f0a 1222 log_link_struct(link, LOG_WARNING,
3f265037 1223 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1224 IFNAMSIZ,
3c9b8860
TG
1225 link->ifname, netdev->ifname,
1226 strerror(-r),
6a0a2f86 1227 NETDEVIF(netdev), NULL);
326cb406
SS
1228 link_enter_failed(link);
1229 return r;
1230 }
1231
326cb406
SS
1232 link->enslaving ++;
1233 }
1234
ef1ba606
TG
1235 return 0;
1236}
1237
769d324c 1238static int link_set_ipv4_forward(Link *link) {
5a8bcb67 1239 const char *p = NULL;
43c6d5ab 1240 bool b;
5a8bcb67
LP
1241 int r;
1242
43c6d5ab
LP
1243 b = link_ipv4_forward_enabled(link);
1244
5a8bcb67 1245 p = strappenda("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
43c6d5ab 1246 r = write_string_file_no_create(p, one_zero(b));
5a8bcb67 1247 if (r < 0)
43c6d5ab
LP
1248 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
1249
1250 if (b) {
1251 _cleanup_free_ char *buf = NULL;
1252
1253 /* If IP forwarding is turned on for this interface,
1254 * then propagate this to the global setting. Given
1255 * that turning this on has side-effects on other
1256 * fields, we'll try to avoid doing this unless
1257 * necessary, hence check the previous value
1258 * first. Note that we never turn this option off
1259 * again, since all interfaces we manage do not do
1260 * forwarding anyway by default, and ownership rules
1261 * of this control are so unclear. */
1262
1263 r = read_one_line_file("/proc/sys/net/ipv4/ip_forward", &buf);
1264 if (r < 0)
1265 log_link_warning_errno(link, r, "Cannot read /proc/sys/net/ipv4/ip_forward: %m");
1266 else if (!streq(buf, "1")) {
1267 r = write_string_file_no_create("/proc/sys/net/ipv4/ip_forward", "1");
1268 if (r < 0)
1269 log_link_warning_errno(link, r, "Cannot write /proc/sys/net/ipv4/ip_forward: %m");
1270 }
1271 }
769d324c
LP
1272
1273 return 0;
1274}
1275
1276static int link_set_ipv6_forward(Link *link) {
1277 const char *p = NULL;
1278 int r;
1279
1280 p = strappenda("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
1281 r = write_string_file_no_create(p, one_zero(link_ipv6_forward_enabled(link)));
1282 if (r < 0)
1283 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
5a8bcb67
LP
1284
1285 return 0;
1286}
1287
a748b692 1288static int link_configure(Link *link) {
02b59d57
TG
1289 int r;
1290
ef1ba606 1291 assert(link);
b22d8a00 1292 assert(link->network);
8434fd5c 1293 assert(link->state == LINK_STATE_PENDING);
a748b692 1294
b98b483b
AR
1295 r = link_set_bridge_fdb(link);
1296 if (r < 0)
1297 return r;
1298
769d324c
LP
1299 r = link_set_ipv4_forward(link);
1300 if (r < 0)
1301 return r;
1302
1303 r = link_set_ipv6_forward(link);
5a8bcb67
LP
1304 if (r < 0)
1305 return r;
1306
78c958f8 1307 if (link_ipv4ll_enabled(link)) {
b22d8a00 1308 r = ipv4ll_configure(link);
eb34d4af
TG
1309 if (r < 0)
1310 return r;
1311 }
1312
78c958f8 1313 if (link_dhcp4_enabled(link)) {
3c9b8860 1314 r = dhcp4_configure(link);
eb34d4af
TG
1315 if (r < 0)
1316 return r;
eb34d4af
TG
1317 }
1318
78c958f8 1319 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1320 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1321 if (r < 0)
1322 return r;
1323
1324 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1325 if (r < 0)
1326 return r;
dd43110f
TG
1327 }
1328
78c958f8 1329 if (link_dhcp6_enabled(link)) {
5c79bd79 1330 r = icmp6_configure(link);
4138fb2c
PF
1331 if (r < 0)
1332 return r;
1333 }
1334
ce43e484
SS
1335 if (link_lldp_enabled(link)) {
1336 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
1337 if (r < 0)
1338 return r;
1339
1340 r = sd_lldp_attach_event(link->lldp, NULL, 0);
1341 if (r < 0)
1342 return r;
49699bac
SS
1343
1344 r = sd_lldp_set_callback(link->lldp,
1345 lldp_handler, link);
1346 if (r < 0)
1347 return r;
ce43e484
SS
1348 }
1349
a61bb41c 1350 if (link_has_carrier(link)) {
1e9be60b
TG
1351 r = link_acquire_conf(link);
1352 if (r < 0)
1353 return r;
cc544d5f 1354 }
1e9be60b 1355
3f265037 1356 return link_enter_join_netdev(link);
505f8da7
TG
1357}
1358
3c9b8860
TG
1359static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1360 void *userdata) {
5da8149f 1361 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1362 Network *network;
505f8da7
TG
1363 int r;
1364
1365 assert(link);
1366 assert(link->ifname);
1367 assert(link->manager);
1368
8434fd5c 1369 if (link->state != LINK_STATE_PENDING)
5da8149f 1370 return 1;
505f8da7 1371
79008bdd 1372 log_link_debug(link, "link state is up-to-date");
505f8da7 1373
3c9b8860
TG
1374 r = network_get(link->manager, link->udev_device, link->ifname,
1375 &link->mac, &network);
57bd6899
TG
1376 if (r == -ENOENT) {
1377 link_enter_unmanaged(link);
5da8149f 1378 return 1;
57bd6899
TG
1379 } else if (r < 0)
1380 return r;
505f8da7 1381
bd2efe92 1382 if (link->flags & IFF_LOOPBACK) {
78c958f8 1383 if (network->ipv4ll)
79008bdd 1384 log_link_debug(link, "ignoring IPv4LL for loopback link");
78c958f8 1385
cb9fc36a 1386 if (network->dhcp != ADDRESS_FAMILY_NO)
79008bdd 1387 log_link_debug(link, "ignoring DHCP clients for loopback link");
78c958f8
TG
1388
1389 if (network->dhcp_server)
79008bdd 1390 log_link_debug(link, "ignoring DHCP server for loopback link");
bd2efe92
TG
1391 }
1392
505f8da7
TG
1393 r = network_apply(link->manager, network, link);
1394 if (r < 0)
1395 return r;
1396
a748b692
TG
1397 r = link_configure(link);
1398 if (r < 0)
1399 return r;
1400
5da8149f 1401 return 1;
505f8da7
TG
1402}
1403
4f561e8e
TG
1404int link_initialized(Link *link, struct udev_device *device) {
1405 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1406 int r;
1407
1408 assert(link);
1409 assert(link->manager);
1410 assert(link->manager->rtnl);
1411 assert(device);
1412
8434fd5c 1413 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1414 return 0;
1415
679b3605
TG
1416 if (link->udev_device)
1417 return 0;
1418
79008bdd 1419 log_link_debug(link, "udev initialized link");
4f561e8e
TG
1420
1421 link->udev_device = udev_device_ref(device);
1422
3c9b8860
TG
1423 /* udev has initialized the link, but we don't know if we have yet
1424 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1425 * when it returns we know that the pending NEWLINKs have already been
1426 * processed and that we are up-to-date */
4f561e8e 1427
3c9b8860
TG
1428 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1429 link->ifindex);
4f561e8e
TG
1430 if (r < 0)
1431 return r;
1432
3c9b8860
TG
1433 r = sd_rtnl_call_async(link->manager->rtnl, req,
1434 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1435 if (r < 0)
1436 return r;
1437
5da8149f
TG
1438 link_ref(link);
1439
4f561e8e
TG
1440 return 0;
1441}
1442
5a8bcb67
LP
1443static Address* link_get_equal_address(Link *link, Address *needle) {
1444 Address *i;
1445
1446 assert(link);
1447 assert(needle);
1448
1449 LIST_FOREACH(addresses, i, link->addresses)
1450 if (address_equal(i, needle))
1451 return i;
1452
1453 return NULL;
1454}
1455
45af44d4 1456int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
fbbeb65a
TG
1457 Manager *m = userdata;
1458 Link *link = NULL;
1459 uint16_t type;
1460 _cleanup_address_free_ Address *address = NULL;
5a8bcb67
LP
1461 Address *existing;
1462 char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
c6d3b303 1463 const char *valid_str = NULL;
fbbeb65a
TG
1464 int r, ifindex;
1465
1466 assert(rtnl);
1467 assert(message);
1468 assert(m);
1469
45af44d4
TG
1470 if (sd_rtnl_message_is_error(message)) {
1471 r = sd_rtnl_message_get_errno(message);
1472 if (r < 0)
1473 log_warning_errno(r, "rtnl: failed to receive address: %m");
1474
1475 return 0;
1476 }
1477
fbbeb65a
TG
1478 r = sd_rtnl_message_get_type(message, &type);
1479 if (r < 0) {
1480 log_warning("rtnl: could not get message type");
1481 return 0;
1482 }
1483
1484 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
45af44d4
TG
1485 if (r < 0) {
1486 log_warning_errno(r, "rtnl: could not get ifindex: %m");
1487 return 0;
1488 } else if (ifindex <= 0) {
1489 log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
fbbeb65a
TG
1490 return 0;
1491 } else {
1492 r = link_get(m, ifindex, &link);
1493 if (r < 0 || !link) {
1e19f352 1494 log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
fbbeb65a
TG
1495 return 0;
1496 }
1497 }
1498
1499 r = address_new_dynamic(&address);
1500 if (r < 0)
393c0c5e 1501 return r;
fbbeb65a
TG
1502
1503 r = sd_rtnl_message_addr_get_family(message, &address->family);
1504 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
5a8bcb67 1505 log_link_warning(link, "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1506 return 0;
1507 }
1508
1509 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1510 if (r < 0) {
5a8bcb67 1511 log_link_warning(link, "rtnl: received address with invalid prefixlen, ignoring");
e375dcde
TG
1512 return 0;
1513 }
1514
1515 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1516 if (r < 0) {
5a8bcb67 1517 log_link_warning(link, "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1518 return 0;
1519 }
1520
81163121
TG
1521 r = sd_rtnl_message_addr_get_flags(message, &address->flags);
1522 if (r < 0) {
5a8bcb67 1523 log_link_warning(link, "rtnl: received address with invalid flags, ignoring");
81163121
TG
1524 return 0;
1525 }
1526
fbbeb65a
TG
1527 switch (address->family) {
1528 case AF_INET:
5a8bcb67 1529 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
fbbeb65a 1530 if (r < 0) {
5a8bcb67 1531 log_link_warning(link, "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1532 return 0;
1533 }
1534
1535 break;
1536
1537 case AF_INET6:
5a8bcb67 1538 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
fbbeb65a 1539 if (r < 0) {
5a8bcb67 1540 log_link_warning(link, "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1541 return 0;
1542 }
1543
1544 break;
1545
1546 default:
1547 assert_not_reached("invalid address family");
1548 }
1549
5a8bcb67 1550 if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
79008bdd 1551 log_link_warning(link, "could not print address");
fbbeb65a
TG
1552 return 0;
1553 }
1554
5a8bcb67 1555 r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
c6d3b303
TG
1556 if (r >= 0) {
1557 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
1558 valid_str = "ever";
1559 else
1560 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
1561 address->cinfo.ifa_valid * USEC_PER_SEC,
1562 USEC_PER_SEC);
1563 }
1564
5a8bcb67
LP
1565 existing = link_get_equal_address(link, address);
1566
1567 switch (type) {
1568 case RTM_NEWADDR:
1569 if (existing) {
1570 log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 1571
428fd0a7 1572
5a8bcb67
LP
1573 existing->scope = address->scope;
1574 existing->flags = address->flags;
1575 existing->cinfo = address->cinfo;
428fd0a7 1576
5a8bcb67
LP
1577 } else {
1578 log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 1579
5a8bcb67
LP
1580 LIST_PREPEND(addresses, link->addresses, address);
1581 address_establish(address, link);
fbbeb65a 1582
5a8bcb67 1583 address = NULL;
428fd0a7 1584
5a8bcb67
LP
1585 link_save(link);
1586 }
f5602be9 1587
428fd0a7 1588 break;
5a8bcb67 1589
fbbeb65a 1590 case RTM_DELADDR:
428fd0a7 1591
5a8bcb67
LP
1592 if (existing) {
1593 log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
1594 address_release(existing, link);
1595 LIST_REMOVE(addresses, link->addresses, existing);
1596 address_free(existing);
393c0c5e 1597 } else
5a8bcb67 1598 log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
f5602be9 1599
fbbeb65a
TG
1600 break;
1601 default:
1602 assert_not_reached("Received invalid RTNL message type");
1603 }
1604
1605 return 1;
1606}
1607
505f8da7
TG
1608int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1609 Link *link;
1610 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1611 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1612 int r;
1613
1614 assert(m);
fbbeb65a 1615 assert(m->rtnl);
505f8da7
TG
1616 assert(message);
1617 assert(ret);
1618
1619 r = link_new(m, message, ret);
1620 if (r < 0)
1621 return r;
1622
1623 link = *ret;
1624
79008bdd 1625 log_link_debug(link, "link %d added", link->ifindex);
505f8da7
TG
1626
1627 if (detect_container(NULL) <= 0) {
1628 /* not in a container, udev will be around */
ae06ab10 1629 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1630 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1631 if (!device) {
79008bdd 1632 log_link_warning(link,
3c9b8860 1633 "could not find udev device: %m");
9fecce80 1634 return -errno;
505f8da7
TG
1635 }
1636
3c4cb064 1637 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1638 /* not yet ready */
79008bdd 1639 log_link_debug(link, "link pending udev initialization...");
505f8da7 1640 return 0;
3c4cb064 1641 }
505f8da7 1642
4f561e8e
TG
1643 r = link_initialized(link, device);
1644 if (r < 0)
1645 return r;
1646 } else {
5da8149f
TG
1647 /* we are calling a callback directly, so must take a ref */
1648 link_ref(link);
1649
4f561e8e
TG
1650 r = link_initialized_and_synced(m->rtnl, NULL, link);
1651 if (r < 0)
1652 return r;
1653 }
505f8da7 1654
a748b692
TG
1655 return 0;
1656}
1657
22936833 1658int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1659 struct ether_addr mac;
ca4e095a 1660 const char *ifname;
afe7fd56 1661 uint32_t mtu;
a61bb41c 1662 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
1663 int r;
1664
dd3efc09 1665 assert(link);
b8941f74 1666 assert(link->ifname);
22936833
TG
1667 assert(m);
1668
7619683b
TG
1669 if (link->state == LINK_STATE_LINGER) {
1670 link_ref(link);
79008bdd 1671 log_link_info(link, "link readded");
7619683b
TG
1672 link->state = LINK_STATE_ENSLAVING;
1673 }
1674
b8941f74
TG
1675 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1676 if (r >= 0 && !streq(ifname, link->ifname)) {
79008bdd 1677 log_link_info(link, "renamed to %s", ifname);
b8941f74
TG
1678
1679 free(link->ifname);
1680 link->ifname = strdup(ifname);
1681 if (!link->ifname)
1682 return -ENOMEM;
1683 }
1684
afe7fd56
TG
1685 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1686 if (r >= 0 && mtu > 0) {
1687 link->mtu = mtu;
1688 if (!link->original_mtu) {
1689 link->original_mtu = mtu;
79008bdd 1690 log_link_debug(link, "saved original MTU: %"
afe7fd56
TG
1691 PRIu32, link->original_mtu);
1692 }
1693
1694 if (link->dhcp_client) {
3c9b8860
TG
1695 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1696 link->mtu);
afe7fd56 1697 if (r < 0) {
79008bdd 1698 log_link_warning(link,
3c9b8860 1699 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1700 strerror(-r));
1701 return r;
1702 }
1703 }
9842de0d 1704 }
69629de9 1705
e9189a1f
TG
1706 /* The kernel may broadcast NEWLINK messages without the MAC address
1707 set, simply ignore them. */
c49b33ac 1708 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1709 if (r >= 0) {
3c9b8860
TG
1710 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1711 ETH_ALEN)) {
c49b33ac 1712
3c9b8860
TG
1713 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1714 ETH_ALEN);
c49b33ac 1715
79008bdd 1716 log_link_debug(link, "MAC address: "
20861203
TG
1717 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1718 mac.ether_addr_octet[0],
1719 mac.ether_addr_octet[1],
1720 mac.ether_addr_octet[2],
1721 mac.ether_addr_octet[3],
1722 mac.ether_addr_octet[4],
1723 mac.ether_addr_octet[5]);
c49b33ac 1724
20861203
TG
1725 if (link->ipv4ll) {
1726 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1727 if (r < 0) {
79008bdd 1728 log_link_warning(link,
3c9b8860 1729 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1730 strerror(-r));
1731 return r;
1732 }
c49b33ac 1733 }
c49b33ac 1734
20861203 1735 if (link->dhcp_client) {
3c9b8860 1736 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
1737 (const uint8_t *) &link->mac,
1738 sizeof (link->mac),
1739 ARPHRD_ETHER);
20861203 1740 if (r < 0) {
79008bdd 1741 log_link_warning(link,
3c9b8860 1742 "Could not update MAC address in DHCP client: %s",
20861203
TG
1743 strerror(-r));
1744 return r;
1745 }
c49b33ac 1746 }
4138fb2c
PF
1747
1748 if (link->dhcp6_client) {
1749 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
1750 (const uint8_t *) &link->mac,
1751 sizeof (link->mac),
1752 ARPHRD_ETHER);
4138fb2c 1753 if (r < 0) {
79008bdd 1754 log_link_warning(link,
3c9b8860 1755 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1756 strerror(-r));
1757 return r;
1758 }
1759 }
c49b33ac 1760 }
4f882b2a
TG
1761 }
1762
a61bb41c
TG
1763 had_carrier = link_has_carrier(link);
1764
1765 r = link_update_flags(link, m);
1766 if (r < 0)
1767 return r;
1768
1769 carrier_gained = !had_carrier && link_has_carrier(link);
1770 carrier_lost = had_carrier && !link_has_carrier(link);
1771
1772 if (carrier_gained) {
79008bdd 1773 log_link_info(link, "gained carrier");
a61bb41c
TG
1774
1775 if (link->network) {
1776 r = link_acquire_conf(link);
1777 if (r < 0) {
1778 link_enter_failed(link);
1779 return r;
1780 }
1781 }
1782 } else if (carrier_lost) {
79008bdd 1783 log_link_info(link, "lost carrier");
a61bb41c
TG
1784
1785 r = link_stop_clients(link);
1786 if (r < 0) {
1787 link_enter_failed(link);
1788 return r;
1789 }
1790 }
1791
1792 return 0;
dd3efc09 1793}
fe8db0c5 1794
e375dcde
TG
1795static void link_update_operstate(Link *link) {
1796
1797 assert(link);
1798
1799 if (link->kernel_operstate == IF_OPER_DORMANT)
1800 link->operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 1801 else if (link_has_carrier(link)) {
e375dcde
TG
1802 Address *address;
1803 uint8_t scope = RT_SCOPE_NOWHERE;
1804
1805 /* if we have carrier, check what addresses we have */
1806 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
1807 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
1808 continue;
1809
e375dcde
TG
1810 if (address->scope < scope)
1811 scope = address->scope;
1812 }
1813
1814 if (scope < RT_SCOPE_SITE)
1815 /* universally accessible addresses found */
1816 link->operstate = LINK_OPERSTATE_ROUTABLE;
1817 else if (scope < RT_SCOPE_HOST)
1818 /* only link or site local addresses found */
1819 link->operstate = LINK_OPERSTATE_DEGRADED;
1820 else
1821 /* no useful addresses found */
1822 link->operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 1823 } else if (link->flags & IFF_UP)
d3df0e39 1824 link->operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 1825 else
d3df0e39 1826 link->operstate = LINK_OPERSTATE_OFF;
e375dcde
TG
1827}
1828
fe8db0c5 1829int link_save(Link *link) {
68a8723c 1830 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1831 _cleanup_fclose_ FILE *f = NULL;
e375dcde 1832 const char *admin_state, *oper_state;
fe8db0c5
TG
1833 int r;
1834
1835 assert(link);
1836 assert(link->state_file);
68a8723c 1837 assert(link->lease_file);
bbf7c048
TG
1838 assert(link->manager);
1839
e375dcde
TG
1840 link_update_operstate(link);
1841
bbf7c048
TG
1842 r = manager_save(link->manager);
1843 if (r < 0)
1844 return r;
fe8db0c5 1845
370e9930
TG
1846 if (link->state == LINK_STATE_LINGER) {
1847 unlink(link->state_file);
1848 return 0;
1849 }
1850
deb2e523
TG
1851 admin_state = link_state_to_string(link->state);
1852 assert(admin_state);
1853
e375dcde
TG
1854 oper_state = link_operstate_to_string(link->operstate);
1855 assert(oper_state);
deb2e523 1856
fe8db0c5
TG
1857 r = fopen_temporary(link->state_file, &f, &temp_path);
1858 if (r < 0)
c2d6bd61 1859 return r;
fe8db0c5
TG
1860
1861 fchmod(fileno(f), 0644);
1862
1863 fprintf(f,
1864 "# This is private data. Do not parse.\n"
deb2e523 1865 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
1866 "OPER_STATE=%s\n",
1867 admin_state, oper_state);
fe8db0c5 1868
bcb7a07e 1869 if (link->network) {
ea352b40
LP
1870 char **address, **domain;
1871 bool space;
b0e39c82 1872
adc5b2e2
TG
1873 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
1874
b0e39c82 1875 fputs("DNS=", f);
ea352b40
LP
1876 space = false;
1877 STRV_FOREACH(address, link->network->dns) {
1878 if (space)
1879 fputc(' ', f);
1880 fputs(*address, f);
1881 space = true;
1882 }
d5314fff 1883
b0e39c82
TG
1884 if (link->network->dhcp_dns &&
1885 link->dhcp_lease) {
1886 const struct in_addr *addresses;
1887
1888 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
1889 if (r > 0) {
ea352b40
LP
1890 if (space)
1891 fputc(' ', f);
b0e39c82 1892 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1893 }
1894 }
1895
b0e39c82
TG
1896 fputs("\n", f);
1897
1898 fprintf(f, "NTP=");
ea352b40
LP
1899 space = false;
1900 STRV_FOREACH(address, link->network->ntp) {
1901 if (space)
1902 fputc(' ', f);
1903 fputs(*address, f);
1904 space = true;
1905 }
d5314fff 1906
b0e39c82
TG
1907 if (link->network->dhcp_ntp &&
1908 link->dhcp_lease) {
1909 const struct in_addr *addresses;
1910
1911 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
1912 if (r > 0) {
ea352b40
LP
1913 if (space)
1914 fputc(' ', f);
b0e39c82 1915 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1916 }
1917 }
1918
b0e39c82 1919 fputs("\n", f);
bd8f6538 1920
6192b846 1921 fprintf(f, "DOMAINS=");
ea352b40
LP
1922 space = false;
1923 STRV_FOREACH(domain, link->network->domains) {
1924 if (space)
1925 fputc(' ', f);
1926 fputs(*domain, f);
1927 space = true;
1928 }
d5314fff 1929
ad0734e8 1930 if (link->network->dhcp_domains &&
9b4d1882
TG
1931 link->dhcp_lease) {
1932 const char *domainname;
1933
1934 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 1935 if (r >= 0) {
ea352b40
LP
1936 if (space)
1937 fputc(' ', f);
6192b846 1938 fputs(domainname, f);
6192b846 1939 }
9b4d1882
TG
1940 }
1941
6192b846
TG
1942 fputs("\n", f);
1943
67272d15
TG
1944 fprintf(f, "WILDCARD_DOMAIN=%s\n",
1945 yes_no(link->network->wildcard_domain));
1946
3c9b8860
TG
1947 fprintf(f, "LLMNR=%s\n",
1948 llmnr_support_to_string(link->network->llmnr));
bcb7a07e 1949 }
7374f9d8 1950
fe8db0c5 1951 if (link->dhcp_lease) {
d9876a52
TG
1952 assert(link->network);
1953
1dc24d5f 1954 r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 1955 if (r < 0)
c2d6bd61 1956 goto fail;
fe8db0c5 1957
7374f9d8 1958 fprintf(f,
b0e39c82
TG
1959 "DHCP_LEASE=%s\n",
1960 link->lease_file);
deb2e523 1961 } else
68a8723c 1962 unlink(link->lease_file);
fe8db0c5 1963
49699bac
SS
1964 if (link->lldp) {
1965 assert(link->network);
1966
1967 r = sd_lldp_save(link->lldp, link->lldp_file);
1968 if (r < 0)
1969 goto fail;
1970
1971 fprintf(f,
1972 "LLDP_FILE=%s\n",
1973 link->lldp_file);
1974 } else
1975 unlink(link->lldp_file);
1976
c2d6bd61
LP
1977 r = fflush_and_check(f);
1978 if (r < 0)
1979 goto fail;
fe8db0c5 1980
c2d6bd61 1981 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 1982 r = -errno;
c2d6bd61 1983 goto fail;
fe8db0c5
TG
1984 }
1985
c2d6bd61 1986 return 0;
c2d6bd61 1987fail:
79008bdd 1988 log_link_error(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
c2d6bd61
LP
1989 unlink(link->state_file);
1990 unlink(temp_path);
fe8db0c5
TG
1991 return r;
1992}
1993
1994static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 1995 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
1996 [LINK_STATE_ENSLAVING] = "configuring",
1997 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1998 [LINK_STATE_SETTING_ROUTES] = "configuring",
1999 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 2000 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 2001 [LINK_STATE_FAILED] = "failed",
370e9930 2002 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
2003};
2004
2005DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
2006
2007static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
2008 [LINK_OPERSTATE_OFF] = "off",
2009 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
2010 [LINK_OPERSTATE_DORMANT] = "dormant",
2011 [LINK_OPERSTATE_CARRIER] = "carrier",
2012 [LINK_OPERSTATE_DEGRADED] = "degraded",
2013 [LINK_OPERSTATE_ROUTABLE] = "routable",
2014};
2015
2016DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);