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