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