]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
udev: make use of new one_zero() helper where appropriate
[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
LP
1239 const char *p = NULL;
1240 int r;
1241
1242 p = strappenda("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
769d324c 1243 r = write_string_file_no_create(p, one_zero(link_ipv4_forward_enabled(link)));
5a8bcb67 1244 if (r < 0)
769d324c
LP
1245 log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface: %m");
1246
1247 return 0;
1248}
1249
1250static int link_set_ipv6_forward(Link *link) {
1251 const char *p = NULL;
1252 int r;
1253
1254 p = strappenda("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
1255 r = write_string_file_no_create(p, one_zero(link_ipv6_forward_enabled(link)));
1256 if (r < 0)
1257 log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
5a8bcb67
LP
1258
1259 return 0;
1260}
1261
a748b692 1262static int link_configure(Link *link) {
02b59d57
TG
1263 int r;
1264
ef1ba606 1265 assert(link);
b22d8a00 1266 assert(link->network);
8434fd5c 1267 assert(link->state == LINK_STATE_PENDING);
a748b692 1268
b98b483b
AR
1269 r = link_set_bridge_fdb(link);
1270 if (r < 0)
1271 return r;
1272
769d324c
LP
1273 r = link_set_ipv4_forward(link);
1274 if (r < 0)
1275 return r;
1276
1277 r = link_set_ipv6_forward(link);
5a8bcb67
LP
1278 if (r < 0)
1279 return r;
1280
78c958f8 1281 if (link_ipv4ll_enabled(link)) {
b22d8a00 1282 r = ipv4ll_configure(link);
eb34d4af
TG
1283 if (r < 0)
1284 return r;
1285 }
1286
78c958f8 1287 if (link_dhcp4_enabled(link)) {
3c9b8860 1288 r = dhcp4_configure(link);
eb34d4af
TG
1289 if (r < 0)
1290 return r;
eb34d4af
TG
1291 }
1292
78c958f8 1293 if (link_dhcp4_server_enabled(link)) {
dd43110f
TG
1294 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1295 if (r < 0)
1296 return r;
1297
1298 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1299 if (r < 0)
1300 return r;
dd43110f
TG
1301 }
1302
78c958f8 1303 if (link_dhcp6_enabled(link)) {
5c79bd79 1304 r = icmp6_configure(link);
4138fb2c
PF
1305 if (r < 0)
1306 return r;
1307 }
1308
ce43e484
SS
1309 if (link_lldp_enabled(link)) {
1310 r = sd_lldp_new(link->ifindex, link->ifname, &link->mac, &link->lldp);
1311 if (r < 0)
1312 return r;
1313
1314 r = sd_lldp_attach_event(link->lldp, NULL, 0);
1315 if (r < 0)
1316 return r;
49699bac
SS
1317
1318 r = sd_lldp_set_callback(link->lldp,
1319 lldp_handler, link);
1320 if (r < 0)
1321 return r;
ce43e484
SS
1322 }
1323
a61bb41c 1324 if (link_has_carrier(link)) {
1e9be60b
TG
1325 r = link_acquire_conf(link);
1326 if (r < 0)
1327 return r;
cc544d5f 1328 }
1e9be60b 1329
3f265037 1330 return link_enter_join_netdev(link);
505f8da7
TG
1331}
1332
3c9b8860
TG
1333static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1334 void *userdata) {
5da8149f 1335 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1336 Network *network;
505f8da7
TG
1337 int r;
1338
1339 assert(link);
1340 assert(link->ifname);
1341 assert(link->manager);
1342
8434fd5c 1343 if (link->state != LINK_STATE_PENDING)
5da8149f 1344 return 1;
505f8da7 1345
79008bdd 1346 log_link_debug(link, "link state is up-to-date");
505f8da7 1347
3c9b8860
TG
1348 r = network_get(link->manager, link->udev_device, link->ifname,
1349 &link->mac, &network);
57bd6899
TG
1350 if (r == -ENOENT) {
1351 link_enter_unmanaged(link);
5da8149f 1352 return 1;
57bd6899
TG
1353 } else if (r < 0)
1354 return r;
505f8da7 1355
bd2efe92 1356 if (link->flags & IFF_LOOPBACK) {
78c958f8 1357 if (network->ipv4ll)
79008bdd 1358 log_link_debug(link, "ignoring IPv4LL for loopback link");
78c958f8 1359
cb9fc36a 1360 if (network->dhcp != ADDRESS_FAMILY_NO)
79008bdd 1361 log_link_debug(link, "ignoring DHCP clients for loopback link");
78c958f8
TG
1362
1363 if (network->dhcp_server)
79008bdd 1364 log_link_debug(link, "ignoring DHCP server for loopback link");
bd2efe92
TG
1365 }
1366
505f8da7
TG
1367 r = network_apply(link->manager, network, link);
1368 if (r < 0)
1369 return r;
1370
a748b692
TG
1371 r = link_configure(link);
1372 if (r < 0)
1373 return r;
1374
5da8149f 1375 return 1;
505f8da7
TG
1376}
1377
4f561e8e
TG
1378int link_initialized(Link *link, struct udev_device *device) {
1379 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1380 int r;
1381
1382 assert(link);
1383 assert(link->manager);
1384 assert(link->manager->rtnl);
1385 assert(device);
1386
8434fd5c 1387 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1388 return 0;
1389
679b3605
TG
1390 if (link->udev_device)
1391 return 0;
1392
79008bdd 1393 log_link_debug(link, "udev initialized link");
4f561e8e
TG
1394
1395 link->udev_device = udev_device_ref(device);
1396
3c9b8860
TG
1397 /* udev has initialized the link, but we don't know if we have yet
1398 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1399 * when it returns we know that the pending NEWLINKs have already been
1400 * processed and that we are up-to-date */
4f561e8e 1401
3c9b8860
TG
1402 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1403 link->ifindex);
4f561e8e
TG
1404 if (r < 0)
1405 return r;
1406
3c9b8860
TG
1407 r = sd_rtnl_call_async(link->manager->rtnl, req,
1408 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1409 if (r < 0)
1410 return r;
1411
5da8149f
TG
1412 link_ref(link);
1413
4f561e8e
TG
1414 return 0;
1415}
1416
5a8bcb67
LP
1417static Address* link_get_equal_address(Link *link, Address *needle) {
1418 Address *i;
1419
1420 assert(link);
1421 assert(needle);
1422
1423 LIST_FOREACH(addresses, i, link->addresses)
1424 if (address_equal(i, needle))
1425 return i;
1426
1427 return NULL;
1428}
1429
45af44d4 1430int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
fbbeb65a
TG
1431 Manager *m = userdata;
1432 Link *link = NULL;
1433 uint16_t type;
1434 _cleanup_address_free_ Address *address = NULL;
5a8bcb67
LP
1435 Address *existing;
1436 char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
c6d3b303 1437 const char *valid_str = NULL;
fbbeb65a
TG
1438 int r, ifindex;
1439
1440 assert(rtnl);
1441 assert(message);
1442 assert(m);
1443
45af44d4
TG
1444 if (sd_rtnl_message_is_error(message)) {
1445 r = sd_rtnl_message_get_errno(message);
1446 if (r < 0)
1447 log_warning_errno(r, "rtnl: failed to receive address: %m");
1448
1449 return 0;
1450 }
1451
fbbeb65a
TG
1452 r = sd_rtnl_message_get_type(message, &type);
1453 if (r < 0) {
1454 log_warning("rtnl: could not get message type");
1455 return 0;
1456 }
1457
1458 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
45af44d4
TG
1459 if (r < 0) {
1460 log_warning_errno(r, "rtnl: could not get ifindex: %m");
1461 return 0;
1462 } else if (ifindex <= 0) {
1463 log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
fbbeb65a
TG
1464 return 0;
1465 } else {
1466 r = link_get(m, ifindex, &link);
1467 if (r < 0 || !link) {
1e19f352 1468 log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
fbbeb65a
TG
1469 return 0;
1470 }
1471 }
1472
1473 r = address_new_dynamic(&address);
1474 if (r < 0)
393c0c5e 1475 return r;
fbbeb65a
TG
1476
1477 r = sd_rtnl_message_addr_get_family(message, &address->family);
1478 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
5a8bcb67 1479 log_link_warning(link, "rtnl: received address with invalid family, ignoring");
fbbeb65a
TG
1480 return 0;
1481 }
1482
1483 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1484 if (r < 0) {
5a8bcb67 1485 log_link_warning(link, "rtnl: received address with invalid prefixlen, ignoring");
e375dcde
TG
1486 return 0;
1487 }
1488
1489 r = sd_rtnl_message_addr_get_scope(message, &address->scope);
1490 if (r < 0) {
5a8bcb67 1491 log_link_warning(link, "rtnl: received address with invalid scope, ignoring");
fbbeb65a
TG
1492 return 0;
1493 }
1494
81163121
TG
1495 r = sd_rtnl_message_addr_get_flags(message, &address->flags);
1496 if (r < 0) {
5a8bcb67 1497 log_link_warning(link, "rtnl: received address with invalid flags, ignoring");
81163121
TG
1498 return 0;
1499 }
1500
fbbeb65a
TG
1501 switch (address->family) {
1502 case AF_INET:
5a8bcb67 1503 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
fbbeb65a 1504 if (r < 0) {
5a8bcb67 1505 log_link_warning(link, "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1506 return 0;
1507 }
1508
1509 break;
1510
1511 case AF_INET6:
5a8bcb67 1512 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
fbbeb65a 1513 if (r < 0) {
5a8bcb67 1514 log_link_warning(link, "rtnl: received address without valid address, ignoring");
fbbeb65a
TG
1515 return 0;
1516 }
1517
1518 break;
1519
1520 default:
1521 assert_not_reached("invalid address family");
1522 }
1523
5a8bcb67 1524 if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
79008bdd 1525 log_link_warning(link, "could not print address");
fbbeb65a
TG
1526 return 0;
1527 }
1528
5a8bcb67 1529 r = sd_rtnl_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
c6d3b303
TG
1530 if (r >= 0) {
1531 if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
1532 valid_str = "ever";
1533 else
1534 valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
1535 address->cinfo.ifa_valid * USEC_PER_SEC,
1536 USEC_PER_SEC);
1537 }
1538
5a8bcb67
LP
1539 existing = link_get_equal_address(link, address);
1540
1541 switch (type) {
1542 case RTM_NEWADDR:
1543 if (existing) {
1544 log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 1545
428fd0a7 1546
5a8bcb67
LP
1547 existing->scope = address->scope;
1548 existing->flags = address->flags;
1549 existing->cinfo = address->cinfo;
428fd0a7 1550
5a8bcb67
LP
1551 } else {
1552 log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
428fd0a7 1553
5a8bcb67
LP
1554 LIST_PREPEND(addresses, link->addresses, address);
1555 address_establish(address, link);
fbbeb65a 1556
5a8bcb67 1557 address = NULL;
428fd0a7 1558
5a8bcb67
LP
1559 link_save(link);
1560 }
f5602be9 1561
428fd0a7 1562 break;
5a8bcb67 1563
fbbeb65a 1564 case RTM_DELADDR:
428fd0a7 1565
5a8bcb67
LP
1566 if (existing) {
1567 log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
1568 address_release(existing, link);
1569 LIST_REMOVE(addresses, link->addresses, existing);
1570 address_free(existing);
393c0c5e 1571 } else
5a8bcb67 1572 log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
f5602be9 1573
fbbeb65a
TG
1574 break;
1575 default:
1576 assert_not_reached("Received invalid RTNL message type");
1577 }
1578
1579 return 1;
1580}
1581
505f8da7
TG
1582int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1583 Link *link;
1584 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1585 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1586 int r;
1587
1588 assert(m);
fbbeb65a 1589 assert(m->rtnl);
505f8da7
TG
1590 assert(message);
1591 assert(ret);
1592
1593 r = link_new(m, message, ret);
1594 if (r < 0)
1595 return r;
1596
1597 link = *ret;
1598
79008bdd 1599 log_link_debug(link, "link %d added", link->ifindex);
505f8da7
TG
1600
1601 if (detect_container(NULL) <= 0) {
1602 /* not in a container, udev will be around */
ae06ab10 1603 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1604 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1605 if (!device) {
79008bdd 1606 log_link_warning(link,
3c9b8860 1607 "could not find udev device: %m");
9fecce80 1608 return -errno;
505f8da7
TG
1609 }
1610
3c4cb064 1611 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1612 /* not yet ready */
79008bdd 1613 log_link_debug(link, "link pending udev initialization...");
505f8da7 1614 return 0;
3c4cb064 1615 }
505f8da7 1616
4f561e8e
TG
1617 r = link_initialized(link, device);
1618 if (r < 0)
1619 return r;
1620 } else {
5da8149f
TG
1621 /* we are calling a callback directly, so must take a ref */
1622 link_ref(link);
1623
4f561e8e
TG
1624 r = link_initialized_and_synced(m->rtnl, NULL, link);
1625 if (r < 0)
1626 return r;
1627 }
505f8da7 1628
a748b692
TG
1629 return 0;
1630}
1631
22936833 1632int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1633 struct ether_addr mac;
ca4e095a 1634 const char *ifname;
afe7fd56 1635 uint32_t mtu;
a61bb41c 1636 bool had_carrier, carrier_gained, carrier_lost;
22936833
TG
1637 int r;
1638
dd3efc09 1639 assert(link);
b8941f74 1640 assert(link->ifname);
22936833
TG
1641 assert(m);
1642
7619683b
TG
1643 if (link->state == LINK_STATE_LINGER) {
1644 link_ref(link);
79008bdd 1645 log_link_info(link, "link readded");
7619683b
TG
1646 link->state = LINK_STATE_ENSLAVING;
1647 }
1648
b8941f74
TG
1649 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1650 if (r >= 0 && !streq(ifname, link->ifname)) {
79008bdd 1651 log_link_info(link, "renamed to %s", ifname);
b8941f74
TG
1652
1653 free(link->ifname);
1654 link->ifname = strdup(ifname);
1655 if (!link->ifname)
1656 return -ENOMEM;
1657 }
1658
afe7fd56
TG
1659 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1660 if (r >= 0 && mtu > 0) {
1661 link->mtu = mtu;
1662 if (!link->original_mtu) {
1663 link->original_mtu = mtu;
79008bdd 1664 log_link_debug(link, "saved original MTU: %"
afe7fd56
TG
1665 PRIu32, link->original_mtu);
1666 }
1667
1668 if (link->dhcp_client) {
3c9b8860
TG
1669 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1670 link->mtu);
afe7fd56 1671 if (r < 0) {
79008bdd 1672 log_link_warning(link,
3c9b8860 1673 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1674 strerror(-r));
1675 return r;
1676 }
1677 }
9842de0d 1678 }
69629de9 1679
e9189a1f
TG
1680 /* The kernel may broadcast NEWLINK messages without the MAC address
1681 set, simply ignore them. */
c49b33ac 1682 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1683 if (r >= 0) {
3c9b8860
TG
1684 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1685 ETH_ALEN)) {
c49b33ac 1686
3c9b8860
TG
1687 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1688 ETH_ALEN);
c49b33ac 1689
79008bdd 1690 log_link_debug(link, "MAC address: "
20861203
TG
1691 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1692 mac.ether_addr_octet[0],
1693 mac.ether_addr_octet[1],
1694 mac.ether_addr_octet[2],
1695 mac.ether_addr_octet[3],
1696 mac.ether_addr_octet[4],
1697 mac.ether_addr_octet[5]);
c49b33ac 1698
20861203
TG
1699 if (link->ipv4ll) {
1700 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1701 if (r < 0) {
79008bdd 1702 log_link_warning(link,
3c9b8860 1703 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1704 strerror(-r));
1705 return r;
1706 }
c49b33ac 1707 }
c49b33ac 1708
20861203 1709 if (link->dhcp_client) {
3c9b8860 1710 r = sd_dhcp_client_set_mac(link->dhcp_client,
76253e73
DW
1711 (const uint8_t *) &link->mac,
1712 sizeof (link->mac),
1713 ARPHRD_ETHER);
20861203 1714 if (r < 0) {
79008bdd 1715 log_link_warning(link,
3c9b8860 1716 "Could not update MAC address in DHCP client: %s",
20861203
TG
1717 strerror(-r));
1718 return r;
1719 }
c49b33ac 1720 }
4138fb2c
PF
1721
1722 if (link->dhcp6_client) {
1723 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
76253e73
DW
1724 (const uint8_t *) &link->mac,
1725 sizeof (link->mac),
1726 ARPHRD_ETHER);
4138fb2c 1727 if (r < 0) {
79008bdd 1728 log_link_warning(link,
3c9b8860 1729 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1730 strerror(-r));
1731 return r;
1732 }
1733 }
c49b33ac 1734 }
4f882b2a
TG
1735 }
1736
a61bb41c
TG
1737 had_carrier = link_has_carrier(link);
1738
1739 r = link_update_flags(link, m);
1740 if (r < 0)
1741 return r;
1742
1743 carrier_gained = !had_carrier && link_has_carrier(link);
1744 carrier_lost = had_carrier && !link_has_carrier(link);
1745
1746 if (carrier_gained) {
79008bdd 1747 log_link_info(link, "gained carrier");
a61bb41c
TG
1748
1749 if (link->network) {
1750 r = link_acquire_conf(link);
1751 if (r < 0) {
1752 link_enter_failed(link);
1753 return r;
1754 }
1755 }
1756 } else if (carrier_lost) {
79008bdd 1757 log_link_info(link, "lost carrier");
a61bb41c
TG
1758
1759 r = link_stop_clients(link);
1760 if (r < 0) {
1761 link_enter_failed(link);
1762 return r;
1763 }
1764 }
1765
1766 return 0;
dd3efc09 1767}
fe8db0c5 1768
e375dcde
TG
1769static void link_update_operstate(Link *link) {
1770
1771 assert(link);
1772
1773 if (link->kernel_operstate == IF_OPER_DORMANT)
1774 link->operstate = LINK_OPERSTATE_DORMANT;
a61bb41c 1775 else if (link_has_carrier(link)) {
e375dcde
TG
1776 Address *address;
1777 uint8_t scope = RT_SCOPE_NOWHERE;
1778
1779 /* if we have carrier, check what addresses we have */
1780 LIST_FOREACH(addresses, address, link->addresses) {
81163121
TG
1781 if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
1782 continue;
1783
e375dcde
TG
1784 if (address->scope < scope)
1785 scope = address->scope;
1786 }
1787
1788 if (scope < RT_SCOPE_SITE)
1789 /* universally accessible addresses found */
1790 link->operstate = LINK_OPERSTATE_ROUTABLE;
1791 else if (scope < RT_SCOPE_HOST)
1792 /* only link or site local addresses found */
1793 link->operstate = LINK_OPERSTATE_DEGRADED;
1794 else
1795 /* no useful addresses found */
1796 link->operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 1797 } else if (link->flags & IFF_UP)
d3df0e39 1798 link->operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 1799 else
d3df0e39 1800 link->operstate = LINK_OPERSTATE_OFF;
e375dcde
TG
1801}
1802
fe8db0c5 1803int link_save(Link *link) {
68a8723c 1804 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1805 _cleanup_fclose_ FILE *f = NULL;
e375dcde 1806 const char *admin_state, *oper_state;
fe8db0c5
TG
1807 int r;
1808
1809 assert(link);
1810 assert(link->state_file);
68a8723c 1811 assert(link->lease_file);
bbf7c048
TG
1812 assert(link->manager);
1813
e375dcde
TG
1814 link_update_operstate(link);
1815
bbf7c048
TG
1816 r = manager_save(link->manager);
1817 if (r < 0)
1818 return r;
fe8db0c5 1819
370e9930
TG
1820 if (link->state == LINK_STATE_LINGER) {
1821 unlink(link->state_file);
1822 return 0;
1823 }
1824
deb2e523
TG
1825 admin_state = link_state_to_string(link->state);
1826 assert(admin_state);
1827
e375dcde
TG
1828 oper_state = link_operstate_to_string(link->operstate);
1829 assert(oper_state);
deb2e523 1830
fe8db0c5
TG
1831 r = fopen_temporary(link->state_file, &f, &temp_path);
1832 if (r < 0)
c2d6bd61 1833 return r;
fe8db0c5
TG
1834
1835 fchmod(fileno(f), 0644);
1836
1837 fprintf(f,
1838 "# This is private data. Do not parse.\n"
deb2e523 1839 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
1840 "OPER_STATE=%s\n",
1841 admin_state, oper_state);
fe8db0c5 1842
bcb7a07e 1843 if (link->network) {
ea352b40
LP
1844 char **address, **domain;
1845 bool space;
b0e39c82 1846
adc5b2e2
TG
1847 fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
1848
b0e39c82 1849 fputs("DNS=", f);
ea352b40
LP
1850 space = false;
1851 STRV_FOREACH(address, link->network->dns) {
1852 if (space)
1853 fputc(' ', f);
1854 fputs(*address, f);
1855 space = true;
1856 }
d5314fff 1857
b0e39c82
TG
1858 if (link->network->dhcp_dns &&
1859 link->dhcp_lease) {
1860 const struct in_addr *addresses;
1861
1862 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
1863 if (r > 0) {
ea352b40
LP
1864 if (space)
1865 fputc(' ', f);
b0e39c82 1866 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1867 }
1868 }
1869
b0e39c82
TG
1870 fputs("\n", f);
1871
1872 fprintf(f, "NTP=");
ea352b40
LP
1873 space = false;
1874 STRV_FOREACH(address, link->network->ntp) {
1875 if (space)
1876 fputc(' ', f);
1877 fputs(*address, f);
1878 space = true;
1879 }
d5314fff 1880
b0e39c82
TG
1881 if (link->network->dhcp_ntp &&
1882 link->dhcp_lease) {
1883 const struct in_addr *addresses;
1884
1885 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
1886 if (r > 0) {
ea352b40
LP
1887 if (space)
1888 fputc(' ', f);
b0e39c82 1889 serialize_in_addrs(f, addresses, r);
b0e39c82
TG
1890 }
1891 }
1892
b0e39c82 1893 fputs("\n", f);
bd8f6538 1894
6192b846 1895 fprintf(f, "DOMAINS=");
ea352b40
LP
1896 space = false;
1897 STRV_FOREACH(domain, link->network->domains) {
1898 if (space)
1899 fputc(' ', f);
1900 fputs(*domain, f);
1901 space = true;
1902 }
d5314fff 1903
ad0734e8 1904 if (link->network->dhcp_domains &&
9b4d1882
TG
1905 link->dhcp_lease) {
1906 const char *domainname;
1907
1908 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
6192b846 1909 if (r >= 0) {
ea352b40
LP
1910 if (space)
1911 fputc(' ', f);
6192b846 1912 fputs(domainname, f);
6192b846 1913 }
9b4d1882
TG
1914 }
1915
6192b846
TG
1916 fputs("\n", f);
1917
67272d15
TG
1918 fprintf(f, "WILDCARD_DOMAIN=%s\n",
1919 yes_no(link->network->wildcard_domain));
1920
3c9b8860
TG
1921 fprintf(f, "LLMNR=%s\n",
1922 llmnr_support_to_string(link->network->llmnr));
bcb7a07e 1923 }
7374f9d8 1924
fe8db0c5 1925 if (link->dhcp_lease) {
d9876a52
TG
1926 assert(link->network);
1927
1dc24d5f 1928 r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 1929 if (r < 0)
c2d6bd61 1930 goto fail;
fe8db0c5 1931
7374f9d8 1932 fprintf(f,
b0e39c82
TG
1933 "DHCP_LEASE=%s\n",
1934 link->lease_file);
deb2e523 1935 } else
68a8723c 1936 unlink(link->lease_file);
fe8db0c5 1937
49699bac
SS
1938 if (link->lldp) {
1939 assert(link->network);
1940
1941 r = sd_lldp_save(link->lldp, link->lldp_file);
1942 if (r < 0)
1943 goto fail;
1944
1945 fprintf(f,
1946 "LLDP_FILE=%s\n",
1947 link->lldp_file);
1948 } else
1949 unlink(link->lldp_file);
1950
c2d6bd61
LP
1951 r = fflush_and_check(f);
1952 if (r < 0)
1953 goto fail;
fe8db0c5 1954
c2d6bd61 1955 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 1956 r = -errno;
c2d6bd61 1957 goto fail;
fe8db0c5
TG
1958 }
1959
c2d6bd61 1960 return 0;
c2d6bd61 1961fail:
79008bdd 1962 log_link_error(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
c2d6bd61
LP
1963 unlink(link->state_file);
1964 unlink(temp_path);
fe8db0c5
TG
1965 return r;
1966}
1967
1968static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 1969 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
1970 [LINK_STATE_ENSLAVING] = "configuring",
1971 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1972 [LINK_STATE_SETTING_ROUTES] = "configuring",
1973 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 1974 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 1975 [LINK_STATE_FAILED] = "failed",
370e9930 1976 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
1977};
1978
1979DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
1980
1981static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
1982 [LINK_OPERSTATE_OFF] = "off",
1983 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
1984 [LINK_OPERSTATE_DORMANT] = "dormant",
1985 [LINK_OPERSTATE_CARRIER] = "carrier",
1986 [LINK_OPERSTATE_DEGRADED] = "degraded",
1987 [LINK_OPERSTATE_ROUTABLE] = "routable",
1988};
1989
1990DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);