]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
networkd: log ifindices when links and netdevs are added
[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
19befb2d 687 r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler, link, 0);
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
7951dea2
SS
1469 if (!link->network->bridge &&
1470 !link->network->bond &&
1471 !link->network->tunnel &&
fe6b2d55
TG
1472 hashmap_isempty(link->network->vlans) &&
1473 hashmap_isempty(link->network->macvlans))
52433f6b 1474 return link_enslaved(link);
02b59d57 1475
d9c67ea1 1476 if (link->network->bond) {
52433f6b
TG
1477 log_struct_link(LOG_DEBUG, link,
1478 "MESSAGE=%s: enslaving by '%s'",
af4e9e2c 1479 link->ifname, link->network->bond->ifname,
d9c67ea1 1480 NETDEV(link->network->bond),
52433f6b 1481 NULL);
449f7554 1482
d9c67ea1 1483 r = netdev_enslave(link->network->bond, link, &enslave_handler);
52433f6b
TG
1484 if (r < 0) {
1485 log_struct_link(LOG_WARNING, link,
1486 "MESSAGE=%s: could not enslave by '%s': %s",
af4e9e2c 1487 link->ifname, link->network->bond->ifname, strerror(-r),
d9c67ea1 1488 NETDEV(link->network->bond),
52433f6b
TG
1489 NULL);
1490 link_enter_failed(link);
1491 return r;
1492 }
1493
b226d99b 1494 link_ref(link);
0ad6148e
MO
1495 link->enslaving ++;
1496 }
1497
d9c67ea1 1498 if (link->network->bridge) {
0ad6148e
MO
1499 log_struct_link(LOG_DEBUG, link,
1500 "MESSAGE=%s: enslaving by '%s'",
af4e9e2c 1501 link->ifname, link->network->bridge->ifname,
d9c67ea1 1502 NETDEV(link->network->bridge),
0ad6148e
MO
1503 NULL);
1504
d9c67ea1 1505 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
0ad6148e
MO
1506 if (r < 0) {
1507 log_struct_link(LOG_WARNING, link,
1508 "MESSAGE=%s: could not enslave by '%s': %s",
af4e9e2c 1509 link->ifname, link->network->bridge->ifname, strerror(-r),
d9c67ea1 1510 NETDEV(link->network->bridge),
0ad6148e
MO
1511 NULL);
1512 link_enter_failed(link);
1513 return r;
1514 }
1515
b226d99b 1516 link_ref(link);
52433f6b
TG
1517 link->enslaving ++;
1518 }
1519
7951dea2
SS
1520 if (link->network->tunnel) {
1521 log_struct_link(LOG_DEBUG, link,
1522 "MESSAGE=%s: enslaving by '%s'",
af4e9e2c 1523 link->ifname, link->network->tunnel->ifname,
7951dea2
SS
1524 NETDEV(link->network->tunnel),
1525 NULL);
1526
1527 r = netdev_enslave(link->network->tunnel, link, &enslave_handler);
1528 if (r < 0) {
1529 log_struct_link(LOG_WARNING, link,
1530 "MESSAGE=%s: could not enslave by '%s': %s",
af4e9e2c 1531 link->ifname, link->network->tunnel->ifname, strerror(-r),
7951dea2
SS
1532 NETDEV(link->network->tunnel),
1533 NULL);
1534 link_enter_failed(link);
1535 return r;
1536 }
1537
1538 link_ref(link);
1539 link->enslaving ++;
1540 }
1541
672682a6 1542 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
52433f6b
TG
1543 log_struct_link(LOG_DEBUG, link,
1544 "MESSAGE=%s: enslaving by '%s'",
af4e9e2c 1545 link->ifname, vlan->ifname, NETDEV(vlan), NULL);
52433f6b 1546
672682a6 1547 r = netdev_enslave(vlan, link, &enslave_handler);
52433f6b
TG
1548 if (r < 0) {
1549 log_struct_link(LOG_WARNING, link,
1550 "MESSAGE=%s: could not enslave by '%s': %s",
af4e9e2c 1551 link->ifname, vlan->ifname, strerror(-r),
672682a6 1552 NETDEV(vlan), NULL);
52433f6b
TG
1553 link_enter_failed(link);
1554 return r;
1555 }
1556
b226d99b 1557 link_ref(link);
52433f6b 1558 link->enslaving ++;
ef1ba606
TG
1559 }
1560
fe6b2d55
TG
1561 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1562 log_struct_link(LOG_DEBUG, link,
1563 "MESSAGE=%s: enslaving by '%s'",
af4e9e2c 1564 link->ifname, macvlan->ifname, NETDEV(macvlan), NULL);
fe6b2d55
TG
1565
1566 r = netdev_enslave(macvlan, link, &enslave_handler);
1567 if (r < 0) {
1568 log_struct_link(LOG_WARNING, link,
1569 "MESSAGE=%s: could not enslave by '%s': %s",
af4e9e2c 1570 link->ifname, macvlan->ifname, strerror(-r),
fe6b2d55
TG
1571 NETDEV(macvlan), NULL);
1572 link_enter_failed(link);
1573 return r;
1574 }
1575
b226d99b 1576 link_ref(link);
fe6b2d55
TG
1577 link->enslaving ++;
1578 }
1579
ef1ba606
TG
1580 return 0;
1581}
1582
a748b692 1583static int link_configure(Link *link) {
02b59d57
TG
1584 int r;
1585
ef1ba606 1586 assert(link);
505f8da7 1587 assert(link->state == LINK_STATE_INITIALIZING);
a748b692 1588
eb34d4af 1589 if (link->network->ipv4ll) {
b5db00e5 1590 uint8_t seed[8];
45ad2c13 1591
eb34d4af
TG
1592 r = sd_ipv4ll_new(&link->ipv4ll);
1593 if (r < 0)
1594 return r;
1595
505f8da7
TG
1596 if (link->udev_device) {
1597 r = net_get_unique_predictable_data(link->udev_device, seed);
1598 if (r >= 0) {
1599 r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
1600 if (r < 0)
1601 return r;
1602 }
b5db00e5
UTL
1603 }
1604
eb34d4af
TG
1605 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1606 if (r < 0)
1607 return r;
1608
4bb40e81
TG
1609 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1610 if (r < 0)
1611 return r;
1612
eb34d4af
TG
1613 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1614 if (r < 0)
1615 return r;
1616
1617 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1618 if (r < 0)
1619 return r;
1620 }
1621
1622 if (link->network->dhcp) {
1623 r = sd_dhcp_client_new(&link->dhcp_client);
1624 if (r < 0)
1625 return r;
1626
1627 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1628 if (r < 0)
1629 return r;
1630
4bb40e81
TG
1631 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1632 if (r < 0)
1633 return r;
1634
eb34d4af
TG
1635 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1636 if (r < 0)
1637 return r;
1638
1639 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1640 if (r < 0)
1641 return r;
1642
1643 if (link->network->dhcp_mtu) {
1644 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1645 if (r < 0)
1646 return r;
1647 }
1648 }
1649
deb2e523 1650 if (link_has_carrier(link->flags, link->operstate)) {
1e9be60b
TG
1651 r = link_acquire_conf(link);
1652 if (r < 0)
1653 return r;
cc544d5f 1654 }
1e9be60b 1655
505f8da7
TG
1656 return link_enter_enslave(link);
1657}
1658
1659int link_initialized(Link *link, struct udev_device *device) {
1660 Network *network;
505f8da7
TG
1661 int r;
1662
1663 assert(link);
1664 assert(link->ifname);
1665 assert(link->manager);
1666
1667 if (link->state != LINK_STATE_INITIALIZING)
1668 return 0;
1669
1670 if (device)
1671 link->udev_device = udev_device_ref(device);
1672
1673 log_debug_link(link, "link initialized");
1674
1675 r = network_get(link->manager, device, link->ifname, &link->mac, &network);
57bd6899
TG
1676 if (r == -ENOENT) {
1677 link_enter_unmanaged(link);
1678 return 0;
1679 } else if (r < 0)
1680 return r;
505f8da7
TG
1681
1682 r = network_apply(link->manager, network, link);
1683 if (r < 0)
1684 return r;
1685
a748b692
TG
1686 r = link_configure(link);
1687 if (r < 0)
1688 return r;
1689
505f8da7
TG
1690 return 0;
1691}
1692
fbbeb65a
TG
1693int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
1694 Manager *m = userdata;
1695 Link *link = NULL;
1696 uint16_t type;
1697 _cleanup_address_free_ Address *address = NULL;
1698 char buf[INET6_ADDRSTRLEN];
1699 int r, ifindex;
1700
1701 assert(rtnl);
1702 assert(message);
1703 assert(m);
1704
1705 r = sd_rtnl_message_get_type(message, &type);
1706 if (r < 0) {
1707 log_warning("rtnl: could not get message type");
1708 return 0;
1709 }
1710
1711 r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
1712 if (r < 0 || ifindex <= 0) {
5ea846cc 1713 log_warning("rtnl: received address message without valid ifindex, ignoring");
fbbeb65a
TG
1714 return 0;
1715 } else {
1716 r = link_get(m, ifindex, &link);
1717 if (r < 0 || !link) {
5ea846cc 1718 log_warning("rtnl: received address for a nonexistent link, ignoring");
fbbeb65a
TG
1719 return 0;
1720 }
1721 }
1722
1723 r = address_new_dynamic(&address);
1724 if (r < 0)
1725 return 0;
1726
1727 r = sd_rtnl_message_addr_get_family(message, &address->family);
1728 if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
1729 log_warning("rtnl: received address with invalid family, ignoring");
1730 return 0;
1731 }
1732
1733 r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
1734 if (r < 0) {
1735 log_warning("rtnl: recevied address with invalid prefixlen, ignoring");
1736 return 0;
1737 }
1738
1739 switch (address->family) {
1740 case AF_INET:
1741 r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
1742 if (r < 0) {
1743 log_warning("rtnl: received address without valid address, ignoring");
1744 return 0;
1745 }
1746
1747 break;
1748
1749 case AF_INET6:
1750 r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
1751 if (r < 0) {
1752 log_warning("rtnl: received address without valid address, ignoring");
1753 return 0;
1754 }
1755
1756 break;
1757
1758 default:
1759 assert_not_reached("invalid address family");
1760 }
1761
1762 if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
1763 log_warning("could not print address");
1764 return 0;
1765 }
1766
1767 switch (type) {
1768 case RTM_NEWADDR:
1769 log_info("added address: %s/%u to ifindex %d", buf,
1770 address->prefixlen, ifindex);
1771 break;
1772
1773 case RTM_DELADDR:
1774 log_info("removed address: %s/%u from ifindex %d", buf,
1775 address->prefixlen, ifindex);
1776 break;
1777 default:
1778 assert_not_reached("Received invalid RTNL message type");
1779 }
1780
1781 return 1;
1782}
1783
1784static int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1785 Link *link = userdata;
1786 int r;
1787
1788 assert(rtnl);
1789 assert(m);
1790 assert(link);
1791
1792 for (; m; m = sd_rtnl_message_next(m)) {
1793 r = sd_rtnl_message_get_errno(m);
1794 if (r < 0) {
1795 log_debug_link(link, "getting address failed: %s", strerror(-r));
1796 continue;
1797 }
1798
1799 r = link_rtnl_process_address(rtnl, m, link->manager);
1800 if (r < 0)
1801 log_warning_link(link, "could not process address: %s", strerror(-r));
1802 }
1803
1804 return 1;
1805}
1806
505f8da7
TG
1807int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1808 Link *link;
fbbeb65a 1809 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
1810 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1811 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1812 int r;
1813
1814 assert(m);
fbbeb65a 1815 assert(m->rtnl);
505f8da7
TG
1816 assert(message);
1817 assert(ret);
1818
1819 r = link_new(m, message, ret);
1820 if (r < 0)
1821 return r;
1822
1823 link = *ret;
1824
5261692f 1825 log_debug_link(link, "link %"PRIu64" added", link->ifindex);
505f8da7 1826
fbbeb65a
TG
1827 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex, 0);
1828 if (r < 0)
1829 return r;
1830
1831 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0, NULL);
1832 if (r < 0)
1833 return r;
1834
505f8da7
TG
1835 if (detect_container(NULL) <= 0) {
1836 /* not in a container, udev will be around */
1837 sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
1838 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1839 if (!device) {
1840 log_warning_link(link, "could not find udev device");
1841 return -errno;
1842 }
1843
1844 if (udev_device_get_is_initialized(device) <= 0)
1845 /* not yet ready */
1846 return 0;
1847 }
1848
1849 r = link_initialized(link, device);
1850 if (r < 0)
1851 return r;
1852
a748b692
TG
1853 return 0;
1854}
1855
22936833 1856int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1857 struct ether_addr mac;
b8941f74 1858 char *ifname;
22936833
TG
1859 int r;
1860
dd3efc09 1861 assert(link);
b8941f74 1862 assert(link->ifname);
22936833
TG
1863 assert(m);
1864
7619683b
TG
1865 if (link->state == LINK_STATE_LINGER) {
1866 link_ref(link);
1867 log_info_link(link, "link readded");
1868 link->state = LINK_STATE_ENSLAVING;
1869 }
1870
b8941f74
TG
1871 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1872 if (r >= 0 && !streq(ifname, link->ifname)) {
1873 log_info_link(link, "renamed to %s", ifname);
1874
1875 free(link->ifname);
1876 link->ifname = strdup(ifname);
1877 if (!link->ifname)
1878 return -ENOMEM;
1879 }
1880
505f8da7 1881 if (!link->original_mtu) {
9842de0d
TG
1882 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1883 if (r >= 0)
1884 log_debug_link(link, "saved original MTU: %"
1885 PRIu16, link->original_mtu);
1886 }
69629de9 1887
e9189a1f
TG
1888 /* The kernel may broadcast NEWLINK messages without the MAC address
1889 set, simply ignore them. */
c49b33ac 1890 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1891 if (r >= 0) {
20861203 1892 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
c49b33ac 1893
20861203 1894 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
c49b33ac 1895
20861203
TG
1896 log_debug_link(link, "MAC address: "
1897 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1898 mac.ether_addr_octet[0],
1899 mac.ether_addr_octet[1],
1900 mac.ether_addr_octet[2],
1901 mac.ether_addr_octet[3],
1902 mac.ether_addr_octet[4],
1903 mac.ether_addr_octet[5]);
c49b33ac 1904
20861203
TG
1905 if (link->ipv4ll) {
1906 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1907 if (r < 0) {
1908 log_warning_link(link, "Could not update MAC "
1909 "address in IPv4LL client: %s",
1910 strerror(-r));
1911 return r;
1912 }
c49b33ac 1913 }
c49b33ac 1914
20861203
TG
1915 if (link->dhcp_client) {
1916 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1917 if (r < 0) {
1918 log_warning_link(link, "Could not update MAC "
1919 "address in DHCP client: %s",
1920 strerror(-r));
1921 return r;
1922 }
c49b33ac
TG
1923 }
1924 }
4f882b2a
TG
1925 }
1926
1e9be60b 1927 return link_update_flags(link, m);
dd3efc09 1928}
fe8db0c5
TG
1929
1930int link_save(Link *link) {
68a8723c 1931 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1932 _cleanup_fclose_ FILE *f = NULL;
deb2e523 1933 const char *admin_state, *oper_state = "unknown";
fe8db0c5
TG
1934 int r;
1935
1936 assert(link);
1937 assert(link->state_file);
68a8723c 1938 assert(link->lease_file);
bbf7c048
TG
1939 assert(link->manager);
1940
1941 r = manager_save(link->manager);
1942 if (r < 0)
1943 return r;
fe8db0c5 1944
370e9930
TG
1945 if (link->state == LINK_STATE_LINGER) {
1946 unlink(link->state_file);
1947 return 0;
1948 }
1949
deb2e523
TG
1950 admin_state = link_state_to_string(link->state);
1951 assert(admin_state);
1952
75adc218 1953 if (link->operstate == IF_OPER_DORMANT)
deb2e523
TG
1954 oper_state = "dormant";
1955 else if (link_has_carrier(link->flags, link->operstate))
1956 oper_state = "carrier";
1957
fe8db0c5
TG
1958 r = fopen_temporary(link->state_file, &f, &temp_path);
1959 if (r < 0)
1960 goto finish;
1961
1962 fchmod(fileno(f), 0644);
1963
1964 fprintf(f,
1965 "# This is private data. Do not parse.\n"
deb2e523
TG
1966 "ADMIN_STATE=%s\n"
1967 "OPER_STATE=%s\n"
1968 "FLAGS=%u\n",
1969 admin_state, oper_state, link->flags);
fe8db0c5
TG
1970
1971 if (link->dhcp_lease) {
68a8723c 1972 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5
TG
1973 if (r < 0)
1974 goto finish;
1975
68a8723c 1976 fprintf(f, "DHCP_LEASE=%s\n", link->lease_file);
deb2e523 1977 } else
68a8723c 1978 unlink(link->lease_file);
fe8db0c5
TG
1979
1980 fflush(f);
1981
1982 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1983 r = -errno;
1984 unlink(link->state_file);
1985 unlink(temp_path);
1986 }
1987
1988finish:
1989 if (r < 0)
bbf7c048 1990 log_error("Failed to save link data to %s: %s", link->state_file, strerror(-r));
fe8db0c5
TG
1991
1992 return r;
1993}
1994
1995static const char* const link_state_table[_LINK_STATE_MAX] = {
deb2e523 1996 [LINK_STATE_INITIALIZING] = "initializing",
fe8db0c5
TG
1997 [LINK_STATE_ENSLAVING] = "configuring",
1998 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1999 [LINK_STATE_SETTING_ROUTES] = "configuring",
2000 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 2001 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 2002 [LINK_STATE_FAILED] = "failed",
370e9930 2003 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
2004};
2005
2006DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);