]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/network/networkd-link.c
timedated: do not reset poll interval with a spike
[thirdparty/systemd.git] / src / network / networkd-link.c
... / ...
CommitLineData
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"
27#include "util.h"
28#include "bus-util.h"
29#include "net-util.h"
30
31#include "dhcp-lease-internal.h"
32
33int link_new(Manager *manager, struct udev_device *device, Link **ret) {
34 _cleanup_link_free_ Link *link = NULL;
35 const char *ifname;
36 int r;
37
38 assert(manager);
39 assert(manager->links);
40 assert(device);
41 assert(ret);
42
43 link = new0(Link, 1);
44 if (!link)
45 return -ENOMEM;
46
47 link->manager = manager;
48 link->state = _LINK_STATE_INVALID;
49
50 link->ifindex = udev_device_get_ifindex(device);
51 if (link->ifindex <= 0)
52 return -EINVAL;
53
54 r = asprintf(&link->state_file, "/run/systemd/network/links/%"PRIu64,
55 link->ifindex);
56 if (r < 0)
57 return -ENOMEM;
58
59 ifname = udev_device_get_sysname(device);
60 link->ifname = strdup(ifname);
61
62 r = hashmap_put(manager->links, &link->ifindex, link);
63 if (r < 0)
64 return r;
65
66 *ret = link;
67 link = NULL;
68
69 return 0;
70}
71
72void link_free(Link *link) {
73 if (!link)
74 return;
75
76 assert(link->manager);
77
78 sd_dhcp_client_free(link->dhcp_client);
79 sd_dhcp_lease_unref(link->dhcp_lease);
80
81 sd_ipv4ll_free(link->ipv4ll);
82
83 hashmap_remove(link->manager->links, &link->ifindex);
84
85 free(link->ifname);
86 free(link->state_file);
87
88 free(link);
89}
90
91int link_get(Manager *m, int ifindex, Link **ret) {
92 Link *link;
93 uint64_t ifindex_64;
94
95 assert(m);
96 assert(m->links);
97 assert(ifindex);
98 assert(ret);
99
100 ifindex_64 = ifindex;
101 link = hashmap_get(m->links, &ifindex_64);
102 if (!link)
103 return -ENODEV;
104
105 *ret = link;
106
107 return 0;
108}
109
110static int link_enter_configured(Link *link) {
111 assert(link);
112 assert(link->state == LINK_STATE_SETTING_ROUTES);
113
114 log_info_link(link, "link configured");
115
116 link->state = LINK_STATE_CONFIGURED;
117
118 link_save(link);
119
120 return 0;
121}
122
123static void link_enter_failed(Link *link) {
124 assert(link);
125
126 log_warning_link(link, "failed");
127
128 link->state = LINK_STATE_FAILED;
129
130 link_save(link);
131}
132
133static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
134 Link *link = userdata;
135 int r;
136
137 assert(link->route_messages > 0);
138 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
139 link->state == LINK_STATE_SETTING_ROUTES ||
140 link->state == LINK_STATE_FAILED);
141
142 link->route_messages --;
143
144 if (link->state == LINK_STATE_FAILED)
145 return 1;
146
147 r = sd_rtnl_message_get_errno(m);
148 if (r < 0 && r != -EEXIST)
149 log_struct_link(LOG_WARNING, link,
150 "MESSAGE=%s: could not set route: %s",
151 link->ifname, strerror(-r),
152 "ERRNO=%d", -r,
153 NULL);
154
155 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
156 * ignore it */
157 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
158 log_debug_link(link, "routes set");
159 link_enter_configured(link);
160 }
161
162 return 1;
163}
164
165static int link_enter_set_routes(Link *link) {
166 Route *rt;
167 struct in_addr a;
168 int r;
169
170 assert(link);
171 assert(link->network);
172 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
173
174 link->state = LINK_STATE_SETTING_ROUTES;
175
176 if (!link->network->static_routes && !link->dhcp_lease &&
177 (!link->ipv4ll || sd_ipv4ll_get_address(link->ipv4ll, &a) < 0))
178 return link_enter_configured(link);
179
180 log_debug_link(link, "setting routes");
181
182 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
183 r = route_configure(rt, link, &route_handler);
184 if (r < 0) {
185 log_warning_link(link,
186 "could not set routes: %s", strerror(-r));
187 link_enter_failed(link);
188 return r;
189 }
190
191 link->route_messages ++;
192 }
193
194 if (link->ipv4ll && !link->dhcp_lease) {
195 _cleanup_route_free_ Route *route = NULL;
196 struct in_addr addr;
197
198 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
199 if (r < 0 && r != -ENOENT) {
200 log_warning_link(link, "IPV4LL error: no address: %s",
201 strerror(-r));
202 return r;
203 }
204
205 if (r != -ENOENT) {
206 r = route_new_dynamic(&route);
207 if (r < 0) {
208 log_error_link(link, "Could not allocate route: %s",
209 strerror(-r));
210 return r;
211 }
212
213 route->family = AF_INET;
214 route->scope = RT_SCOPE_LINK;
215 route->metrics = 99;
216
217 r = route_configure(route, link, &route_handler);
218 if (r < 0) {
219 log_warning_link(link,
220 "could not set routes: %s", strerror(-r));
221 link_enter_failed(link);
222 return r;
223 }
224
225 link->route_messages ++;
226 }
227 }
228
229 if (link->dhcp_lease) {
230 _cleanup_route_free_ Route *route = NULL;
231 _cleanup_route_free_ Route *route_gw = NULL;
232 struct in_addr gateway;
233
234 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
235 if (r < 0) {
236 log_warning_link(link, "DHCP error: no router: %s",
237 strerror(-r));
238 return r;
239 }
240
241 r = route_new_dynamic(&route);
242 if (r < 0) {
243 log_error_link(link, "Could not allocate route: %s",
244 strerror(-r));
245 return r;
246 }
247
248 r = route_new_dynamic(&route_gw);
249 if (r < 0) {
250 log_error_link(link, "Could not allocate route: %s",
251 strerror(-r));
252 return r;
253 }
254
255 /* The dhcp netmask may mask out the gateway. Add an explicit
256 * route for the gw host so that we can route no matter the
257 * netmask or existing kernel route tables. */
258 route_gw->family = AF_INET;
259 route_gw->dst_addr.in = gateway;
260 route_gw->dst_prefixlen = 32;
261 route_gw->scope = RT_SCOPE_LINK;
262
263 r = route_configure(route_gw, link, &route_handler);
264 if (r < 0) {
265 log_warning_link(link,
266 "could not set host route: %s", strerror(-r));
267 return r;
268 }
269
270 link->route_messages ++;
271
272 route->family = AF_INET;
273 route->in_addr.in = gateway;
274
275 r = route_configure(route, link, &route_handler);
276 if (r < 0) {
277 log_warning_link(link,
278 "could not set routes: %s", strerror(-r));
279 link_enter_failed(link);
280 return r;
281 }
282
283 link->route_messages ++;
284 }
285
286 return 0;
287}
288
289static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
290 Link *link = userdata;
291 int r;
292
293 assert(m);
294 assert(link);
295 assert(link->ifname);
296
297 if (link->state == LINK_STATE_FAILED)
298 return 1;
299
300 r = sd_rtnl_message_get_errno(m);
301 if (r < 0 && r != -ENOENT)
302 log_struct_link(LOG_WARNING, link,
303 "MESSAGE=%s: could not drop route: %s",
304 link->ifname, strerror(-r),
305 "ERRNO=%d", -r,
306 NULL);
307
308 return 0;
309}
310
311static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
312 Link *link = userdata;
313 int r;
314
315 assert(m);
316 assert(link);
317 assert(link->ifname);
318 assert(link->addr_messages > 0);
319 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
320
321 link->addr_messages --;
322
323 if (link->state == LINK_STATE_FAILED)
324 return 1;
325
326 r = sd_rtnl_message_get_errno(m);
327 if (r < 0 && r != -EEXIST)
328 log_struct_link(LOG_WARNING, link,
329 "MESSAGE=%s: could not set address: %s",
330 link->ifname, strerror(-r),
331 "ERRNO=%d", -r,
332 NULL);
333
334 if (link->addr_messages == 0) {
335 log_debug_link(link, "addresses set");
336 link_enter_set_routes(link);
337 }
338
339 return 1;
340}
341
342static int link_enter_set_addresses(Link *link) {
343 Address *ad;
344 struct in_addr a;
345 int r;
346
347 assert(link);
348 assert(link->network);
349 assert(link->state != _LINK_STATE_INVALID);
350
351 link->state = LINK_STATE_SETTING_ADDRESSES;
352
353 if (!link->network->static_addresses && !link->dhcp_lease &&
354 (!link->ipv4ll || sd_ipv4ll_get_address(link->ipv4ll, &a) < 0))
355 return link_enter_set_routes(link);
356
357 log_debug_link(link, "setting addresses");
358
359 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
360 r = address_configure(ad, link, &address_handler);
361 if (r < 0) {
362 log_warning_link(link,
363 "could not set addresses: %s", strerror(-r));
364 link_enter_failed(link);
365 return r;
366 }
367
368 link->addr_messages ++;
369 }
370
371 if (link->ipv4ll && !link->dhcp_lease) {
372 _cleanup_address_free_ Address *ll_addr = NULL;
373 struct in_addr addr;
374
375 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
376 if (r < 0 && r != -ENOENT) {
377 log_warning_link(link, "IPV4LL error: no address: %s",
378 strerror(-r));
379 return r;
380 }
381
382 if (r != -ENOENT) {
383 r = address_new_dynamic(&ll_addr);
384 if (r < 0) {
385 log_error_link(link, "Could not allocate address: %s", strerror(-r));
386 return r;
387 }
388
389 ll_addr->family = AF_INET;
390 ll_addr->in_addr.in = addr;
391 ll_addr->prefixlen = 16;
392 ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
393 ll_addr->scope = RT_SCOPE_LINK;
394
395 r = address_configure(ll_addr, link, &address_handler);
396 if (r < 0) {
397 log_warning_link(link,
398 "could not set addresses: %s", strerror(-r));
399 link_enter_failed(link);
400 return r;
401 }
402
403 link->addr_messages ++;
404 }
405 }
406
407 if (link->dhcp_lease) {
408 _cleanup_address_free_ Address *address = NULL;
409 struct in_addr addr;
410 struct in_addr netmask;
411 unsigned prefixlen;
412
413 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
414 if (r < 0) {
415 log_warning_link(link, "DHCP error: no address: %s",
416 strerror(-r));
417 return r;
418 }
419
420 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
421 if (r < 0) {
422 log_warning_link(link, "DHCP error: no netmask: %s",
423 strerror(-r));
424 return r;
425 }
426
427 prefixlen = net_netmask_to_prefixlen(&netmask);
428
429 r = address_new_dynamic(&address);
430 if (r < 0) {
431 log_error_link(link, "Could not allocate address: %s",
432 strerror(-r));
433 return r;
434 }
435
436 address->family = AF_INET;
437 address->in_addr.in = addr;
438 address->prefixlen = prefixlen;
439 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
440
441 r = address_configure(address, link, &address_handler);
442 if (r < 0) {
443 log_warning_link(link,
444 "could not set addresses: %s", strerror(-r));
445 link_enter_failed(link);
446 return r;
447 }
448
449 link->addr_messages ++;
450 }
451
452 return 0;
453}
454
455static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
456 Link *link = userdata;
457 int r;
458
459 assert(m);
460 assert(link);
461 assert(link->ifname);
462
463 if (link->state == LINK_STATE_FAILED)
464 return 1;
465
466 r = sd_rtnl_message_get_errno(m);
467 if (r < 0 && r != -ENOENT)
468 log_struct_link(LOG_WARNING, link,
469 "MESSAGE=%s: could not drop address: %s",
470 link->ifname, strerror(-r),
471 "ERRNO=%d", -r,
472 NULL);
473
474 return 0;
475}
476
477static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
478 int r;
479
480 r = sd_bus_message_get_errno(m);
481 if (r < 0)
482 log_warning("Could not set hostname: %s", strerror(-r));
483
484 return 1;
485}
486
487static int set_hostname(sd_bus *bus, const char *hostname) {
488 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
489 int r = 0;
490
491 assert(hostname);
492
493 log_debug("Setting transient hostname: '%s'", hostname);
494
495 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
496 log_info("Not connected to system bus, ignoring transient hostname.");
497 return 0;
498 }
499
500 r = sd_bus_message_new_method_call(
501 bus,
502 &m,
503 "org.freedesktop.hostname1",
504 "/org/freedesktop/hostname1",
505 "org.freedesktop.hostname1",
506 "SetHostname");
507 if (r < 0)
508 return r;
509
510 r = sd_bus_message_append(m, "sb", hostname, false);
511 if (r < 0)
512 return r;
513
514 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
515 if (r < 0)
516 log_error("Could not set transient hostname: %s", strerror(-r));
517
518 return r;
519}
520
521static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
522 Link *link = userdata;
523 int r;
524
525 assert(m);
526 assert(link);
527 assert(link->ifname);
528
529 if (link->state == LINK_STATE_FAILED)
530 return 1;
531
532 r = sd_rtnl_message_get_errno(m);
533 if (r < 0)
534 log_struct_link(LOG_WARNING, link,
535 "MESSAGE=%s: could not set MTU: %s",
536 link->ifname, strerror(-r),
537 "ERRNO=%d", -r,
538 NULL);
539
540 return 1;
541}
542
543static int link_set_mtu(Link *link, uint32_t mtu) {
544 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
545 int r;
546
547 assert(link);
548 assert(link->manager);
549 assert(link->manager->rtnl);
550
551 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
552
553 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
554 RTM_SETLINK, link->ifindex);
555 if (r < 0) {
556 log_error_link(link, "Could not allocate RTM_SETLINK message");
557 return r;
558 }
559
560 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
561 if (r < 0) {
562 log_error_link(link, "Could not append MTU: %s", strerror(-r));
563 return r;
564 }
565
566 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
567 if (r < 0) {
568 log_error_link(link,
569 "Could not send rtnetlink message: %s", strerror(-r));
570 return r;
571 }
572
573 return 0;
574}
575
576static int dhcp_lease_lost(Link *link) {
577 _cleanup_address_free_ Address *address = NULL;
578 struct in_addr addr;
579 struct in_addr netmask;
580 unsigned prefixlen;
581 int r;
582
583 assert(link);
584 assert(link->dhcp_lease);
585
586 log_warning_link(link, "DHCP lease lost");
587
588 r = address_new_dynamic(&address);
589 if (r >= 0) {
590 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
591 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
592 prefixlen = net_netmask_to_prefixlen(&netmask);
593
594 address->family = AF_INET;
595 address->in_addr.in = addr;
596 address->prefixlen = prefixlen;
597
598 address_drop(address, link, &address_drop_handler);
599 }
600
601 if (link->network->dhcp_mtu) {
602 uint16_t mtu;
603
604 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
605 if (r >= 0 && link->original_mtu != mtu) {
606 r = link_set_mtu(link, link->original_mtu);
607 if (r < 0) {
608 log_warning_link(link, "DHCP error: could not reset MTU");
609 link_enter_failed(link);
610 return r;
611 }
612 }
613 }
614
615 if (link->network->dhcp_hostname) {
616 const char *hostname = NULL;
617
618 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
619 if (r >= 0 && hostname) {
620 r = set_hostname(link->manager->bus, "");
621 if (r < 0)
622 log_error("Failed to reset transient hostname");
623 }
624 }
625
626 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
627
628 return 0;
629}
630
631static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
632 sd_dhcp_lease *lease;
633 struct in_addr address;
634 struct in_addr netmask;
635 struct in_addr gateway;
636 unsigned prefixlen;
637 struct in_addr *nameservers;
638 size_t nameservers_size;
639 int r;
640
641 assert(client);
642 assert(link);
643
644 r = sd_dhcp_client_get_lease(client, &lease);
645 if (r < 0) {
646 log_warning_link(link, "DHCP error: no lease: %s",
647 strerror(-r));
648 return r;
649 }
650
651 r = sd_dhcp_lease_get_address(lease, &address);
652 if (r < 0) {
653 log_warning_link(link, "DHCP error: no address: %s",
654 strerror(-r));
655 return r;
656 }
657
658 r = sd_dhcp_lease_get_netmask(lease, &netmask);
659 if (r < 0) {
660 log_warning_link(link, "DHCP error: no netmask: %s",
661 strerror(-r));
662 return r;
663 }
664
665 prefixlen = net_netmask_to_prefixlen(&netmask);
666
667 r = sd_dhcp_lease_get_router(lease, &gateway);
668 if (r < 0) {
669 log_warning_link(link, "DHCP error: no router: %s",
670 strerror(-r));
671 return r;
672 }
673
674 log_struct_link(LOG_INFO, link,
675 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
676 link->ifname,
677 ADDRESS_FMT_VAL(address),
678 prefixlen,
679 ADDRESS_FMT_VAL(gateway),
680 "ADDRESS=%u.%u.%u.%u",
681 ADDRESS_FMT_VAL(address),
682 "PREFIXLEN=%u",
683 prefixlen,
684 "GATEWAY=%u.%u.%u.%u",
685 ADDRESS_FMT_VAL(gateway),
686 NULL);
687
688 link->dhcp_lease = lease;
689
690 if (link->network->dhcp_dns) {
691 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
692 if (r >= 0) {
693 r = manager_update_resolv_conf(link->manager);
694 if (r < 0)
695 log_error("Failed to update resolv.conf");
696 }
697 }
698
699 if (link->network->dhcp_mtu) {
700 uint16_t mtu;
701
702 r = sd_dhcp_lease_get_mtu(lease, &mtu);
703 if (r >= 0) {
704 r = link_set_mtu(link, mtu);
705 if (r < 0)
706 log_error_link(link, "Failed to set MTU "
707 "to %" PRIu16, mtu);
708 }
709 }
710
711 if (link->network->dhcp_hostname) {
712 const char *hostname;
713
714 r = sd_dhcp_lease_get_hostname(lease, &hostname);
715 if (r >= 0) {
716 r = set_hostname(link->manager->bus, hostname);
717 if (r < 0)
718 log_error("Failed to set transient hostname "
719 "to '%s'", hostname);
720 }
721 }
722
723 link_enter_set_addresses(link);
724
725 return 0;
726}
727
728static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
729 Link *link = userdata;
730 int r;
731
732 assert(link);
733 assert(link->network);
734 assert(link->manager);
735
736 if (link->state == LINK_STATE_FAILED)
737 return;
738
739 switch (event) {
740 case DHCP_EVENT_NO_LEASE:
741 log_debug_link(link, "IP address in use.");
742 break;
743 case DHCP_EVENT_EXPIRED:
744 case DHCP_EVENT_STOP:
745 case DHCP_EVENT_IP_CHANGE:
746 if (link->network->dhcp_critical) {
747 log_error_link(link, "DHCPv4 connection considered system critical, "
748 "ignoring request to reconfigure it.");
749 return;
750 }
751
752 if (link->dhcp_lease) {
753 r = dhcp_lease_lost(link);
754 if (r < 0) {
755 link_enter_failed(link);
756 return;
757 }
758 }
759
760 if (event == DHCP_EVENT_IP_CHANGE) {
761 r = dhcp_lease_acquired(client, link);
762 if (r < 0) {
763 link_enter_failed(link);
764 return;
765 }
766 }
767
768 if (event == DHCP_EVENT_EXPIRED && link->network->ipv4ll) {
769 r = sd_ipv4ll_start (link->ipv4ll);
770 if (r < 0) {
771 link_enter_failed(link);
772 return;
773 }
774 }
775
776 break;
777 case DHCP_EVENT_IP_ACQUIRE:
778 r = dhcp_lease_acquired(client, link);
779 if (r < 0) {
780 link_enter_failed(link);
781 return;
782 }
783 if (link->ipv4ll) {
784 r = sd_ipv4ll_stop(link->ipv4ll);
785 if (r < 0) {
786 link_enter_failed(link);
787 return;
788 }
789 }
790 break;
791 default:
792 if (event < 0)
793 log_warning_link(link, "DHCP error: %s", strerror(-event));
794 else
795 log_warning_link(link, "DHCP unknown event: %d", event);
796 break;
797 }
798
799 return;
800}
801
802static int ipv4ll_address_lost(sd_ipv4ll *ll, Link *link) {
803 int r;
804 struct in_addr addr;
805
806 assert(ll);
807 assert(link);
808
809 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
810 if (r >= 0) {
811 _cleanup_address_free_ Address *address = NULL;
812 _cleanup_route_free_ Route *route = NULL;
813
814 log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
815 ADDRESS_FMT_VAL(addr));
816
817 r = address_new_dynamic(&address);
818 if (r < 0) {
819 log_error_link(link, "Could not allocate address: %s", strerror(-r));
820 return r;
821 }
822
823 address->family = AF_INET;
824 address->in_addr.in = addr;
825 address->prefixlen = 16;
826 address->scope = RT_SCOPE_LINK;
827
828 address_drop(address, link, &address_drop_handler);
829
830 r = route_new_dynamic(&route);
831 if (r < 0) {
832 log_error_link(link, "Could not allocate route: %s",
833 strerror(-r));
834 return r;
835 }
836
837 route->family = AF_INET;
838 route->scope = RT_SCOPE_LINK;
839 route->metrics = 99;
840
841 route_drop(route, link, &route_drop_handler);
842 }
843
844 return 0;
845}
846
847static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
848 struct in_addr address;
849 int r;
850
851 assert(ll);
852 assert(link);
853
854 r = sd_ipv4ll_get_address(ll, &address);
855 if (r < 0)
856 return r;
857
858 log_struct_link(LOG_INFO, link,
859 "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
860 link->ifname,
861 ADDRESS_FMT_VAL(address),
862 NULL);
863
864 link_enter_set_addresses(link);
865
866 return 0;
867}
868
869static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
870 Link *link = userdata;
871 int r;
872
873 assert(link);
874 assert(link->network);
875 assert(link->manager);
876
877 switch(event) {
878 case IPV4LL_EVENT_STOP:
879 case IPV4LL_EVENT_CONFLICT:
880 r = ipv4ll_address_lost(ll, link);
881 if (r < 0) {
882 link_enter_failed(link);
883 return;
884 }
885 break;
886 case IPV4LL_EVENT_BIND:
887 r = ipv4ll_address_claimed(ll, link);
888 if (r < 0) {
889 link_enter_failed(link);
890 return;
891 }
892 break;
893 default:
894 if (event < 0)
895 log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
896 else
897 log_warning_link(link, "IPv4 link-local unknown event: %d", event);
898 break;
899 }
900}
901
902static int link_acquire_conf(Link *link) {
903 int r;
904
905 assert(link);
906 assert(link->network);
907 assert(link->manager);
908 assert(link->manager->event);
909
910 if (link->network->ipv4ll) {
911 assert(link->ipv4ll);
912
913 log_debug_link(link, "acquiring IPv4 link-local address");
914
915 r = sd_ipv4ll_start(link->ipv4ll);
916 if (r < 0)
917 return r;
918 }
919
920 if (link->network->dhcp) {
921 assert(link->dhcp_client);
922
923 log_debug_link(link, "acquiring DHCPv4 lease");
924
925 r = sd_dhcp_client_start(link->dhcp_client);
926 if (r < 0)
927 return r;
928 }
929
930 return 0;
931}
932
933static int link_update_flags(Link *link, unsigned flags) {
934 int r;
935
936 assert(link);
937 assert(link->network);
938
939 if (link->state == LINK_STATE_FAILED)
940 return 0;
941
942 if (link->flags == flags)
943 return 0;
944
945 log_debug_link(link, "link status updated: %#.8x -> %#.8x",
946 link->flags, flags);
947
948 if ((link->flags & IFF_UP) != (flags & IFF_UP))
949 log_info_link(link,
950 "link is %s", flags & IFF_UP ? "up": "down");
951
952 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
953 if (flags & IFF_LOWER_UP) {
954 log_info_link(link, "carrier on");
955
956 if (link->network->dhcp || link->network->ipv4ll) {
957 r = link_acquire_conf(link);
958 if (r < 0) {
959 log_warning_link(link, "Could not acquire configuration: %s", strerror(-r));
960 link_enter_failed(link);
961 return r;
962 }
963 }
964 } else {
965 log_info_link(link, "carrier off");
966
967 if (link->network->dhcp) {
968 r = sd_dhcp_client_stop(link->dhcp_client);
969 if (r < 0) {
970 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
971 link_enter_failed(link);
972 return r;
973 }
974 }
975
976 if (link->network->ipv4ll) {
977 r = sd_ipv4ll_stop(link->ipv4ll);
978 if (r < 0) {
979 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
980 link_enter_failed(link);
981 return r;
982 }
983 }
984 }
985 }
986
987 link->flags = flags;
988
989 return 0;
990}
991
992static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
993 Link *link = userdata;
994 int r;
995
996 assert(link);
997
998 if (link->state == LINK_STATE_FAILED)
999 return 1;
1000
1001 r = sd_rtnl_message_get_errno(m);
1002 if (r >= 0)
1003 link_update_flags(link, link->flags | IFF_UP);
1004 else
1005 log_struct_link(LOG_WARNING, link,
1006 "MESSAGE=%s: could not bring up interface: %s",
1007 link->ifname, strerror(-r),
1008 "ERRNO=%d", -r,
1009 NULL);
1010 return 1;
1011}
1012
1013static int link_up(Link *link) {
1014 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1015 int r;
1016
1017 assert(link);
1018 assert(link->manager);
1019 assert(link->manager->rtnl);
1020
1021 log_debug_link(link, "bringing link up");
1022
1023 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1024 RTM_SETLINK, link->ifindex);
1025 if (r < 0) {
1026 log_error_link(link, "Could not allocate RTM_SETLINK message");
1027 return r;
1028 }
1029
1030 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
1031 if (r < 0) {
1032 log_error_link(link, "Could not set link flags: %s", strerror(-r));
1033 return r;
1034 }
1035
1036 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
1037 if (r < 0) {
1038 log_error_link(link,
1039 "Could not send rtnetlink message: %s", strerror(-r));
1040 return r;
1041 }
1042
1043 return 0;
1044}
1045
1046static int link_enslaved(Link *link) {
1047 int r;
1048
1049 assert(link);
1050 assert(link->state == LINK_STATE_ENSLAVING);
1051 assert(link->network);
1052
1053 r = link_up(link);
1054 if (r < 0) {
1055 link_enter_failed(link);
1056 return r;
1057 }
1058
1059 if (!link->network->dhcp && !link->network->ipv4ll)
1060 return link_enter_set_addresses(link);
1061
1062 return 0;
1063}
1064
1065static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1066 Link *link = userdata;
1067 int r;
1068
1069 assert(link);
1070 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
1071 assert(link->network);
1072
1073 link->enslaving --;
1074
1075 if (link->state == LINK_STATE_FAILED)
1076 return 1;
1077
1078 r = sd_rtnl_message_get_errno(m);
1079 if (r < 0) {
1080 log_struct_link(LOG_ERR, link,
1081 "MESSAGE=%s: could not enslave: %s",
1082 link->ifname, strerror(-r),
1083 "ERRNO=%d", -r,
1084 NULL);
1085 link_enter_failed(link);
1086 return 1;
1087 }
1088
1089 log_debug_link(link, "enslaved");
1090
1091 if (link->enslaving == 0)
1092 link_enslaved(link);
1093
1094 return 1;
1095}
1096
1097static int link_enter_enslave(Link *link) {
1098 NetDev *vlan, *macvlan;
1099 Iterator i;
1100 int r;
1101
1102 assert(link);
1103 assert(link->network);
1104 assert(link->state == _LINK_STATE_INVALID);
1105
1106 link->state = LINK_STATE_ENSLAVING;
1107
1108 link_save(link);
1109
1110 if (!link->network->bridge && !link->network->bond &&
1111 hashmap_isempty(link->network->vlans) &&
1112 hashmap_isempty(link->network->macvlans))
1113 return link_enslaved(link);
1114
1115 if (link->network->bridge) {
1116 log_struct_link(LOG_DEBUG, link,
1117 "MESSAGE=%s: enslaving by '%s'",
1118 link->ifname, link->network->bridge->name,
1119 NETDEV(link->network->bridge),
1120 NULL);
1121
1122 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1123 if (r < 0) {
1124 log_struct_link(LOG_WARNING, link,
1125 "MESSAGE=%s: could not enslave by '%s': %s",
1126 link->ifname, link->network->bridge->name, strerror(-r),
1127 NETDEV(link->network->bridge),
1128 NULL);
1129 link_enter_failed(link);
1130 return r;
1131 }
1132
1133 link->enslaving ++;
1134 }
1135
1136 if (link->network->bond) {
1137 log_struct_link(LOG_DEBUG, link,
1138 "MESSAGE=%s: enslaving by '%s'",
1139 link->ifname, link->network->bond->name,
1140 NETDEV(link->network->bond),
1141 NULL);
1142
1143 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1144 if (r < 0) {
1145 log_struct_link(LOG_WARNING, link,
1146 "MESSAGE=%s: could not enslave by '%s': %s",
1147 link->ifname, link->network->bond->name, strerror(-r),
1148 NETDEV(link->network->bond),
1149 NULL);
1150 link_enter_failed(link);
1151 return r;
1152 }
1153
1154 link->enslaving ++;
1155 }
1156
1157 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
1158 log_struct_link(LOG_DEBUG, link,
1159 "MESSAGE=%s: enslaving by '%s'",
1160 link->ifname, vlan->name, NETDEV(vlan), NULL);
1161
1162 r = netdev_enslave(vlan, link, &enslave_handler);
1163 if (r < 0) {
1164 log_struct_link(LOG_WARNING, link,
1165 "MESSAGE=%s: could not enslave by '%s': %s",
1166 link->ifname, vlan->name, strerror(-r),
1167 NETDEV(vlan), NULL);
1168 link_enter_failed(link);
1169 return r;
1170 }
1171
1172 link->enslaving ++;
1173 }
1174
1175 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1176 log_struct_link(LOG_DEBUG, link,
1177 "MESSAGE=%s: enslaving by '%s'",
1178 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1179
1180 r = netdev_enslave(macvlan, link, &enslave_handler);
1181 if (r < 0) {
1182 log_struct_link(LOG_WARNING, link,
1183 "MESSAGE=%s: could not enslave by '%s': %s",
1184 link->ifname, macvlan->name, strerror(-r),
1185 NETDEV(macvlan), NULL);
1186 link_enter_failed(link);
1187 return r;
1188 }
1189
1190 link->enslaving ++;
1191 }
1192
1193 return 0;
1194}
1195
1196static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1197 void *userdata) {
1198 Link *link = userdata;
1199 int r;
1200
1201 assert(link);
1202
1203 if (link->state == LINK_STATE_FAILED)
1204 return 1;
1205
1206 r = sd_rtnl_message_get_errno(m);
1207 if (r < 0) {
1208 log_struct_link(LOG_ERR, link,
1209 "MESSAGE=%s: could not get state: %s",
1210 link->ifname, strerror(-r),
1211 "ERRNO=%d", -r,
1212 NULL);
1213 link_enter_failed(link);
1214 return 1;
1215 }
1216
1217 link_update(link, m);
1218
1219 return 1;
1220}
1221
1222static int link_getlink(Link *link) {
1223 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1224 int r;
1225
1226 assert(link);
1227 assert(link->manager);
1228 assert(link->manager->rtnl);
1229
1230 log_debug_link(link, "requesting link status");
1231
1232 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1233 RTM_GETLINK, link->ifindex);
1234 if (r < 0) {
1235 log_error_link(link, "Could not allocate RTM_GETLINK message");
1236 return r;
1237 }
1238
1239 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1240 link, 0, NULL);
1241 if (r < 0) {
1242 log_error_link(link,
1243 "Could not send rtnetlink message: %s", strerror(-r));
1244 return r;
1245 }
1246
1247 return 0;
1248}
1249
1250static int link_configure(Link *link) {
1251 int r;
1252
1253 assert(link);
1254 assert(link->state == _LINK_STATE_INVALID);
1255
1256 r = link_getlink(link);
1257 if (r < 0)
1258 return r;
1259
1260 return link_enter_enslave(link);
1261}
1262
1263int link_add(Manager *m, struct udev_device *device, Link **ret) {
1264 Link *link = NULL;
1265 Network *network;
1266 int r;
1267
1268 assert(m);
1269 assert(device);
1270
1271 r = link_new(m, device, &link);
1272 if (r < 0)
1273 return r;
1274
1275 *ret = link;
1276
1277 r = network_get(m, device, &network);
1278 if (r < 0)
1279 return r == -ENOENT ? 0 : r;
1280
1281 r = network_apply(m, network, link);
1282 if (r < 0)
1283 return r;
1284
1285 if (link->network->ipv4ll) {
1286 r = sd_ipv4ll_new(&link->ipv4ll);
1287 if (r < 0)
1288 return r;
1289
1290 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1291 if (r < 0)
1292 return r;
1293
1294 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1295 if (r < 0)
1296 return r;
1297
1298 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1299 if (r < 0)
1300 return r;
1301 }
1302
1303 if (link->network->dhcp) {
1304 r = sd_dhcp_client_new(&link->dhcp_client);
1305 if (r < 0)
1306 return r;
1307
1308 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1309 if (r < 0)
1310 return r;
1311
1312 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1313 if (r < 0)
1314 return r;
1315
1316 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1317 if (r < 0)
1318 return r;
1319
1320 if (link->network->dhcp_mtu) {
1321 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1322 if (r < 0)
1323 return r;
1324 }
1325 }
1326
1327 r = link_configure(link);
1328 if (r < 0)
1329 return r;
1330
1331 return 0;
1332}
1333
1334int link_update(Link *link, sd_rtnl_message *m) {
1335 unsigned flags;
1336 struct ether_addr mac;
1337 int r;
1338
1339 assert(link);
1340 assert(link->network);
1341 assert(m);
1342
1343 if (link->state == LINK_STATE_FAILED)
1344 return 0;
1345
1346 if (link->network->dhcp && link->network->dhcp_mtu &&
1347 !link->original_mtu) {
1348 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1349 if (r >= 0)
1350 log_debug_link(link, "saved original MTU: %"
1351 PRIu16, link->original_mtu);
1352 }
1353
1354 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
1355 if (r >= 0 && memcmp(&link->mac.ether_addr_octet, &mac.ether_addr_octet, ETH_ALEN)) {
1356
1357 memcpy(&link->mac.ether_addr_octet, &mac.ether_addr_octet, ETH_ALEN);
1358
1359 log_debug_link(link, "MAC address: "
1360 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1361 mac.ether_addr_octet[0],
1362 mac.ether_addr_octet[1],
1363 mac.ether_addr_octet[2],
1364 mac.ether_addr_octet[3],
1365 mac.ether_addr_octet[4],
1366 mac.ether_addr_octet[5]);
1367
1368 if (link->ipv4ll) {
1369 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1370 if (r < 0) {
1371 log_warning_link(link, "Could not update MAC "
1372 "address in IPv4LL client: %s",
1373 strerror(-r));
1374 return r;
1375 }
1376 }
1377
1378 if (link->dhcp_client) {
1379 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1380 if (r < 0) {
1381 log_warning_link(link, "Could not update MAC "
1382 "address in DHCP client: %s",
1383 strerror(-r));
1384 return r;
1385 }
1386 }
1387 }
1388
1389 r = sd_rtnl_message_link_get_flags(m, &flags);
1390 if (r < 0) {
1391 log_warning_link(link, "Could not get link flags");
1392 return r;
1393 }
1394
1395 return link_update_flags(link, flags);
1396}
1397
1398int link_save(Link *link) {
1399 _cleanup_free_ char *temp_path = NULL;
1400 _cleanup_fclose_ FILE *f = NULL;
1401 int r;
1402
1403 assert(link);
1404 assert(link->state_file);
1405
1406 r = fopen_temporary(link->state_file, &f, &temp_path);
1407 if (r < 0)
1408 goto finish;
1409
1410 fchmod(fileno(f), 0644);
1411
1412 fprintf(f,
1413 "# This is private data. Do not parse.\n"
1414 "STATE=%s\n",
1415 link_state_to_string(link->state));
1416
1417 if (link->dhcp_lease) {
1418 char *lease_file;
1419
1420 r = asprintf(&lease_file, "/run/systemd/network/leases/%"PRIu64,
1421 link->ifindex);
1422 if (r < 0)
1423 return -ENOMEM;
1424
1425 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1426 if (r < 0)
1427 goto finish;
1428
1429 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1430 }
1431
1432 fflush(f);
1433
1434 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1435 r = -errno;
1436 unlink(link->state_file);
1437 unlink(temp_path);
1438 }
1439
1440finish:
1441 if (r < 0)
1442 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1443
1444 return r;
1445}
1446
1447static const char* const link_state_table[_LINK_STATE_MAX] = {
1448 [LINK_STATE_ENSLAVING] = "configuring",
1449 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1450 [LINK_STATE_SETTING_ROUTES] = "configuring",
1451 [LINK_STATE_CONFIGURED] = "configured",
1452 [LINK_STATE_FAILED] = "failed",
1453};
1454
1455DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);