chiark / gitweb /
3c683a0ce0fa0ec8bafa2eabd98cb4130236f650
[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_link_info(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_link_warning(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_link_debug(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_link_debug(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_link_debug(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_link_debug(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_link_debug(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_link_warning(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_link_warning(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_link_warning(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_link_warning(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_link_error(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_link_error(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         r = sd_dhcp_client_start(link->dhcp);
457         if (r < 0)
458                 return r;
459
460         return 0;
461 }
462
463 static int link_update_flags(Link *link, unsigned flags) {
464         int r;
465
466         assert(link);
467         assert(link->network);
468
469         if (link->state == LINK_STATE_FAILED)
470                 return 0;
471
472         if (link->flags == flags) {
473                 log_debug_link(link, "link status unchanged: %#x", flags);
474                 return 0;
475         }
476
477         if ((link->flags & IFF_UP) != (flags & IFF_UP))
478                 log_info_link(link,
479                               "power %s", flags & IFF_UP ? "on": "off");
480
481         if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
482                 if (flags & IFF_LOWER_UP) {
483                         log_link_info(link, "carrier on");
484
485                         if (link->network->dhcp) {
486                                 r = link_acquire_conf(link);
487                                 if (r < 0) {
488                                         link_enter_failed(link);
489                                         return r;
490                                 }
491                         }
492                 } else {
493                         log_link_info(link, "carrier off");
494
495                         if (link->network->dhcp) {
496                                 r = sd_dhcp_client_stop(link->dhcp);
497                                 if (r < 0) {
498                                         link_enter_failed(link);
499                                         return r;
500                                 }
501                         }
502                 }
503         }
504
505         log_debug_link(link,
506                        "link status updated: %#x -> %#x", link->flags, flags);
507
508         link->flags = flags;
509
510         return 0;
511 }
512
513 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
514         Link *link = userdata;
515         int r;
516
517         assert(link);
518
519         if (link->state == LINK_STATE_FAILED)
520                 return 1;
521
522         r = sd_rtnl_message_get_errno(m);
523         if (r < 0) {
524                 log_warning_link(link,
525                                  "could not bring up interface: %s", strerror(-r));
526                 link_enter_failed(link);
527         }
528
529         link_update_flags(link, link->flags | IFF_UP);
530
531         return 1;
532 }
533
534 static int link_up(Link *link) {
535         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
536         int r;
537
538         assert(link);
539         assert(link->manager);
540         assert(link->manager->rtnl);
541
542         log_link_debug(link, "bringing link up");
543
544         r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
545         if (r < 0) {
546                 log_link_error(link, "Could not allocate RTM_SETLINK message");
547                 return r;
548         }
549
550         r = sd_rtnl_message_link_set_flags(req, IFF_UP);
551         if (r < 0) {
552                 log_error_link(link, "Could not set link flags: %s", strerror(-r));
553                 return r;
554         }
555
556         r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
557         if (r < 0) {
558                 log_error_link(link,
559                                "Could not send rtnetlink message: %s", strerror(-r));
560                 return r;
561         }
562
563         return 0;
564 }
565
566 static int link_bridge_joined(Link *link) {
567         int r;
568
569         assert(link);
570         assert(link->state == LINK_STATE_JOINING_BRIDGE);
571         assert(link->network);
572
573         r = link_up(link);
574         if (r < 0) {
575                 link_enter_failed(link);
576                 return r;
577         }
578
579         if (!link->network->dhcp)
580                 return link_enter_set_addresses(link);
581
582         return 0;
583 }
584
585 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
586         Link *link = userdata;
587         int r;
588
589         assert(link);
590         assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
591         assert(link->network);
592
593         if (link->state == LINK_STATE_FAILED)
594                 return 1;
595
596         r = sd_rtnl_message_get_errno(m);
597         if (r < 0) {
598                 log_struct_link(LOG_ERR, link,
599                                 "MESSAGE=%s: could not join bridge '%s': %s",
600                                 link->ifname, link->network->bridge->name, strerror(-r),
601                                 BRIDGE(link->network->bridge),
602                                 NULL);
603                 link_enter_failed(link);
604                 return 1;
605         }
606
607         log_struct_link(LOG_DEBUG, link,
608                         "MESSAGE=%s: joined bridge '%s'",
609                         link->network->bridge->name,
610                         BRIDGE(link->network->bridge),
611                         NULL);
612         link_bridge_joined(link);
613
614         return 1;
615 }
616
617 static int link_enter_join_bridge(Link *link) {
618         int r;
619
620         assert(link);
621         assert(link->network);
622         assert(link->state == _LINK_STATE_INVALID);
623
624         link->state = LINK_STATE_JOINING_BRIDGE;
625
626         if (!link->network->bridge)
627                 return link_bridge_joined(link);
628
629         log_struct_link(LOG_DEBUG, link,
630                         "MESSAGE=%s: joining bridge '%s'",
631                         link->network->bridge->name,
632                         BRIDGE(link->network->bridge),
633                         NULL);
634         log_link_debug(link, "joining bridge");
635
636         r = bridge_join(link->network->bridge, link, &bridge_handler);
637         if (r < 0) {
638                 log_struct_link(LOG_WARNING, link,
639                                 "MESSAGE=%s: could not join bridge '%s': %s",
640                                 link->network->bridge->name, strerror(-r),
641                                 BRIDGE(link->network->bridge),
642                                 NULL);
643                 link_enter_failed(link);
644                 return r;
645         }
646
647         return 0;
648 }
649
650 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
651         Link *link = userdata;
652         int r;
653
654         assert(link);
655
656         if (link->state == LINK_STATE_FAILED)
657                 return 1;
658
659         r = sd_rtnl_message_get_errno(m);
660         if (r < 0) {
661                 log_warning_link(link, "could not get state: %s", strerror(-r));
662                 link_enter_failed(link);
663         }
664
665         log_link_debug(link, "got link state");
666
667         link_update(link, m);
668
669         return 1;
670 }
671
672 static int link_get(Link *link) {
673         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
674         int r;
675
676         assert(link);
677         assert(link->manager);
678         assert(link->manager->rtnl);
679
680         log_link_debug(link, "requesting link status");
681
682         r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
683         if (r < 0) {
684                 log_link_error(link, "Could not allocate RTM_GETLINK message");
685                 return r;
686         }
687
688         r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
689         if (r < 0) {
690                 log_error_link(link,
691                                "Could not send rtnetlink message: %s", strerror(-r));
692                 return r;
693         }
694
695         return 0;
696 }
697
698 int link_configure(Link *link) {
699         int r;
700
701         assert(link);
702         assert(link->network);
703         assert(link->state == _LINK_STATE_INVALID);
704
705         r = link_get(link);
706         if (r < 0) {
707                 link_enter_failed(link);
708                 return r;
709         }
710
711         return link_enter_join_bridge(link);
712 }
713
714 int link_update(Link *link, sd_rtnl_message *m) {
715         unsigned flags;
716         int r;
717
718         assert(link);
719         assert(m);
720
721         if (link->state == LINK_STATE_FAILED)
722                 return 0;
723
724         r = sd_rtnl_message_link_get_flags(m, &flags);
725         if (r < 0) {
726                 log_link_warning(link, "could not get link flags");
727                 return r;
728         }
729
730         return link_update_flags(link, flags);
731 }