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