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