chiark / gitweb /
25d92c8aa4f46574b68c87e4b21e1c64bd7eaacc
[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
323         if (link->state == LINK_STATE_FAILED)
324                 return;
325
326         if (event < 0) {
327                 log_warning_link(link, "DHCP error: %s", strerror(-event));
328                 link_enter_failed(link);
329                 return;
330         }
331
332         if (event == DHCP_EVENT_NO_LEASE)
333                 log_debug_link(link, "IP address in use.");
334
335         if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
336             event == DHCP_EVENT_STOP) {
337                 if (link->dhcp_address) {
338                         address_drop(link->dhcp_address, link, address_drop_handler);
339
340                         address_free(link->dhcp_address);
341                         link->dhcp_address = NULL;
342                 }
343
344                 if (link->dhcp_route) {
345                         route_free(link->dhcp_route);
346                         link->dhcp_route = NULL;
347                 }
348         }
349
350         r = sd_dhcp_client_get_address(client, &address);
351         if (r < 0) {
352                 log_warning_link(link, "DHCP error: no address");
353                 link_enter_failed(link);
354                 return;
355         }
356
357         r = sd_dhcp_client_get_netmask(client, &netmask);
358         if (r < 0) {
359                 log_warning_link(link, "DHCP error: no netmask");
360                 link_enter_failed(link);
361                 return;
362         }
363
364         prefixlen = sd_dhcp_client_prefixlen(&netmask);
365         if (prefixlen < 0) {
366                 log_warning_link(link, "DHCP error: no prefixlen");
367                 link_enter_failed(link);
368                 return;
369         }
370
371         r = sd_dhcp_client_get_router(client, &gateway);
372         if (r < 0) {
373                 log_warning_link(link, "DHCP error: no router");
374                 link_enter_failed(link);
375                 return;
376         }
377
378         if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
379                 _cleanup_address_free_ Address *addr = NULL;
380                 _cleanup_route_free_ Route *rt = NULL;
381
382                 log_struct_link(LOG_INFO, link,
383                                 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
384                                 link->ifname,
385                                 ADDRESS_FMT_VAL(address),
386                                 prefixlen,
387                                 ADDRESS_FMT_VAL(gateway),
388                                 "ADDRESS=%u.%u.%u.%u",
389                                 ADDRESS_FMT_VAL(address),
390                                 "PREFIXLEN=%u",
391                                 prefixlen,
392                                 "GATEWAY=%u.%u.%u.%u",
393                                 ADDRESS_FMT_VAL(gateway),
394                                 NULL);
395
396                 r = address_new_dynamic(&addr);
397                 if (r < 0) {
398                         log_error_link(link, "Could not allocate address");
399                         link_enter_failed(link);
400                         return;
401                 }
402
403                 addr->family = AF_INET;
404                 addr->in_addr.in = address;
405                 addr->prefixlen = prefixlen;
406                 addr->netmask = netmask;
407
408                 r = route_new_dynamic(&rt);
409                 if (r < 0) {
410                         log_error_link(link, "Could not allocate route");
411                         link_enter_failed(link);
412                         return;
413                 }
414
415                 rt->family = AF_INET;
416                 rt->in_addr.in = gateway;
417
418                 link->dhcp_address = addr;
419                 link->dhcp_route = rt;
420                 addr = NULL;
421                 rt = NULL;
422
423                 link_enter_set_addresses(link);
424         }
425
426         return;
427 }
428
429 static int link_acquire_conf(Link *link) {
430         int r;
431
432         assert(link);
433         assert(link->network);
434         assert(link->network->dhcp);
435         assert(link->manager);
436         assert(link->manager->event);
437
438         if (!link->dhcp) {
439                 link->dhcp = sd_dhcp_client_new(link->manager->event);
440                 if (!link->dhcp)
441                         return -ENOMEM;
442
443                 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
444                 if (r < 0)
445                         return r;
446
447                 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
448                 if (r < 0)
449                         return r;
450
451                 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
452                 if (r < 0)
453                         return r;
454         }
455
456         log_debug_link(link, "acquiring DHCPv4 lease");
457
458         r = sd_dhcp_client_start(link->dhcp);
459         if (r < 0)
460                 return r;
461
462         return 0;
463 }
464
465 static int link_update_flags(Link *link, unsigned flags) {
466         int r;
467
468         assert(link);
469         assert(link->network);
470
471         if (link->state == LINK_STATE_FAILED)
472                 return 0;
473
474         if (link->flags == flags) {
475                 log_debug_link(link, "link status unchanged: %#.8x", flags);
476                 return 0;
477         }
478
479         if ((link->flags & IFF_UP) != (flags & IFF_UP))
480                 log_info_link(link,
481                               "power %s", flags & IFF_UP ? "on": "off");
482
483         if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
484                 if (flags & IFF_LOWER_UP) {
485                         log_info_link(link, "carrier on");
486
487                         if (link->network->dhcp) {
488                                 r = link_acquire_conf(link);
489                                 if (r < 0) {
490                                         link_enter_failed(link);
491                                         return r;
492                                 }
493                         }
494                 } else {
495                         log_info_link(link, "carrier off");
496
497                         if (link->network->dhcp) {
498                                 r = sd_dhcp_client_stop(link->dhcp);
499                                 if (r < 0) {
500                                         link_enter_failed(link);
501                                         return r;
502                                 }
503                         }
504                 }
505         }
506
507         log_debug_link(link,
508                        "link status updated: %#.8x -> %#.8x", link->flags, flags);
509
510         link->flags = flags;
511
512         return 0;
513 }
514
515 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
516         Link *link = userdata;
517         int r;
518
519         assert(link);
520
521         if (link->state == LINK_STATE_FAILED)
522                 return 1;
523
524         r = sd_rtnl_message_get_errno(m);
525         if (r < 0) {
526                 log_warning_link(link,
527                                  "could not bring up interface: %s", strerror(-r));
528                 link_enter_failed(link);
529         }
530
531         link_update_flags(link, link->flags | IFF_UP);
532
533         return 1;
534 }
535
536 static int link_up(Link *link) {
537         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
538         int r;
539
540         assert(link);
541         assert(link->manager);
542         assert(link->manager->rtnl);
543
544         log_debug_link(link, "bringing link up");
545
546         r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
547         if (r < 0) {
548                 log_error_link(link, "Could not allocate RTM_SETLINK message");
549                 return r;
550         }
551
552         r = sd_rtnl_message_link_set_flags(req, IFF_UP);
553         if (r < 0) {
554                 log_error_link(link, "Could not set link flags: %s", strerror(-r));
555                 return r;
556         }
557
558         r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
559         if (r < 0) {
560                 log_error_link(link,
561                                "Could not send rtnetlink message: %s", strerror(-r));
562                 return r;
563         }
564
565         return 0;
566 }
567
568 static int link_bridge_joined(Link *link) {
569         int r;
570
571         assert(link);
572         assert(link->state == LINK_STATE_JOINING_BRIDGE);
573         assert(link->network);
574
575         r = link_up(link);
576         if (r < 0) {
577                 link_enter_failed(link);
578                 return r;
579         }
580
581         if (!link->network->dhcp)
582                 return link_enter_set_addresses(link);
583
584         return 0;
585 }
586
587 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
588         Link *link = userdata;
589         int r;
590
591         assert(link);
592         assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
593         assert(link->network);
594
595         if (link->state == LINK_STATE_FAILED)
596                 return 1;
597
598         r = sd_rtnl_message_get_errno(m);
599         if (r < 0) {
600                 log_struct_link(LOG_ERR, link,
601                                 "MESSAGE=%s: could not join bridge '%s': %s",
602                                 link->ifname, link->network->bridge->name, strerror(-r),
603                                 BRIDGE(link->network->bridge),
604                                 NULL);
605                 link_enter_failed(link);
606                 return 1;
607         }
608
609         log_struct_link(LOG_DEBUG, link,
610                         "MESSAGE=%s: joined bridge '%s'",
611                         link->network->bridge->name,
612                         BRIDGE(link->network->bridge),
613                         NULL);
614
615         link_bridge_joined(link);
616
617         return 1;
618 }
619
620 static int link_enter_join_bridge(Link *link) {
621         int r;
622
623         assert(link);
624         assert(link->network);
625         assert(link->state == _LINK_STATE_INVALID);
626
627         link->state = LINK_STATE_JOINING_BRIDGE;
628
629         if (!link->network->bridge)
630                 return link_bridge_joined(link);
631
632         log_struct_link(LOG_DEBUG, link,
633                         "MESSAGE=%s: joining bridge '%s'",
634                         link->network->bridge->name,
635                         BRIDGE(link->network->bridge),
636                         NULL);
637         log_debug_link(link, "joining bridge");
638
639         r = bridge_join(link->network->bridge, link, &bridge_handler);
640         if (r < 0) {
641                 log_struct_link(LOG_WARNING, link,
642                                 "MESSAGE=%s: could not join bridge '%s': %s",
643                                 link->network->bridge->name, strerror(-r),
644                                 BRIDGE(link->network->bridge),
645                                 NULL);
646                 link_enter_failed(link);
647                 return r;
648         }
649
650         return 0;
651 }
652
653 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
654         Link *link = userdata;
655         int r;
656
657         assert(link);
658
659         if (link->state == LINK_STATE_FAILED)
660                 return 1;
661
662         r = sd_rtnl_message_get_errno(m);
663         if (r < 0) {
664                 log_warning_link(link, "could not get state: %s", strerror(-r));
665                 link_enter_failed(link);
666         }
667
668         log_debug_link(link, "got link state");
669
670         link_update(link, m);
671
672         return 1;
673 }
674
675 static int link_get(Link *link) {
676         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
677         int r;
678
679         assert(link);
680         assert(link->manager);
681         assert(link->manager->rtnl);
682
683         log_debug_link(link, "requesting link status");
684
685         r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
686         if (r < 0) {
687                 log_error_link(link, "Could not allocate RTM_GETLINK message");
688                 return r;
689         }
690
691         r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
692         if (r < 0) {
693                 log_error_link(link,
694                                "Could not send rtnetlink message: %s", strerror(-r));
695                 return r;
696         }
697
698         return 0;
699 }
700
701 int link_configure(Link *link) {
702         int r;
703
704         assert(link);
705         assert(link->network);
706         assert(link->state == _LINK_STATE_INVALID);
707
708         r = link_get(link);
709         if (r < 0) {
710                 link_enter_failed(link);
711                 return r;
712         }
713
714         return link_enter_join_bridge(link);
715 }
716
717 int link_update(Link *link, sd_rtnl_message *m) {
718         unsigned flags;
719         int r;
720
721         assert(link);
722         assert(m);
723
724         if (link->state == LINK_STATE_FAILED)
725                 return 0;
726
727         r = sd_rtnl_message_link_get_flags(m, &flags);
728         if (r < 0) {
729                 log_warning_link(link, "could not get link flags");
730                 return r;
731         }
732
733         return link_update_flags(link, flags);
734 }