chiark / gitweb /
6186f7f892603f16c617f928d31b367755fd52f5
[elogind.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 }