]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-link.c
sd-rtnl: only alter link flags when reqeusted to
[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
29 int link_new(Manager *manager, struct udev_device *device, Link **ret) {
30 _cleanup_link_free_ Link *link = NULL;
31 const char *mac;
32 struct ether_addr *mac_addr;
33 const char *ifname;
34 int r;
35
36 assert(device);
37 assert(ret);
38
39 link = new0(Link, 1);
40 if (!link)
41 return -ENOMEM;
42
43 link->manager = manager;
44 link->state = _LINK_STATE_INVALID;
45
46 link->ifindex = udev_device_get_ifindex(device);
47 if (link->ifindex <= 0)
48 return -EINVAL;
49
50 mac = udev_device_get_sysattr_value(device, "address");
51 if (mac) {
52 mac_addr = ether_aton(mac);
53 if (mac_addr)
54 memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
55 }
56
57 ifname = udev_device_get_sysname(device);
58 link->ifname = strdup(ifname);
59
60 r = hashmap_put(manager->links, &link->ifindex, link);
61 if (r < 0)
62 return r;
63
64 *ret = link;
65 link = NULL;
66
67 return 0;
68 }
69
70 void link_free(Link *link) {
71 if (!link)
72 return;
73
74 assert(link->manager);
75
76 if (link->dhcp)
77 sd_dhcp_client_free(link->dhcp);
78
79 route_free(link->dhcp_route);
80 link->dhcp_route = NULL;
81
82 address_free(link->dhcp_address);
83 link->dhcp_address = NULL;
84
85 hashmap_remove(link->manager->links, &link->ifindex);
86
87 free(link->ifname);
88
89 free(link);
90 }
91
92 int link_add(Manager *m, struct udev_device *device, Link **ret) {
93 Link *link;
94 Network *network;
95 int r;
96 uint64_t ifindex;
97 const char *devtype;
98
99 assert(m);
100 assert(device);
101
102 ifindex = udev_device_get_ifindex(device);
103 link = hashmap_get(m->links, &ifindex);
104 if (link) {
105 *ret = link;
106 return -EEXIST;
107 }
108
109 r = link_new(m, device, &link);
110 if (r < 0)
111 return r;
112
113 *ret = link;
114
115 devtype = udev_device_get_devtype(device);
116 if (streq_ptr(devtype, "bridge")) {
117 r = bridge_set_link(m, link);
118 if (r < 0 && r != -ENOENT)
119 return r;
120 }
121
122 r = network_get(m, device, &network);
123 if (r < 0)
124 return r == -ENOENT ? 0 : r;
125
126 r = network_apply(m, network, link);
127 if (r < 0)
128 return r;
129
130 return 0;
131 }
132
133 static int link_enter_configured(Link *link) {
134 assert(link);
135 assert(link->state == LINK_STATE_SETTING_ROUTES);
136
137 log_info_link(link, "link configured");
138
139 link->state = LINK_STATE_CONFIGURED;
140
141 return 0;
142 }
143
144 static void link_enter_failed(Link *link) {
145 assert(link);
146
147 log_warning_link(link, "failed");
148
149 link->state = LINK_STATE_FAILED;
150 }
151
152 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
153 Link *link = userdata;
154 int r;
155
156 assert(link->route_messages > 0);
157 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
158 link->state == LINK_STATE_SETTING_ROUTES ||
159 link->state == LINK_STATE_FAILED);
160
161 link->route_messages --;
162
163 if (link->state == LINK_STATE_FAILED)
164 return 1;
165
166 r = sd_rtnl_message_get_errno(m);
167 if (r < 0 && r != -EEXIST)
168 log_warning_link(link, "could not set route: %s", strerror(-r));
169
170 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
171 * ignore it */
172 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
173 log_debug_link(link, "routes set");
174 link_enter_configured(link);
175 }
176
177 return 1;
178 }
179
180 static int link_enter_set_routes(Link *link) {
181 Route *route;
182 int r;
183
184 assert(link);
185 assert(link->network);
186 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
187
188 link->state = LINK_STATE_SETTING_ROUTES;
189
190 if (!link->network->static_routes && !link->dhcp_route)
191 return link_enter_configured(link);
192
193 log_debug_link(link, "setting routes");
194
195 LIST_FOREACH(static_routes, route, link->network->static_routes) {
196 r = route_configure(route, link, &route_handler);
197 if (r < 0) {
198 log_warning_link(link,
199 "could not set routes: %s", strerror(-r));
200 link_enter_failed(link);
201 return r;
202 }
203
204 link->route_messages ++;
205 }
206
207 if (link->dhcp_route) {
208 r = route_configure(link->dhcp_route, link, &route_handler);
209 if (r < 0) {
210 log_warning_link(link,
211 "could not set routes: %s", strerror(-r));
212 link_enter_failed(link);
213 return r;
214 }
215
216 link->route_messages ++;
217 }
218
219 return 0;
220 }
221
222 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
223 Link *link = userdata;
224 int r;
225
226 assert(m);
227 assert(link);
228 assert(link->ifname);
229 assert(link->addr_messages > 0);
230 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
231
232 link->addr_messages --;
233
234 if (link->state == LINK_STATE_FAILED)
235 return 1;
236
237 r = sd_rtnl_message_get_errno(m);
238 if (r < 0 && r != -EEXIST)
239 log_struct_link(LOG_ERR, link,
240 "MESSAGE=%s: could not set address: %s",
241 link->ifname, strerror(-r),
242 "ERRNO=%d", -r,
243 NULL);
244
245 if (link->addr_messages == 0) {
246 log_debug_link(link, "addresses set");
247 link_enter_set_routes(link);
248 }
249
250 return 1;
251 }
252
253 static int link_enter_set_addresses(Link *link) {
254 Address *address;
255 int r;
256
257 assert(link);
258 assert(link->network);
259 assert(link->state != _LINK_STATE_INVALID);
260
261 link->state = LINK_STATE_SETTING_ADDRESSES;
262
263 if (!link->network->static_addresses && !link->dhcp_address)
264 return link_enter_set_routes(link);
265
266 log_debug_link(link, "setting addresses");
267
268 LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
269 r = address_configure(address, link, &address_handler);
270 if (r < 0) {
271 log_warning_link(link,
272 "could not set addresses: %s", strerror(-r));
273 link_enter_failed(link);
274 return r;
275 }
276
277 link->addr_messages ++;
278 }
279
280 if (link->dhcp_address) {
281 r = address_configure(link->dhcp_address, link, &address_handler);
282 if (r < 0) {
283 log_warning_link(link,
284 "could not set addresses: %s", strerror(-r));
285 link_enter_failed(link);
286 return r;
287 }
288
289 link->addr_messages ++;
290 }
291
292 return 0;
293 }
294
295 static int address_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 != -EEXIST)
308 log_warning_link(link, "could not drop address: %s", strerror(-r));
309
310 return 1;
311 }
312
313 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
314 Link *link = userdata;
315 struct in_addr address;
316 struct in_addr netmask;
317 struct in_addr gateway;
318 int prefixlen;
319 int r;
320
321 assert(link);
322 assert(link->network);
323
324 if (link->state == LINK_STATE_FAILED)
325 return;
326
327 if (event < 0) {
328 log_warning_link(link, "DHCP error: %s", strerror(-event));
329 link_enter_failed(link);
330 return;
331 }
332
333 if (event == DHCP_EVENT_NO_LEASE)
334 log_debug_link(link, "IP address in use.");
335
336 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
337 event == DHCP_EVENT_STOP) {
338 if (link->dhcp_address) {
339 address_drop(link->dhcp_address, link, address_drop_handler);
340
341 address_free(link->dhcp_address);
342 link->dhcp_address = NULL;
343 }
344
345 if (link->dhcp_route) {
346 route_free(link->dhcp_route);
347 link->dhcp_route = NULL;
348 }
349 }
350
351 r = sd_dhcp_client_get_address(client, &address);
352 if (r < 0) {
353 log_warning_link(link, "DHCP error: no address");
354 link_enter_failed(link);
355 return;
356 }
357
358 r = sd_dhcp_client_get_netmask(client, &netmask);
359 if (r < 0) {
360 log_warning_link(link, "DHCP error: no netmask");
361 link_enter_failed(link);
362 return;
363 }
364
365 prefixlen = sd_dhcp_client_prefixlen(&netmask);
366 if (prefixlen < 0) {
367 log_warning_link(link, "DHCP error: no prefixlen");
368 link_enter_failed(link);
369 return;
370 }
371
372 r = sd_dhcp_client_get_router(client, &gateway);
373 if (r < 0) {
374 log_warning_link(link, "DHCP error: no router");
375 link_enter_failed(link);
376 return;
377 }
378
379 if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
380 _cleanup_address_free_ Address *addr = NULL;
381 _cleanup_route_free_ Route *rt = NULL;
382 struct in_addr **nameservers;
383
384 log_struct_link(LOG_INFO, link,
385 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
386 link->ifname,
387 ADDRESS_FMT_VAL(address),
388 prefixlen,
389 ADDRESS_FMT_VAL(gateway),
390 "ADDRESS=%u.%u.%u.%u",
391 ADDRESS_FMT_VAL(address),
392 "PREFIXLEN=%u",
393 prefixlen,
394 "GATEWAY=%u.%u.%u.%u",
395 ADDRESS_FMT_VAL(gateway),
396 NULL);
397
398 r = address_new_dynamic(&addr);
399 if (r < 0) {
400 log_error_link(link, "Could not allocate address");
401 link_enter_failed(link);
402 return;
403 }
404
405 addr->family = AF_INET;
406 addr->in_addr.in = address;
407 addr->prefixlen = prefixlen;
408 addr->netmask = netmask;
409
410 r = route_new_dynamic(&rt);
411 if (r < 0) {
412 log_error_link(link, "Could not allocate route");
413 link_enter_failed(link);
414 return;
415 }
416
417 rt->family = AF_INET;
418 rt->in_addr.in = gateway;
419
420 link->dhcp_address = addr;
421 link->dhcp_route = rt;
422 addr = NULL;
423 rt = NULL;
424
425 if (link->network->dhcp_dns) {
426 r = sd_dhcp_client_get_dns(client, &nameservers);
427 if (r >= 0) {
428 r = manager_update_resolv_conf(link->manager);
429 if (r < 0)
430 log_error("Failed to update resolv.conf");
431 }
432 }
433
434 link_enter_set_addresses(link);
435 }
436
437 return;
438 }
439
440 static int link_acquire_conf(Link *link) {
441 int r;
442
443 assert(link);
444 assert(link->network);
445 assert(link->network->dhcp);
446 assert(link->manager);
447 assert(link->manager->event);
448
449 if (!link->dhcp) {
450 link->dhcp = sd_dhcp_client_new(link->manager->event);
451 if (!link->dhcp)
452 return -ENOMEM;
453
454 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
455 if (r < 0)
456 return r;
457
458 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
459 if (r < 0)
460 return r;
461
462 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
463 if (r < 0)
464 return r;
465 }
466
467 log_debug_link(link, "acquiring DHCPv4 lease");
468
469 r = sd_dhcp_client_start(link->dhcp);
470 if (r < 0)
471 return r;
472
473 return 0;
474 }
475
476 static int link_update_flags(Link *link, unsigned flags) {
477 int r;
478
479 assert(link);
480 assert(link->network);
481
482 if (link->state == LINK_STATE_FAILED)
483 return 0;
484
485 if (link->flags == flags) {
486 log_debug_link(link, "link status unchanged: %#.8x", flags);
487 return 0;
488 }
489
490 if ((link->flags & IFF_UP) != (flags & IFF_UP))
491 log_info_link(link,
492 "power %s", flags & IFF_UP ? "on": "off");
493
494 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
495 if (flags & IFF_LOWER_UP) {
496 log_info_link(link, "carrier on");
497
498 if (link->network->dhcp) {
499 r = link_acquire_conf(link);
500 if (r < 0) {
501 link_enter_failed(link);
502 return r;
503 }
504 }
505 } else {
506 log_info_link(link, "carrier off");
507
508 if (link->network->dhcp) {
509 r = sd_dhcp_client_stop(link->dhcp);
510 if (r < 0) {
511 link_enter_failed(link);
512 return r;
513 }
514 }
515 }
516 }
517
518 log_debug_link(link,
519 "link status updated: %#.8x -> %#.8x", link->flags, flags);
520
521 link->flags = flags;
522
523 return 0;
524 }
525
526 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
527 Link *link = userdata;
528 int r;
529
530 assert(link);
531
532 if (link->state == LINK_STATE_FAILED)
533 return 1;
534
535 r = sd_rtnl_message_get_errno(m);
536 if (r < 0) {
537 log_warning_link(link,
538 "could not bring up interface: %s", strerror(-r));
539 link_enter_failed(link);
540 }
541
542 link_update_flags(link, link->flags | IFF_UP);
543
544 return 1;
545 }
546
547 static int link_up(Link *link) {
548 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
549 int r;
550
551 assert(link);
552 assert(link->manager);
553 assert(link->manager->rtnl);
554
555 log_debug_link(link, "bringing link up");
556
557 r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
558 if (r < 0) {
559 log_error_link(link, "Could not allocate RTM_SETLINK message");
560 return r;
561 }
562
563 r = sd_rtnl_message_link_set_flags(req, IFF_UP);
564 if (r < 0) {
565 log_error_link(link, "Could not set link flags: %s", strerror(-r));
566 return r;
567 }
568
569 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
570 if (r < 0) {
571 log_error_link(link,
572 "Could not send rtnetlink message: %s", strerror(-r));
573 return r;
574 }
575
576 return 0;
577 }
578
579 static int link_bridge_joined(Link *link) {
580 int r;
581
582 assert(link);
583 assert(link->state == LINK_STATE_JOINING_BRIDGE);
584 assert(link->network);
585
586 r = link_up(link);
587 if (r < 0) {
588 link_enter_failed(link);
589 return r;
590 }
591
592 if (!link->network->dhcp)
593 return link_enter_set_addresses(link);
594
595 return 0;
596 }
597
598 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
599 Link *link = userdata;
600 int r;
601
602 assert(link);
603 assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
604 assert(link->network);
605
606 if (link->state == LINK_STATE_FAILED)
607 return 1;
608
609 r = sd_rtnl_message_get_errno(m);
610 if (r < 0) {
611 log_struct_link(LOG_ERR, link,
612 "MESSAGE=%s: could not join bridge '%s': %s",
613 link->ifname, link->network->bridge->name, strerror(-r),
614 BRIDGE(link->network->bridge),
615 NULL);
616 link_enter_failed(link);
617 return 1;
618 }
619
620 log_struct_link(LOG_DEBUG, link,
621 "MESSAGE=%s: joined bridge '%s'",
622 link->network->bridge->name,
623 BRIDGE(link->network->bridge),
624 NULL);
625
626 link_bridge_joined(link);
627
628 return 1;
629 }
630
631 static int link_enter_join_bridge(Link *link) {
632 int r;
633
634 assert(link);
635 assert(link->network);
636 assert(link->state == _LINK_STATE_INVALID);
637
638 link->state = LINK_STATE_JOINING_BRIDGE;
639
640 if (!link->network->bridge)
641 return link_bridge_joined(link);
642
643 log_struct_link(LOG_DEBUG, link,
644 "MESSAGE=%s: joining bridge '%s'",
645 link->network->bridge->name,
646 BRIDGE(link->network->bridge),
647 NULL);
648 log_debug_link(link, "joining bridge");
649
650 r = bridge_join(link->network->bridge, link, &bridge_handler);
651 if (r < 0) {
652 log_struct_link(LOG_WARNING, link,
653 "MESSAGE=%s: could not join bridge '%s': %s",
654 link->network->bridge->name, strerror(-r),
655 BRIDGE(link->network->bridge),
656 NULL);
657 link_enter_failed(link);
658 return r;
659 }
660
661 return 0;
662 }
663
664 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
665 Link *link = userdata;
666 int r;
667
668 assert(link);
669
670 if (link->state == LINK_STATE_FAILED)
671 return 1;
672
673 r = sd_rtnl_message_get_errno(m);
674 if (r < 0) {
675 log_warning_link(link, "could not get state: %s", strerror(-r));
676 link_enter_failed(link);
677 }
678
679 log_debug_link(link, "got link state");
680
681 link_update(link, m);
682
683 return 1;
684 }
685
686 static int link_get(Link *link) {
687 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
688 int r;
689
690 assert(link);
691 assert(link->manager);
692 assert(link->manager->rtnl);
693
694 log_debug_link(link, "requesting link status");
695
696 r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
697 if (r < 0) {
698 log_error_link(link, "Could not allocate RTM_GETLINK message");
699 return r;
700 }
701
702 r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
703 if (r < 0) {
704 log_error_link(link,
705 "Could not send rtnetlink message: %s", strerror(-r));
706 return r;
707 }
708
709 return 0;
710 }
711
712 int link_configure(Link *link) {
713 int r;
714
715 assert(link);
716 assert(link->network);
717 assert(link->state == _LINK_STATE_INVALID);
718
719 r = link_get(link);
720 if (r < 0) {
721 link_enter_failed(link);
722 return r;
723 }
724
725 return link_enter_join_bridge(link);
726 }
727
728 int link_update(Link *link, sd_rtnl_message *m) {
729 unsigned flags;
730 int r;
731
732 assert(link);
733 assert(m);
734
735 if (link->state == LINK_STATE_FAILED)
736 return 0;
737
738 r = sd_rtnl_message_link_get_flags(m, &flags);
739 if (r < 0) {
740 log_warning_link(link, "could not get link flags");
741 return r;
742 }
743
744 return link_update_flags(link, flags);
745 }