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