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