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