chiark / gitweb /
1f495b38bbc579f4951bc039123f15d40af1bbc0
[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 #include "bus-util.h"
29 #include "net-util.h"
30
31 int link_new(Manager *manager, struct udev_device *device, Link **ret) {
32         _cleanup_link_free_ Link *link = NULL;
33         const char *mac;
34         struct ether_addr *mac_addr;
35         const char *ifname;
36         int r;
37
38         assert(manager);
39         assert(manager->links);
40         assert(device);
41         assert(ret);
42
43         link = new0(Link, 1);
44         if (!link)
45                 return -ENOMEM;
46
47         link->manager = manager;
48         link->state = _LINK_STATE_INVALID;
49
50         link->ifindex = udev_device_get_ifindex(device);
51         if (link->ifindex <= 0)
52                 return -EINVAL;
53
54         mac = udev_device_get_sysattr_value(device, "address");
55         if (mac) {
56                 mac_addr = ether_aton(mac);
57                 if (mac_addr)
58                         memcpy(&link->mac, mac_addr, sizeof(struct ether_addr));
59         }
60
61         ifname = udev_device_get_sysname(device);
62         link->ifname = strdup(ifname);
63
64         r = hashmap_put(manager->links, &link->ifindex, link);
65         if (r < 0)
66                 return r;
67
68         *ret = link;
69         link = NULL;
70
71         return 0;
72 }
73
74 void link_free(Link *link) {
75         if (!link)
76                 return;
77
78         assert(link->manager);
79
80         sd_dhcp_client_free(link->dhcp_client);
81         sd_dhcp_lease_unref(link->dhcp_lease);
82
83         hashmap_remove(link->manager->links, &link->ifindex);
84
85         free(link->ifname);
86
87         free(link);
88 }
89
90 int link_get(Manager *m, int ifindex, Link **ret) {
91         Link *link;
92         uint64_t ifindex_64;
93
94         assert(m);
95         assert(m->links);
96         assert(ifindex);
97         assert(ret);
98
99         ifindex_64 = ifindex;
100         link = hashmap_get(m->links, &ifindex_64);
101         if (!link)
102                 return -ENODEV;
103
104         *ret = link;
105
106         return 0;
107 }
108
109 int link_add(Manager *m, struct udev_device *device, Link **ret) {
110         Link *link = NULL;
111         Network *network;
112         int r;
113
114         assert(m);
115         assert(device);
116
117         r = link_new(m, device, &link);
118         if (r < 0)
119                 return r;
120
121         *ret = link;
122
123         r = network_get(m, device, &network);
124         if (r < 0)
125                 return r == -ENOENT ? 0 : r;
126
127         r = network_apply(m, network, link);
128         if (r < 0)
129                 return r;
130
131         return 0;
132 }
133
134 static int link_enter_configured(Link *link) {
135         assert(link);
136         assert(link->state == LINK_STATE_SETTING_ROUTES);
137
138         log_info_link(link, "link configured");
139
140         link->state = LINK_STATE_CONFIGURED;
141
142         return 0;
143 }
144
145 static void link_enter_failed(Link *link) {
146         assert(link);
147
148         log_warning_link(link, "failed");
149
150         link->state = LINK_STATE_FAILED;
151 }
152
153 static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
154         Link *link = userdata;
155         int r;
156
157         assert(link->route_messages > 0);
158         assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
159                link->state == LINK_STATE_SETTING_ROUTES ||
160                link->state == LINK_STATE_FAILED);
161
162         link->route_messages --;
163
164         if (link->state == LINK_STATE_FAILED)
165                 return 1;
166
167         r = sd_rtnl_message_get_errno(m);
168         if (r < 0 && r != -EEXIST)
169                 log_struct_link(LOG_WARNING, link,
170                                 "MESSAGE=%s: could not set route: %s",
171                                 link->ifname, strerror(-r),
172                                 "ERRNO=%d", -r,
173                                 NULL);
174
175         /* we might have received an old reply after moving back to SETTING_ADDRESSES,
176          * ignore it */
177         if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
178                 log_debug_link(link, "routes set");
179                 link_enter_configured(link);
180         }
181
182         return 1;
183 }
184
185 static int link_enter_set_routes(Link *link) {
186         Route *rt;
187         int r;
188
189         assert(link);
190         assert(link->network);
191         assert(link->state == LINK_STATE_SETTING_ADDRESSES);
192
193         link->state = LINK_STATE_SETTING_ROUTES;
194
195         if (!link->network->static_routes && !link->dhcp_lease)
196                 return link_enter_configured(link);
197
198         log_debug_link(link, "setting routes");
199
200         LIST_FOREACH(static_routes, rt, link->network->static_routes) {
201                 r = route_configure(rt, link, &route_handler);
202                 if (r < 0) {
203                         log_warning_link(link,
204                                          "could not set routes: %s", strerror(-r));
205                         link_enter_failed(link);
206                         return r;
207                 }
208
209                 link->route_messages ++;
210         }
211
212         if (link->dhcp_lease) {
213                 _cleanup_route_free_ Route *route = NULL;
214                 struct in_addr gateway;
215
216                 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
217                 if (r < 0) {
218                         log_warning_link(link, "DHCP error: no router: %s",
219                                          strerror(-r));
220                         return r;
221                 }
222
223                 r = route_new_dynamic(&route);
224                 if (r < 0) {
225                         log_error_link(link, "Could not allocate route: %s",
226                                        strerror(-r));
227                         return r;
228                 }
229
230                 route->family = AF_INET;
231                 route->in_addr.in = gateway;
232
233                 r = route_configure(route, link, &route_handler);
234                 if (r < 0) {
235                         log_warning_link(link,
236                                          "could not set routes: %s", strerror(-r));
237                         link_enter_failed(link);
238                         return r;
239                 }
240
241                 link->route_messages ++;
242         }
243
244         return 0;
245 }
246
247 static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
248         Link *link = userdata;
249         int r;
250
251         assert(m);
252         assert(link);
253         assert(link->ifname);
254         assert(link->addr_messages > 0);
255         assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
256
257         link->addr_messages --;
258
259         if (link->state == LINK_STATE_FAILED)
260                 return 1;
261
262         r = sd_rtnl_message_get_errno(m);
263         if (r < 0 && r != -EEXIST)
264                 log_struct_link(LOG_WARNING, link,
265                                 "MESSAGE=%s: could not set address: %s",
266                                 link->ifname, strerror(-r),
267                                 "ERRNO=%d", -r,
268                                 NULL);
269
270         if (link->addr_messages == 0) {
271                 log_debug_link(link, "addresses set");
272                 link_enter_set_routes(link);
273         }
274
275         return 1;
276 }
277
278 static int link_enter_set_addresses(Link *link) {
279         Address *ad;
280         int r;
281
282         assert(link);
283         assert(link->network);
284         assert(link->state != _LINK_STATE_INVALID);
285
286         link->state = LINK_STATE_SETTING_ADDRESSES;
287
288         if (!link->network->static_addresses && !link->dhcp_lease)
289                 return link_enter_set_routes(link);
290
291         log_debug_link(link, "setting addresses");
292
293         LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
294                 r = address_configure(ad, link, &address_handler);
295                 if (r < 0) {
296                         log_warning_link(link,
297                                          "could not set addresses: %s", strerror(-r));
298                         link_enter_failed(link);
299                         return r;
300                 }
301
302                 link->addr_messages ++;
303         }
304
305         if (link->dhcp_lease) {
306                 _cleanup_address_free_ Address *address = NULL;
307                 struct in_addr addr;
308                 struct in_addr netmask;
309                 unsigned prefixlen;
310
311                 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
312                 if (r < 0) {
313                         log_warning_link(link, "DHCP error: no address: %s",
314                                          strerror(-r));
315                         return r;
316                 }
317
318                 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
319                 if (r < 0) {
320                         log_warning_link(link, "DHCP error: no netmask: %s",
321                                          strerror(-r));
322                         return r;
323                 }
324
325                 prefixlen = net_netmask_to_prefixlen(&netmask);
326
327                 r = address_new_dynamic(&address);
328                 if (r < 0) {
329                         log_error_link(link, "Could not allocate address: %s",
330                                        strerror(-r));
331                         return r;
332                 }
333
334                 address->family = AF_INET;
335                 address->in_addr.in = addr;
336                 address->prefixlen = prefixlen;
337                 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
338
339                 r = address_configure(address, link, &address_handler);
340                 if (r < 0) {
341                         log_warning_link(link,
342                                          "could not set addresses: %s", strerror(-r));
343                         link_enter_failed(link);
344                         return r;
345                 }
346
347                 link->addr_messages ++;
348         }
349
350         return 0;
351 }
352
353 static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
354         Link *link = userdata;
355         int r;
356
357         assert(m);
358         assert(link);
359         assert(link->ifname);
360
361         if (link->state == LINK_STATE_FAILED)
362                 return 1;
363
364         r = sd_rtnl_message_get_errno(m);
365         if (r < 0 && r != -ENOENT)
366                 log_struct_link(LOG_WARNING, link,
367                                 "MESSAGE=%s: could not drop address: %s",
368                                 link->ifname, strerror(-r),
369                                 "ERRNO=%d", -r,
370                                 NULL);
371
372         return 1;
373 }
374
375 static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
376         int r;
377
378         r = sd_bus_message_get_errno(m);
379         if (r < 0)
380                 log_warning("Could not set hostname: %s", strerror(-r));
381
382         return 1;
383 }
384
385 static int set_hostname(sd_bus *bus, const char *hostname) {
386         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
387         int r = 0;
388
389         assert(hostname);
390
391         log_debug("Setting transient hostname: '%s'", hostname);
392
393         if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
394                 log_info("Not connected to system bus, ignoring transient hostname.");
395                 return 0;
396         }
397
398         r = sd_bus_message_new_method_call(
399                         bus,
400                         &m,
401                         "org.freedesktop.hostname1",
402                         "/org/freedesktop/hostname1",
403                         "org.freedesktop.hostname1",
404                         "SetHostname");
405         if (r < 0)
406                 return r;
407
408         r = sd_bus_message_append(m, "sb", hostname, false);
409         if (r < 0)
410                 return r;
411
412         r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
413         if (r < 0)
414                 log_error("Could not set transient hostname: %s", strerror(-r));
415
416         return r;
417 }
418
419 static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
420         Link *link = userdata;
421         int r;
422
423         assert(m);
424         assert(link);
425         assert(link->ifname);
426
427         if (link->state == LINK_STATE_FAILED)
428                 return 1;
429
430         r = sd_rtnl_message_get_errno(m);
431         if (r < 0)
432                 log_struct_link(LOG_WARNING, link,
433                                 "MESSAGE=%s: could not set MTU: %s",
434                                 link->ifname, strerror(-r),
435                                 "ERRNO=%d", -r,
436                                 NULL);
437
438         return 1;
439 }
440
441 static int link_set_mtu(Link *link, uint32_t mtu) {
442         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
443         int r;
444
445         assert(link);
446         assert(link->manager);
447         assert(link->manager->rtnl);
448
449         log_debug_link(link, "setting MTU: %" PRIu32, mtu);
450
451         r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
452                                      RTM_SETLINK, link->ifindex);
453         if (r < 0) {
454                 log_error_link(link, "Could not allocate RTM_SETLINK message");
455                 return r;
456         }
457
458         r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
459         if (r < 0) {
460                 log_error_link(link, "Could not append MTU: %s", strerror(-r));
461                 return r;
462         }
463
464         r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
465         if (r < 0) {
466                 log_error_link(link,
467                                "Could not send rtnetlink message: %s", strerror(-r));
468                 return r;
469         }
470
471         return 0;
472 }
473
474 static int dhcp_lease_lost(Link *link) {
475         _cleanup_address_free_ Address *address = NULL;
476         struct in_addr addr;
477         struct in_addr netmask;
478         unsigned prefixlen;
479         int r;
480
481         assert(link);
482         assert(link->dhcp_lease);
483
484         log_warning_link(link, "DHCP lease lost");
485
486         r = address_new_dynamic(&address);
487         if (r >= 0) {
488                 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
489                 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
490                 prefixlen = net_netmask_to_prefixlen(&netmask);
491
492                 address->family = AF_INET;
493                 address->in_addr.in = addr;
494                 address->prefixlen = prefixlen;
495
496                 address_drop(address, link, address_drop_handler);
497         }
498
499         if (link->network->dhcp_mtu) {
500                 uint16_t mtu;
501
502                 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
503                 if (r >= 0 && link->original_mtu != mtu) {
504                         r = link_set_mtu(link, link->original_mtu);
505                         if (r < 0) {
506                                 log_warning_link(link, "DHCP error: could not reset MTU");
507                                 link_enter_failed(link);
508                                 return r;
509                         }
510                 }
511         }
512
513         if (link->network->dhcp_hostname) {
514                 const char *hostname = NULL;
515
516                 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
517                 if (r >= 0 && hostname) {
518                         r = set_hostname(link->manager->bus, "");
519                         if (r < 0)
520                                 log_error("Failed to reset transient hostname");
521                 }
522         }
523
524         link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
525
526         return 0;
527 }
528
529 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
530         sd_dhcp_lease *lease;
531         struct in_addr address;
532         struct in_addr netmask;
533         struct in_addr gateway;
534         unsigned prefixlen;
535         struct in_addr *nameservers;
536         size_t nameservers_size;
537         int r;
538
539         assert(client);
540         assert(link);
541
542         r = sd_dhcp_client_get_lease(client, &lease);
543         if (r < 0) {
544                 log_warning_link(link, "DHCP error: no lease: %s",
545                                  strerror(-r));
546                 return r;
547         }
548
549         r = sd_dhcp_lease_get_address(lease, &address);
550         if (r < 0) {
551                 log_warning_link(link, "DHCP error: no address: %s",
552                                  strerror(-r));
553                 return r;
554         }
555
556         r = sd_dhcp_lease_get_netmask(lease, &netmask);
557         if (r < 0) {
558                 log_warning_link(link, "DHCP error: no netmask: %s",
559                                  strerror(-r));
560                 return r;
561         }
562
563         prefixlen = net_netmask_to_prefixlen(&netmask);
564
565         r = sd_dhcp_lease_get_router(lease, &gateway);
566         if (r < 0) {
567                 log_warning_link(link, "DHCP error: no router: %s",
568                                  strerror(-r));
569                 return r;
570         }
571
572         log_struct_link(LOG_INFO, link,
573                         "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
574                          link->ifname,
575                          ADDRESS_FMT_VAL(address),
576                          prefixlen,
577                          ADDRESS_FMT_VAL(gateway),
578                          "ADDRESS=%u.%u.%u.%u",
579                          ADDRESS_FMT_VAL(address),
580                          "PREFIXLEN=%u",
581                          prefixlen,
582                          "GATEWAY=%u.%u.%u.%u",
583                          ADDRESS_FMT_VAL(gateway),
584                          NULL);
585
586         link->dhcp_lease = lease;
587
588         if (link->network->dhcp_dns) {
589                 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
590                 if (r >= 0) {
591                         r = manager_update_resolv_conf(link->manager);
592                         if (r < 0)
593                                 log_error("Failed to update resolv.conf");
594                 }
595         }
596
597         if (link->network->dhcp_mtu) {
598                 uint16_t mtu;
599
600                 r = sd_dhcp_lease_get_mtu(lease, &mtu);
601                 if (r >= 0) {
602                         r = link_set_mtu(link, mtu);
603                         if (r < 0)
604                                 log_error_link(link, "Failed to set MTU "
605                                                "to %" PRIu16, mtu);
606                 }
607         }
608
609         if (link->network->dhcp_hostname) {
610                 const char *hostname;
611
612                 r = sd_dhcp_lease_get_hostname(lease, &hostname);
613                 if (r >= 0) {
614                         r = set_hostname(link->manager->bus, hostname);
615                         if (r < 0)
616                                 log_error("Failed to set transient hostname "
617                                           "to '%s'", hostname);
618                 }
619         }
620
621         link_enter_set_addresses(link);
622
623         return 0;
624 }
625
626 static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
627         Link *link = userdata;
628         int r;
629
630         assert(link);
631         assert(link->network);
632         assert(link->manager);
633
634         if (link->state == LINK_STATE_FAILED)
635                 return;
636
637         switch (event) {
638                 case DHCP_EVENT_NO_LEASE:
639                         log_debug_link(link, "IP address in use.");
640                         break;
641                 case DHCP_EVENT_EXPIRED:
642                 case DHCP_EVENT_STOP:
643                 case DHCP_EVENT_IP_CHANGE:
644                         if (link->network->dhcp_critical) {
645                                 log_error_link(link, "DHCPv4 connection considered system critical, "
646                                                "ignoring request to reconfigure it.");
647                                 return;
648                         }
649
650                         if (link->dhcp_lease) {
651                                 r = dhcp_lease_lost(link);
652                                 if (r < 0) {
653                                         link_enter_failed(link);
654                                         return;
655                                 }
656                         }
657
658                         if (event == DHCP_EVENT_IP_CHANGE) {
659                                 r = dhcp_lease_acquired(client, link);
660                                 if (r < 0) {
661                                         link_enter_failed(link);
662                                         return;
663                                 }
664                         }
665
666                         break;
667                 case DHCP_EVENT_IP_ACQUIRE:
668                         r = dhcp_lease_acquired(client, link);
669                         if (r < 0) {
670                                 link_enter_failed(link);
671                                 return;
672                         }
673                         break;
674                 default:
675                         if (event < 0)
676                                 log_warning_link(link, "DHCP error: %s", strerror(-event));
677                         else
678                                 log_warning_link(link, "DHCP unknown event: %d", event);
679                         break;
680         }
681
682         return;
683 }
684
685 static int link_acquire_conf(Link *link) {
686         int r;
687
688         assert(link);
689         assert(link->network);
690         assert(link->network->dhcp);
691         assert(link->manager);
692         assert(link->manager->event);
693
694         if (!link->dhcp_client) {
695                 r = sd_dhcp_client_new(&link->dhcp_client);
696                 if (r < 0)
697                         return r;
698
699                 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
700                 if (r < 0)
701                         return r;
702
703                 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
704                 if (r < 0)
705                         return r;
706
707                 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
708                 if (r < 0)
709                         return r;
710
711                 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
712                 if (r < 0)
713                         return r;
714
715                 if (link->network->dhcp_mtu) {
716                         r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
717                         if (r < 0)
718                                 return r;
719                 }
720         }
721
722         log_debug_link(link, "acquiring DHCPv4 lease");
723
724         r = sd_dhcp_client_start(link->dhcp_client);
725         if (r < 0)
726                 return r;
727
728         return 0;
729 }
730
731 static int link_update_flags(Link *link, unsigned flags) {
732         int r;
733
734         assert(link);
735         assert(link->network);
736
737         if (link->state == LINK_STATE_FAILED)
738                 return 0;
739
740         if (link->flags == flags) {
741                 log_debug_link(link, "link status unchanged: %#.8x", flags);
742                 return 0;
743         }
744
745         if ((link->flags & IFF_UP) != (flags & IFF_UP))
746                 log_info_link(link,
747                               "link is %s", flags & IFF_UP ? "up": "down");
748
749         if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
750                 if (flags & IFF_LOWER_UP) {
751                         log_info_link(link, "carrier on");
752
753                         if (link->network->dhcp) {
754                                 r = link_acquire_conf(link);
755                                 if (r < 0) {
756                                         log_warning_link(link, "Could not acquire DHCPv4 lease: %s", strerror(-r));
757                                         link_enter_failed(link);
758                                         return r;
759                                 }
760                         }
761                 } else {
762                         log_info_link(link, "carrier off");
763
764                         if (link->network->dhcp) {
765                                 r = sd_dhcp_client_stop(link->dhcp_client);
766                                 if (r < 0) {
767                                         log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
768                                         link_enter_failed(link);
769                                         return r;
770                                 }
771                         }
772                 }
773         }
774
775         log_debug_link(link,
776                        "link status updated: %#.8x -> %#.8x", link->flags, flags);
777
778         link->flags = flags;
779
780         return 0;
781 }
782
783 static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
784         Link *link = userdata;
785         int r;
786
787         assert(link);
788
789         if (link->state == LINK_STATE_FAILED)
790                 return 1;
791
792         r = sd_rtnl_message_get_errno(m);
793         if (r < 0) {
794                 log_struct_link(LOG_ERR, link,
795                                 "MESSAGE=%s: could not bring up interface: %s",
796                                 link->ifname, strerror(-r),
797                                 "ERRNO=%d", -r,
798                                 NULL);
799                 link_enter_failed(link);
800                 return 1;
801         }
802
803         link_update_flags(link, link->flags | IFF_UP);
804
805         return 1;
806 }
807
808 static int link_up(Link *link) {
809         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
810         int r;
811
812         assert(link);
813         assert(link->manager);
814         assert(link->manager->rtnl);
815
816         log_debug_link(link, "bringing link up");
817
818         r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
819                                      RTM_SETLINK, link->ifindex);
820         if (r < 0) {
821                 log_error_link(link, "Could not allocate RTM_SETLINK message");
822                 return r;
823         }
824
825         r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
826         if (r < 0) {
827                 log_error_link(link, "Could not set link flags: %s", strerror(-r));
828                 return r;
829         }
830
831         r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
832         if (r < 0) {
833                 log_error_link(link,
834                                "Could not send rtnetlink message: %s", strerror(-r));
835                 return r;
836         }
837
838         return 0;
839 }
840
841 static int link_enslaved(Link *link) {
842         int r;
843
844         assert(link);
845         assert(link->state == LINK_STATE_ENSLAVING);
846         assert(link->network);
847
848         r = link_up(link);
849         if (r < 0) {
850                 link_enter_failed(link);
851                 return r;
852         }
853
854         if (!link->network->dhcp)
855                 return link_enter_set_addresses(link);
856
857         return 0;
858 }
859
860 static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
861         Link *link = userdata;
862         int r;
863
864         assert(link);
865         assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
866         assert(link->network);
867
868         link->enslaving --;
869
870         if (link->state == LINK_STATE_FAILED)
871                 return 1;
872
873         r = sd_rtnl_message_get_errno(m);
874         if (r < 0) {
875                 log_struct_link(LOG_ERR, link,
876                                 "MESSAGE=%s: could not enslave: %s",
877                                 link->ifname, strerror(-r),
878                                 "ERRNO=%d", -r,
879                                 NULL);
880                 link_enter_failed(link);
881                 return 1;
882         }
883
884         log_debug_link(link, "enslaved");
885
886         if (link->enslaving == 0)
887                 link_enslaved(link);
888
889         return 1;
890 }
891
892 static int link_enter_enslave(Link *link) {
893         NetDev *vlan;
894         Iterator i;
895         int r;
896
897         assert(link);
898         assert(link->network);
899         assert(link->state == _LINK_STATE_INVALID);
900
901         link->state = LINK_STATE_ENSLAVING;
902
903         if (!link->network->bridge && !link->network->bond &&
904             hashmap_isempty(link->network->vlans))
905                 return link_enslaved(link);
906
907         if (link->network->bridge) {
908                 log_struct_link(LOG_DEBUG, link,
909                                 "MESSAGE=%s: enslaving by '%s'",
910                                 link->ifname, link->network->bridge->name,
911                                 NETDEV(link->network->bridge),
912                                 NULL);
913
914                 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
915                 if (r < 0) {
916                         log_struct_link(LOG_WARNING, link,
917                                         "MESSAGE=%s: could not enslave by '%s': %s",
918                                         link->ifname, link->network->bridge->name, strerror(-r),
919                                         NETDEV(link->network->bridge),
920                                         NULL);
921                         link_enter_failed(link);
922                         return r;
923                 }
924
925                 link->enslaving ++;
926         }
927
928         HASHMAP_FOREACH(vlan, link->network->vlans, i) {
929                 log_struct_link(LOG_DEBUG, link,
930                                 "MESSAGE=%s: enslaving by '%s'",
931                                 link->ifname, vlan->name, NETDEV(vlan), NULL);
932
933                 r = netdev_enslave(vlan, link, &enslave_handler);
934                 if (r < 0) {
935                         log_struct_link(LOG_WARNING, link,
936                                         "MESSAGE=%s: could not enslave by '%s': %s",
937                                         link->ifname, vlan->name, strerror(-r),
938                                         NETDEV(vlan), NULL);
939                         link_enter_failed(link);
940                         return r;
941                 }
942
943                 link->enslaving ++;
944         }
945
946         return 0;
947 }
948
949 static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
950                                 void *userdata) {
951         Link *link = userdata;
952         int r;
953
954         assert(link);
955
956         if (link->state == LINK_STATE_FAILED)
957                 return 1;
958
959         r = sd_rtnl_message_get_errno(m);
960         if (r < 0) {
961                 log_struct_link(LOG_ERR, link,
962                                 "MESSAGE=%s: could not get state: %s",
963                                 link->ifname, strerror(-r),
964                                 "ERRNO=%d", -r,
965                                 NULL);
966                 link_enter_failed(link);
967                 return 1;
968         }
969
970         log_debug_link(link, "got link state");
971
972         link_update(link, m);
973
974         return 1;
975 }
976
977 static int link_getlink(Link *link) {
978         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
979         int r;
980
981         assert(link);
982         assert(link->manager);
983         assert(link->manager->rtnl);
984
985         log_debug_link(link, "requesting link status");
986
987         r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
988                                      RTM_GETLINK, link->ifindex);
989         if (r < 0) {
990                 log_error_link(link, "Could not allocate RTM_GETLINK message");
991                 return r;
992         }
993
994         r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
995                                link, 0, NULL);
996         if (r < 0) {
997                 log_error_link(link,
998                                "Could not send rtnetlink message: %s", strerror(-r));
999                 return r;
1000         }
1001
1002         return 0;
1003 }
1004
1005 int link_configure(Link *link) {
1006         int r;
1007
1008         assert(link);
1009         assert(link->network);
1010         assert(link->state == _LINK_STATE_INVALID);
1011
1012         r = link_getlink(link);
1013         if (r < 0) {
1014                 link_enter_failed(link);
1015                 return r;
1016         }
1017
1018         return link_enter_enslave(link);
1019 }
1020
1021 int link_update(Link *link, sd_rtnl_message *m) {
1022         unsigned flags;
1023         void *data;
1024         uint16_t type;
1025         int r;
1026
1027         assert(link);
1028         assert(m);
1029
1030         if (link->state == LINK_STATE_FAILED)
1031                 return 0;
1032
1033         r = sd_rtnl_message_link_get_flags(m, &flags);
1034         if (r < 0) {
1035                 log_warning_link(link, "Could not get link flags");
1036                 return r;
1037         }
1038
1039         while (sd_rtnl_message_read(m, &type, &data) > 0) {
1040                 if (type == IFLA_MTU && link->network->dhcp &&
1041                     link->network->dhcp_mtu && !link->original_mtu) {
1042                         link->original_mtu = *(uint16_t *) data;
1043                         log_debug_link(link, "saved original MTU: %" PRIu16,
1044                                        link->original_mtu);
1045                 }
1046         }
1047
1048         return link_update_flags(link, flags);
1049 }