chiark / gitweb /
bus: always create --user bus when kdbus is active
[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) {
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                 return 0;
106
107         r = link_new(m, device, &link);
108         if (r < 0) {
109                 log_error("Could not create link: %s", strerror(-r));
110                 return r;
111         }
112
113         devtype = udev_device_get_devtype(device);
114         if (streq_ptr(devtype, "bridge")) {
115                 r = bridge_set_link(m, link);
116                 if (r < 0)
117                         return r == -ENOENT ? 0 : r;
118         }
119
120         r = network_get(m, device, &network);
121         if (r < 0)
122                 return r == -ENOENT ? 0 : r;
123
124         r = network_apply(m, network, link);
125         if (r < 0)
126                 return r;
127
128         return 0;
129 }
130
131 static int link_enter_configured(Link *link) {
132         assert(link);
133         assert(link->state == LINK_STATE_SETTING_ROUTES);
134
135         log_info("%s: link configured", link->ifname);
136
137         link->state = LINK_STATE_CONFIGURED;
138
139         return 0;
140 }
141
142 static void link_enter_failed(Link *link) {
143         assert(link);
144
145         log_warning("%s: failed", link->ifname);
146
147         link->state = LINK_STATE_FAILED;
148 }
149
150 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
151         Link *link = userdata;
152         int r;
153
154         assert(link->route_messages > 0);
155         assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
156                link->state == LINK_STATE_SETTING_ROUTES ||
157                link->state == LINK_STATE_FAILED);
158
159         link->route_messages --;
160
161         if (link->state == LINK_STATE_FAILED)
162                 return 1;
163
164         r = sd_rtnl_message_get_errno(m);
165         if (r < 0 && r != -EEXIST)
166                 log_warning("%s: could not set route: %s",
167                             link->ifname, strerror(-r));
168
169         /* we might have received an old reply after moving back to SETTING_ADDRESSES,
170          * ignore it */
171         if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
172                 log_debug("%s: routes set", link->ifname);
173                 link_enter_configured(link);
174         }
175
176         return 1;
177 }
178
179 static int link_enter_set_routes(Link *link) {
180         Route *route;
181         int r;
182
183         assert(link);
184         assert(link->network);
185         assert(link->state == LINK_STATE_SETTING_ADDRESSES);
186
187         link->state = LINK_STATE_SETTING_ROUTES;
188
189         if (!link->network->static_routes && !link->dhcp_route)
190                 return link_enter_configured(link);
191
192         log_debug("%s: setting routes", link->ifname);
193
194         LIST_FOREACH(static_routes, route, link->network->static_routes) {
195                 r = route_configure(route, link, &route_handler);
196                 if (r < 0) {
197                         log_warning("%s: could not set routes", link->ifname);
198                         link_enter_failed(link);
199                         return r;
200                 }
201
202                 link->route_messages ++;
203         }
204
205         if (link->dhcp_route) {
206                 r = route_configure(link->dhcp_route, link, &route_handler);
207                 if (r < 0) {
208                         log_warning("%s: could not set routes", link->ifname);
209                         link_enter_failed(link);
210                         return r;
211                 }
212
213                 link->route_messages ++;
214         }
215
216         return 0;
217 }
218
219 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
220         Link *link = userdata;
221         int r;
222
223         assert(m);
224         assert(link);
225         assert(link->ifname);
226         assert(link->addr_messages > 0);
227         assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
228
229         link->addr_messages --;
230
231         if (link->state == LINK_STATE_FAILED)
232                 return 1;
233
234         r = sd_rtnl_message_get_errno(m);
235         if (r < 0 && r != -EEXIST)
236                 log_warning("%s: could not set address: %s",
237                             link->ifname, strerror(-r));
238
239         if (link->addr_messages == 0) {
240                 log_debug("%s: addresses set", link->ifname);
241                 link_enter_set_routes(link);
242         }
243
244         return 1;
245 }
246
247 static int link_enter_set_addresses(Link *link) {
248         Address *address;
249         int r;
250
251         assert(link);
252         assert(link->network);
253         assert(link->state != _LINK_STATE_INVALID);
254
255         link->state = LINK_STATE_SETTING_ADDRESSES;
256
257         if (!link->network->static_addresses && !link->dhcp_address)
258                 return link_enter_set_routes(link);
259
260         log_debug("%s: setting addresses", link->ifname);
261
262         LIST_FOREACH(static_addresses, address, link->network->static_addresses) {
263                 r = address_configure(address, link, &address_handler);
264                 if (r < 0) {
265                         log_warning("%s: could not set addresses", link->ifname);
266                         link_enter_failed(link);
267                         return r;
268                 }
269
270                 link->addr_messages ++;
271         }
272
273         if (link->dhcp_address) {
274                 r = address_configure(link->dhcp_address, link, &address_handler);
275                 if (r < 0) {
276                         log_warning("%s: could not set addresses", link->ifname);
277                         link_enter_failed(link);
278                         return r;
279                 }
280
281                 link->addr_messages ++;
282         }
283
284         return 0;
285 }
286
287 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
288         Link *link = userdata;
289         int r;
290
291         assert(m);
292         assert(link);
293         assert(link->ifname);
294
295         if (link->state == LINK_STATE_FAILED)
296                 return 1;
297
298         r = sd_rtnl_message_get_errno(m);
299         if (r < 0 && r != -EEXIST)
300                 log_warning("%s: could not drop address: %s",
301                             link->ifname, strerror(-r));
302
303         return 1;
304 }
305
306 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
307         Link *link = userdata;
308         struct in_addr address;
309         struct in_addr netmask;
310         struct in_addr gateway;
311         int prefixlen;
312         int r;
313
314         assert(link);
315
316         if (link->state == LINK_STATE_FAILED)
317                 return;
318
319         if (event < 0) {
320                 log_warning("%s: DHCP error: %s", link->ifname, strerror(-event));
321                 link_enter_failed(link);
322                 return;
323         }
324
325         if (event == DHCP_EVENT_NO_LEASE)
326                 log_debug("%s: IP address in use.", link->ifname);
327
328         if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_EXPIRED ||
329             event == DHCP_EVENT_STOP) {
330                 if (link->dhcp_address) {
331                         address_drop(link->dhcp_address, link, address_drop_handler);
332
333                         address_free(link->dhcp_address);
334                         link->dhcp_address = NULL;
335                 }
336
337                 if (link->dhcp_route) {
338                         route_free(link->dhcp_route);
339                         link->dhcp_route = NULL;
340                 }
341         }
342
343         r = sd_dhcp_client_get_address(client, &address);
344         if (r < 0) {
345                 log_warning("%s: DHCP error: no address", link->ifname);
346                 link_enter_failed(link);
347                 return;
348         }
349
350         r = sd_dhcp_client_get_netmask(client, &netmask);
351         if (r < 0) {
352                 log_warning("%s: DHCP error: no netmask", link->ifname);
353                 link_enter_failed(link);
354                 return;
355         }
356
357         prefixlen = sd_dhcp_client_prefixlen(&netmask);
358         if (prefixlen < 0) {
359                 log_warning("%s: DHCP error: no prefixlen", link->ifname);
360                 link_enter_failed(link);
361                 return;
362         }
363
364         r = sd_dhcp_client_get_router(client, &gateway);
365         if (r < 0) {
366                 log_warning("%s: DHCP error: no router", link->ifname);
367                 link_enter_failed(link);
368                 return;
369         }
370
371         if (event == DHCP_EVENT_IP_CHANGE || event == DHCP_EVENT_IP_ACQUIRE) {
372                 _cleanup_address_free_ Address *addr = NULL;
373                 _cleanup_route_free_ Route *rt = NULL;
374
375                 log_info("%s: received config over DHCPv4", link->ifname);
376
377                 r = address_new_dynamic(&addr);
378                 if (r < 0) {
379                         log_error("Could not allocate address");
380                         link_enter_failed(link);
381                         return;
382                 }
383
384                 addr->family = AF_INET;
385                 addr->in_addr.in = address;
386                 addr->prefixlen = prefixlen;
387                 addr->netmask = netmask;
388
389                 r = route_new_dynamic(&rt);
390                 if (r < 0) {
391                         log_error("Could not allocate route");
392                         link_enter_failed(link);
393                         return;
394                 }
395
396                 rt->family = AF_INET;
397                 rt->in_addr.in = gateway;
398
399                 link->dhcp_address = addr;
400                 link->dhcp_route = rt;
401                 addr = NULL;
402                 rt = NULL;
403
404                 link_enter_set_addresses(link);
405         }
406
407         return;
408 }
409
410 static int link_acquire_conf(Link *link) {
411         int r;
412
413         assert(link);
414         assert(link->network);
415         assert(link->network->dhcp);
416         assert(link->manager);
417         assert(link->manager->event);
418
419         if (!link->dhcp) {
420                 link->dhcp = sd_dhcp_client_new(link->manager->event);
421                 if (!link->dhcp)
422                         return -ENOMEM;
423
424                 r = sd_dhcp_client_set_index(link->dhcp, link->ifindex);
425                 if (r < 0)
426                         return r;
427
428                 r = sd_dhcp_client_set_mac(link->dhcp, &link->mac);
429                 if (r < 0)
430                         return r;
431
432                 r = sd_dhcp_client_set_callback(link->dhcp, dhcp_handler, link);
433                 if (r < 0)
434                         return r;
435         }
436
437         r = sd_dhcp_client_start(link->dhcp);
438         if (r < 0)
439                 return r;
440
441         return 0;
442 }
443
444 static int link_update_flags(Link *link, unsigned flags) {
445         int r;
446
447         assert(link);
448         assert(link->network);
449
450         if (link->state == LINK_STATE_FAILED)
451                 return 0;
452
453         if (link->flags & IFF_UP && !(flags & IFF_UP))
454                 log_info("%s: interface is down", link->ifname);
455         else if (!(link->flags & IFF_UP) && flags & IFF_UP)
456                 log_info("%s: interface is up", link->ifname);
457
458         if (link->flags & IFF_LOWER_UP && !(flags & IFF_LOWER_UP)) {
459                 log_info("%s: disconnected", link->ifname);
460
461                 if (link->network->dhcp) {
462                         r = sd_dhcp_client_stop(link->dhcp);
463                         if (r < 0) {
464                                 link_enter_failed(link);
465                                 return r;
466                         }
467                 }
468         } else if (!(link->flags & IFF_LOWER_UP) && flags & IFF_LOWER_UP) {
469                 log_info("%s: connected", link->ifname);
470
471                 if (link->network->dhcp) {
472                         r = link_acquire_conf(link);
473                         if (r < 0) {
474                                 link_enter_failed(link);
475                                 return r;
476                         }
477                 }
478         }
479
480         link->flags = flags;
481
482         return 0;
483 }
484
485 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
486         Link *link = userdata;
487         int r;
488
489         assert(link);
490
491         if (link->state == LINK_STATE_FAILED)
492                 return 1;
493
494         r = sd_rtnl_message_get_errno(m);
495         if (r < 0) {
496                 log_warning("%s: could not bring up interface: %s",
497                             link->ifname, strerror(-r));
498                 link_enter_failed(link);
499         }
500
501         link_update_flags(link, link->flags | IFF_UP);
502
503         return 1;
504 }
505
506 static int link_up(Link *link) {
507         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
508         int r;
509
510         assert(link);
511         assert(link->manager);
512         assert(link->manager->rtnl);
513
514         log_debug("%s: bringing up link", link->ifname);
515
516         r = sd_rtnl_message_link_new(RTM_SETLINK, link->ifindex, &req);
517         if (r < 0) {
518                 log_error("Could not allocate RTM_SETLINK message");
519                 return r;
520         }
521
522         r = sd_rtnl_message_link_set_flags(req, IFF_UP);
523         if (r < 0) {
524                 log_error("Could not set link flags");
525                 return r;
526         }
527
528         r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
529         if (r < 0) {
530                 log_error("Could not send rtnetlink message: %s", strerror(-r));
531                 return r;
532         }
533
534         return 0;
535 }
536
537 static int link_bridge_joined(Link *link) {
538         int r;
539
540         assert(link);
541         assert(link->state == LINK_STATE_JOINING_BRIDGE);
542         assert(link->network);
543
544         r = link_up(link);
545         if (r < 0) {
546                 link_enter_failed(link);
547                 return r;
548         }
549
550         if (!link->network->dhcp)
551                 return link_enter_set_addresses(link);
552
553         return 0;
554 }
555
556 static int bridge_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
557         Link *link = userdata;
558         int r;
559
560         assert(link);
561         assert(link->state == LINK_STATE_JOINING_BRIDGE || link->state == LINK_STATE_FAILED);
562         assert(link->network);
563
564         if (link->state == LINK_STATE_FAILED)
565                 return 1;
566
567         r = sd_rtnl_message_get_errno(m);
568         if (r < 0) {
569                 log_warning("%s: could not join bridge '%s': %s",
570                             link->ifname, link->network->bridge->name, strerror(-r));
571                 link_enter_failed(link);
572                 return 1;
573         } else
574                 log_debug("%s: joined bridge '%s'",
575                             link->ifname, link->network->bridge->name);
576
577         link_bridge_joined(link);
578
579         return 1;
580 }
581
582 static int link_enter_join_bridge(Link *link) {
583         int r;
584
585         assert(link);
586         assert(link->network);
587         assert(link->state == _LINK_STATE_INVALID);
588
589         link->state = LINK_STATE_JOINING_BRIDGE;
590
591         if (!link->network->bridge)
592                 return link_bridge_joined(link);
593
594         log_debug("%s: joining bridge", link->ifname);
595
596         r = bridge_join(link->network->bridge, link, &bridge_handler);
597         if (r < 0) {
598                 log_warning("%s: could not join bridge '%s'", link->ifname,
599                             link->network->bridge->name);
600                 link_enter_failed(link);
601                 return r;
602         }
603
604         return 0;
605 }
606
607 static int link_get_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
608         Link *link = userdata;
609         int r;
610
611         assert(link);
612
613         if (link->state == LINK_STATE_FAILED)
614                 return 1;
615
616         r = sd_rtnl_message_get_errno(m);
617         if (r < 0) {
618                 log_warning("%s: could not get state: %s",
619                             link->ifname, strerror(-r));
620                 link_enter_failed(link);
621         }
622
623         log_debug("%s: got link state", link->ifname);
624
625         link_update(link, m);
626
627         return 1;
628 }
629
630 static int link_get(Link *link) {
631         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
632         int r;
633
634         assert(link);
635         assert(link->manager);
636         assert(link->manager->rtnl);
637
638         log_debug("%s: requesting link status", link->ifname);
639
640         r = sd_rtnl_message_link_new(RTM_GETLINK, link->ifindex, &req);
641         if (r < 0) {
642                 log_error("Could not allocate RTM_GETLINK message");
643                 return r;
644         }
645
646         r = sd_rtnl_call_async(link->manager->rtnl, req, link_get_handler, link, 0, NULL);
647         if (r < 0) {
648                 log_error("Could not send rtnetlink message: %s", strerror(-r));
649                 return r;
650         }
651
652         return 0;
653 }
654
655 int link_configure(Link *link) {
656         int r;
657
658         assert(link);
659         assert(link->network);
660         assert(link->state == _LINK_STATE_INVALID);
661
662         r = link_get(link);
663         if (r < 0) {
664                 link_enter_failed(link);
665                 return r;
666         }
667
668         return link_enter_join_bridge(link);
669 }
670
671 int link_update(Link *link, sd_rtnl_message *m) {
672         unsigned flags;
673         int r;
674
675         assert(link);
676         assert(m);
677
678         if (link->state == LINK_STATE_FAILED)
679                 return 0;
680
681         r = sd_rtnl_message_link_get_flags(m, &flags);
682         if (r < 0) {
683                 log_warning("%s: could not get link flags", link->ifname);
684                 return r;
685         }
686
687         return link_update_flags(link, flags);
688 }