]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
sd-dhcp-client: Add an explicit stop state for the DHCP client
[thirdparty/systemd.git] / src / network / networkd-link.c
CommitLineData
f579559b
TG
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"
1346b1f0 28#include "bus-util.h"
c6f7c917 29#include "network-internal.h"
f579559b 30
fe8db0c5
TG
31#include "dhcp-lease-internal.h"
32
aba496a5
UTL
33static int ipv4ll_address_update(Link *link, bool deprecate);
34static bool ipv4ll_is_bound(sd_ipv4ll *ll);
35
f579559b
TG
36int link_new(Manager *manager, struct udev_device *device, Link **ret) {
37 _cleanup_link_free_ Link *link = NULL;
c166a070 38 const char *ifname;
f579559b
TG
39 int r;
40
0c2f9b84
TG
41 assert(manager);
42 assert(manager->links);
f579559b
TG
43 assert(device);
44 assert(ret);
45
46 link = new0(Link, 1);
47 if (!link)
48 return -ENOMEM;
49
5a3eb5a7
TG
50 link->manager = manager;
51 link->state = _LINK_STATE_INVALID;
52
0617ffab
TG
53 link->ifindex = udev_device_get_ifindex(device);
54 if (link->ifindex <= 0)
f579559b
TG
55 return -EINVAL;
56
315db1a8
ZJS
57 r = asprintf(&link->state_file, "/run/systemd/network/links/%"PRIu64,
58 link->ifindex);
fe8db0c5 59 if (r < 0)
315db1a8 60 return -ENOMEM;
fe8db0c5 61
c166a070
TG
62 ifname = udev_device_get_sysname(device);
63 link->ifname = strdup(ifname);
64
0617ffab 65 r = hashmap_put(manager->links, &link->ifindex, link);
f579559b
TG
66 if (r < 0)
67 return r;
68
b5db00e5
UTL
69 link->udev_device = udev_device_ref(device);
70
f579559b
TG
71 *ret = link;
72 link = NULL;
73
74 return 0;
75}
76
77void link_free(Link *link) {
78 if (!link)
79 return;
80
0617ffab 81 assert(link->manager);
f579559b 82
e5b04c8d 83 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 84 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 85
5c1d3fc9
UTL
86 sd_ipv4ll_free(link->ipv4ll);
87
0617ffab 88 hashmap_remove(link->manager->links, &link->ifindex);
f579559b 89
c166a070 90 free(link->ifname);
fe8db0c5 91 free(link->state_file);
c166a070 92
b5db00e5
UTL
93 udev_device_unref(link->udev_device);
94
f579559b
TG
95 free(link);
96}
97
11a7f229
TG
98int 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
f882c247 117static int link_enter_configured(Link *link) {
ef1ba606
TG
118 assert(link);
119 assert(link->state == LINK_STATE_SETTING_ROUTES);
120
39032b87 121 log_info_link(link, "link configured");
f882c247
TG
122
123 link->state = LINK_STATE_CONFIGURED;
124
fe8db0c5
TG
125 link_save(link);
126
f882c247
TG
127 return 0;
128}
129
ef1ba606
TG
130static void link_enter_failed(Link *link) {
131 assert(link);
f882c247 132
39032b87 133 log_warning_link(link, "failed");
449f7554 134
ef1ba606 135 link->state = LINK_STATE_FAILED;
fe8db0c5
TG
136
137 link_save(link);
f882c247
TG
138}
139
f882c247
TG
140static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
141 Link *link = userdata;
142 int r;
143
f5be5601
TG
144 assert(link->route_messages > 0);
145 assert(link->state == LINK_STATE_SETTING_ADDRESSES ||
146 link->state == LINK_STATE_SETTING_ROUTES ||
147 link->state == LINK_STATE_FAILED);
f882c247 148
f5be5601 149 link->route_messages --;
f882c247
TG
150
151 if (link->state == LINK_STATE_FAILED)
152 return 1;
153
154 r = sd_rtnl_message_get_errno(m);
c166a070 155 if (r < 0 && r != -EEXIST)
c9ccc19f
TG
156 log_struct_link(LOG_WARNING, link,
157 "MESSAGE=%s: could not set route: %s",
158 link->ifname, strerror(-r),
159 "ERRNO=%d", -r,
160 NULL);
f882c247 161
f5be5601
TG
162 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
163 * ignore it */
164 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
39032b87 165 log_debug_link(link, "routes set");
dd3efc09
TG
166 link_enter_configured(link);
167 }
f882c247
TG
168
169 return 1;
170}
171
172static int link_enter_set_routes(Link *link) {
a6cc569e 173 Route *rt;
f882c247
TG
174 int r;
175
176 assert(link);
177 assert(link->network);
ef1ba606 178 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 179
ef1ba606 180 link->state = LINK_STATE_SETTING_ROUTES;
f882c247 181
5c1d3fc9 182 if (!link->network->static_routes && !link->dhcp_lease &&
aba496a5 183 (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false))
dd3efc09 184 return link_enter_configured(link);
f882c247 185
39032b87 186 log_debug_link(link, "setting routes");
449f7554 187
a6cc569e
TG
188 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
189 r = route_configure(rt, link, &route_handler);
dd3efc09 190 if (r < 0) {
3333d748
ZJS
191 log_warning_link(link,
192 "could not set routes: %s", strerror(-r));
ef1ba606
TG
193 link_enter_failed(link);
194 return r;
dd3efc09 195 }
c166a070 196
f5be5601
TG
197 link->route_messages ++;
198 }
199
5c1d3fc9
UTL
200 if (link->ipv4ll && !link->dhcp_lease) {
201 _cleanup_route_free_ Route *route = NULL;
202 struct in_addr addr;
203
204 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
205 if (r < 0 && r != -ENOENT) {
206 log_warning_link(link, "IPV4LL error: no address: %s",
207 strerror(-r));
208 return r;
209 }
210
211 if (r != -ENOENT) {
212 r = route_new_dynamic(&route);
213 if (r < 0) {
214 log_error_link(link, "Could not allocate route: %s",
215 strerror(-r));
216 return r;
217 }
218
219 route->family = AF_INET;
220 route->scope = RT_SCOPE_LINK;
221 route->metrics = 99;
222
223 r = route_configure(route, link, &route_handler);
224 if (r < 0) {
225 log_warning_link(link,
226 "could not set routes: %s", strerror(-r));
227 link_enter_failed(link);
228 return r;
229 }
230
231 link->route_messages ++;
232 }
233 }
234
a6cc569e
TG
235 if (link->dhcp_lease) {
236 _cleanup_route_free_ Route *route = NULL;
9765ce69 237 _cleanup_route_free_ Route *route_gw = NULL;
a6cc569e
TG
238 struct in_addr gateway;
239
240 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
241 if (r < 0) {
242 log_warning_link(link, "DHCP error: no router: %s",
243 strerror(-r));
244 return r;
245 }
246
247 r = route_new_dynamic(&route);
248 if (r < 0) {
249 log_error_link(link, "Could not allocate route: %s",
250 strerror(-r));
251 return r;
252 }
253
9765ce69
BP
254 r = route_new_dynamic(&route_gw);
255 if (r < 0) {
256 log_error_link(link, "Could not allocate route: %s",
257 strerror(-r));
258 return r;
259 }
260
261 /* The dhcp netmask may mask out the gateway. Add an explicit
262 * route for the gw host so that we can route no matter the
263 * netmask or existing kernel route tables. */
264 route_gw->family = AF_INET;
265 route_gw->dst_addr.in = gateway;
266 route_gw->dst_prefixlen = 32;
267 route_gw->scope = RT_SCOPE_LINK;
268
269 r = route_configure(route_gw, link, &route_handler);
270 if (r < 0) {
271 log_warning_link(link,
272 "could not set host route: %s", strerror(-r));
273 return r;
274 }
275
276 link->route_messages ++;
277
a6cc569e
TG
278 route->family = AF_INET;
279 route->in_addr.in = gateway;
280
281 r = route_configure(route, link, &route_handler);
f5be5601 282 if (r < 0) {
3333d748
ZJS
283 log_warning_link(link,
284 "could not set routes: %s", strerror(-r));
f5be5601
TG
285 link_enter_failed(link);
286 return r;
287 }
288
289 link->route_messages ++;
f882c247
TG
290 }
291
292 return 0;
293}
294
5c1d3fc9
UTL
295static int route_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 != -ENOENT)
308 log_struct_link(LOG_WARNING, link,
309 "MESSAGE=%s: could not drop route: %s",
310 link->ifname, strerror(-r),
311 "ERRNO=%d", -r,
312 NULL);
313
314 return 0;
315}
316
f882c247
TG
317static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
318 Link *link = userdata;
319 int r;
320
f5be5601
TG
321 assert(m);
322 assert(link);
323 assert(link->ifname);
324 assert(link->addr_messages > 0);
ef1ba606 325 assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED);
f882c247 326
f5be5601 327 link->addr_messages --;
f882c247
TG
328
329 if (link->state == LINK_STATE_FAILED)
330 return 1;
331
332 r = sd_rtnl_message_get_errno(m);
c166a070 333 if (r < 0 && r != -EEXIST)
c9ccc19f 334 log_struct_link(LOG_WARNING, link,
3333d748
ZJS
335 "MESSAGE=%s: could not set address: %s",
336 link->ifname, strerror(-r),
337 "ERRNO=%d", -r,
338 NULL);
f882c247 339
f5be5601 340 if (link->addr_messages == 0) {
39032b87 341 log_debug_link(link, "addresses set");
ef1ba606 342 link_enter_set_routes(link);
dd3efc09 343 }
f882c247
TG
344
345 return 1;
346}
347
348static int link_enter_set_addresses(Link *link) {
a6cc569e 349 Address *ad;
f882c247
TG
350 int r;
351
352 assert(link);
353 assert(link->network);
f5be5601 354 assert(link->state != _LINK_STATE_INVALID);
f882c247 355
ef1ba606 356 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 357
5c1d3fc9 358 if (!link->network->static_addresses && !link->dhcp_lease &&
aba496a5 359 (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false))
ef1ba606 360 return link_enter_set_routes(link);
f882c247 361
39032b87 362 log_debug_link(link, "setting addresses");
449f7554 363
a6cc569e
TG
364 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
365 r = address_configure(ad, link, &address_handler);
dd3efc09 366 if (r < 0) {
3333d748
ZJS
367 log_warning_link(link,
368 "could not set addresses: %s", strerror(-r));
ef1ba606
TG
369 link_enter_failed(link);
370 return r;
dd3efc09 371 }
c166a070 372
f5be5601
TG
373 link->addr_messages ++;
374 }
375
5c1d3fc9
UTL
376 if (link->ipv4ll && !link->dhcp_lease) {
377 _cleanup_address_free_ Address *ll_addr = NULL;
378 struct in_addr addr;
379
380 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
381 if (r < 0 && r != -ENOENT) {
382 log_warning_link(link, "IPV4LL error: no address: %s",
383 strerror(-r));
384 return r;
385 }
386
387 if (r != -ENOENT) {
388 r = address_new_dynamic(&ll_addr);
389 if (r < 0) {
390 log_error_link(link, "Could not allocate address: %s", strerror(-r));
391 return r;
392 }
393
394 ll_addr->family = AF_INET;
395 ll_addr->in_addr.in = addr;
396 ll_addr->prefixlen = 16;
397 ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
398 ll_addr->scope = RT_SCOPE_LINK;
399
400 r = address_configure(ll_addr, link, &address_handler);
401 if (r < 0) {
402 log_warning_link(link,
403 "could not set addresses: %s", strerror(-r));
404 link_enter_failed(link);
405 return r;
406 }
407
408 link->addr_messages ++;
409 }
410 }
411
a6cc569e
TG
412 if (link->dhcp_lease) {
413 _cleanup_address_free_ Address *address = NULL;
414 struct in_addr addr;
415 struct in_addr netmask;
416 unsigned prefixlen;
417
418 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
419 if (r < 0) {
420 log_warning_link(link, "DHCP error: no address: %s",
421 strerror(-r));
422 return r;
423 }
424
425 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
426 if (r < 0) {
427 log_warning_link(link, "DHCP error: no netmask: %s",
428 strerror(-r));
429 return r;
430 }
431
432 prefixlen = net_netmask_to_prefixlen(&netmask);
433
434 r = address_new_dynamic(&address);
435 if (r < 0) {
436 log_error_link(link, "Could not allocate address: %s",
437 strerror(-r));
438 return r;
439 }
440
441 address->family = AF_INET;
442 address->in_addr.in = addr;
443 address->prefixlen = prefixlen;
444 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
445
446 r = address_configure(address, link, &address_handler);
f5be5601 447 if (r < 0) {
3333d748
ZJS
448 log_warning_link(link,
449 "could not set addresses: %s", strerror(-r));
f5be5601
TG
450 link_enter_failed(link);
451 return r;
452 }
453
454 link->addr_messages ++;
f882c247
TG
455 }
456
457 return 0;
458}
459
aba496a5
UTL
460static int address_update_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
461 Link *link = userdata;
462 int r;
463
464 assert(m);
465 assert(link);
466 assert(link->ifname);
467
468 if (link->state == LINK_STATE_FAILED)
469 return 1;
470
471 r = sd_rtnl_message_get_errno(m);
472 if (r < 0 && r != -ENOENT)
473 log_struct_link(LOG_WARNING, link,
474 "MESSAGE=%s: could not update address: %s",
475 link->ifname, strerror(-r),
476 "ERRNO=%d", -r,
477 NULL);
478
479 return 0;
480}
481
ff254138
TG
482static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
483 Link *link = userdata;
484 int r;
485
486 assert(m);
487 assert(link);
488 assert(link->ifname);
489
490 if (link->state == LINK_STATE_FAILED)
491 return 1;
492
493 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
494 if (r < 0 && r != -ENOENT)
495 log_struct_link(LOG_WARNING, link,
496 "MESSAGE=%s: could not drop address: %s",
497 link->ifname, strerror(-r),
498 "ERRNO=%d", -r,
499 NULL);
ff254138 500
5c1d3fc9 501 return 0;
ff254138
TG
502}
503
1346b1f0
TG
504static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
505 int r;
506
507 r = sd_bus_message_get_errno(m);
508 if (r < 0)
509 log_warning("Could not set hostname: %s", strerror(-r));
510
511 return 1;
512}
513
514static int set_hostname(sd_bus *bus, const char *hostname) {
515 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
516 int r = 0;
517
1346b1f0
TG
518 assert(hostname);
519
520 log_debug("Setting transient hostname: '%s'", hostname);
521
bcbca829
TG
522 if (!bus) { /* TODO: replace by assert when we can rely on kdbus */
523 log_info("Not connected to system bus, ignoring transient hostname.");
524 return 0;
525 }
526
1346b1f0
TG
527 r = sd_bus_message_new_method_call(
528 bus,
151b9b96 529 &m,
1346b1f0
TG
530 "org.freedesktop.hostname1",
531 "/org/freedesktop/hostname1",
532 "org.freedesktop.hostname1",
151b9b96 533 "SetHostname");
1346b1f0
TG
534 if (r < 0)
535 return r;
536
537 r = sd_bus_message_append(m, "sb", hostname, false);
538 if (r < 0)
539 return r;
540
541 r = sd_bus_call_async(bus, m, set_hostname_handler, NULL, 0, NULL);
542 if (r < 0)
543 log_error("Could not set transient hostname: %s", strerror(-r));
544
545 return r;
546}
547
4f882b2a
TG
548static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
549 Link *link = userdata;
550 int r;
551
552 assert(m);
553 assert(link);
554 assert(link->ifname);
555
556 if (link->state == LINK_STATE_FAILED)
557 return 1;
558
559 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
560 if (r < 0)
561 log_struct_link(LOG_WARNING, link,
562 "MESSAGE=%s: could not set MTU: %s",
563 link->ifname, strerror(-r),
564 "ERRNO=%d", -r,
565 NULL);
4f882b2a
TG
566
567 return 1;
568}
569
570static int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 571 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
572 int r;
573
574 assert(link);
575 assert(link->manager);
576 assert(link->manager->rtnl);
577
578 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
579
151b9b96
LP
580 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
581 RTM_SETLINK, link->ifindex);
4f882b2a
TG
582 if (r < 0) {
583 log_error_link(link, "Could not allocate RTM_SETLINK message");
584 return r;
585 }
586
587 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
588 if (r < 0) {
589 log_error_link(link, "Could not append MTU: %s", strerror(-r));
590 return r;
591 }
592
593 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
594 if (r < 0) {
595 log_error_link(link,
596 "Could not send rtnetlink message: %s", strerror(-r));
597 return r;
598 }
599
600 return 0;
601}
602
a6cc569e
TG
603static int dhcp_lease_lost(Link *link) {
604 _cleanup_address_free_ Address *address = NULL;
3e790eae
UTL
605 _cleanup_route_free_ Route *route_gw = NULL;
606 _cleanup_route_free_ Route *route = NULL;
a6cc569e
TG
607 struct in_addr addr;
608 struct in_addr netmask;
3e790eae 609 struct in_addr gateway;
a6cc569e 610 unsigned prefixlen;
ff254138
TG
611 int r;
612
613 assert(link);
a6cc569e 614 assert(link->dhcp_lease);
ff254138 615
14efd761
TG
616 log_warning_link(link, "DHCP lease lost");
617
a6cc569e
TG
618 r = address_new_dynamic(&address);
619 if (r >= 0) {
620 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
621 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
3e790eae 622 sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
a6cc569e 623 prefixlen = net_netmask_to_prefixlen(&netmask);
ff254138 624
3e790eae
UTL
625 r = route_new_dynamic(&route_gw);
626 if (r >= 0) {
627 route_gw->family = AF_INET;
628 route_gw->dst_addr.in = gateway;
629 route_gw->dst_prefixlen = 32;
630 route_gw->scope = RT_SCOPE_LINK;
631
632 route_drop(route_gw, link, &route_drop_handler);
633 }
634
635 r = route_new_dynamic(&route);
636 if (r >= 0) {
637 route->family = AF_INET;
638 route->in_addr.in = gateway;
639
640 route_drop(route, link, &route_drop_handler);
641 }
642
a6cc569e
TG
643 address->family = AF_INET;
644 address->in_addr.in = addr;
645 address->prefixlen = prefixlen;
ff254138 646
5c1d3fc9 647 address_drop(address, link, &address_drop_handler);
c07aeadf 648 }
eb27aeca 649
c07aeadf
TG
650 if (link->network->dhcp_mtu) {
651 uint16_t mtu;
ff254138 652
a6cc569e 653 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
c07aeadf
TG
654 if (r >= 0 && link->original_mtu != mtu) {
655 r = link_set_mtu(link, link->original_mtu);
656 if (r < 0) {
657 log_warning_link(link, "DHCP error: could not reset MTU");
658 link_enter_failed(link);
659 return r;
660 }
ff254138 661 }
c07aeadf 662 }
ff254138 663
c07aeadf 664 if (link->network->dhcp_hostname) {
216816c6
TG
665 const char *hostname = NULL;
666
667 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
668 if (r >= 0 && hostname) {
669 r = set_hostname(link->manager->bus, "");
670 if (r < 0)
671 log_error("Failed to reset transient hostname");
672 }
c07aeadf 673 }
4f882b2a 674
a6cc569e
TG
675 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
676
c07aeadf
TG
677 return 0;
678}
4f882b2a 679
c07aeadf 680static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
a6cc569e 681 sd_dhcp_lease *lease;
c07aeadf
TG
682 struct in_addr address;
683 struct in_addr netmask;
684 struct in_addr gateway;
685 unsigned prefixlen;
c07aeadf
TG
686 struct in_addr *nameservers;
687 size_t nameservers_size;
688 int r;
1346b1f0 689
c07aeadf
TG
690 assert(client);
691 assert(link);
ff254138 692
a6cc569e
TG
693 r = sd_dhcp_client_get_lease(client, &lease);
694 if (r < 0) {
695 log_warning_link(link, "DHCP error: no lease: %s",
696 strerror(-r));
697 return r;
698 }
699
700 r = sd_dhcp_lease_get_address(lease, &address);
ff254138 701 if (r < 0) {
c07aeadf
TG
702 log_warning_link(link, "DHCP error: no address: %s",
703 strerror(-r));
704 return r;
ff254138
TG
705 }
706
a6cc569e 707 r = sd_dhcp_lease_get_netmask(lease, &netmask);
ff254138 708 if (r < 0) {
c07aeadf
TG
709 log_warning_link(link, "DHCP error: no netmask: %s",
710 strerror(-r));
711 return r;
ff254138
TG
712 }
713
377a218f 714 prefixlen = net_netmask_to_prefixlen(&netmask);
ff254138 715
a6cc569e 716 r = sd_dhcp_lease_get_router(lease, &gateway);
ff254138 717 if (r < 0) {
c07aeadf
TG
718 log_warning_link(link, "DHCP error: no router: %s",
719 strerror(-r));
720 return r;
ff254138
TG
721 }
722
c07aeadf
TG
723 log_struct_link(LOG_INFO, link,
724 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
725 link->ifname,
726 ADDRESS_FMT_VAL(address),
727 prefixlen,
728 ADDRESS_FMT_VAL(gateway),
729 "ADDRESS=%u.%u.%u.%u",
730 ADDRESS_FMT_VAL(address),
731 "PREFIXLEN=%u",
732 prefixlen,
733 "GATEWAY=%u.%u.%u.%u",
734 ADDRESS_FMT_VAL(gateway),
735 NULL);
736
d50cf59b
TG
737 link->dhcp_lease = lease;
738
c07aeadf 739 if (link->network->dhcp_dns) {
a6cc569e 740 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
c07aeadf
TG
741 if (r >= 0) {
742 r = manager_update_resolv_conf(link->manager);
743 if (r < 0)
744 log_error("Failed to update resolv.conf");
ff254138 745 }
c07aeadf 746 }
ff254138 747
c07aeadf
TG
748 if (link->network->dhcp_mtu) {
749 uint16_t mtu;
750
a6cc569e 751 r = sd_dhcp_lease_get_mtu(lease, &mtu);
c07aeadf
TG
752 if (r >= 0) {
753 r = link_set_mtu(link, mtu);
754 if (r < 0)
755 log_error_link(link, "Failed to set MTU "
756 "to %" PRIu16, mtu);
757 }
758 }
ff254138 759
c07aeadf
TG
760 if (link->network->dhcp_hostname) {
761 const char *hostname;
ff254138 762
a6cc569e 763 r = sd_dhcp_lease_get_hostname(lease, &hostname);
c07aeadf
TG
764 if (r >= 0) {
765 r = set_hostname(link->manager->bus, hostname);
766 if (r < 0)
767 log_error("Failed to set transient hostname "
768 "to '%s'", hostname);
3bef724f 769 }
c07aeadf 770 }
3bef724f 771
c07aeadf
TG
772 link_enter_set_addresses(link);
773
774 return 0;
775}
776
777static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
778 Link *link = userdata;
aba496a5 779 int r = 0;
c07aeadf
TG
780
781 assert(link);
782 assert(link->network);
783 assert(link->manager);
784
785 if (link->state == LINK_STATE_FAILED)
786 return;
787
788 switch (event) {
789 case DHCP_EVENT_NO_LEASE:
790 log_debug_link(link, "IP address in use.");
791 break;
792 case DHCP_EVENT_EXPIRED:
793 case DHCP_EVENT_STOP:
794 case DHCP_EVENT_IP_CHANGE:
795 if (link->network->dhcp_critical) {
796 log_error_link(link, "DHCPv4 connection considered system critical, "
797 "ignoring request to reconfigure it.");
798 return;
4f882b2a 799 }
4f882b2a 800
17256461
UTL
801 if (link->dhcp_lease) {
802 r = dhcp_lease_lost(link);
803 if (r < 0) {
804 link_enter_failed(link);
805 return;
806 }
c07aeadf 807 }
1346b1f0 808
c07aeadf
TG
809 if (event == DHCP_EVENT_IP_CHANGE) {
810 r = dhcp_lease_acquired(client, link);
811 if (r < 0) {
812 link_enter_failed(link);
813 return;
814 }
1346b1f0 815 }
1346b1f0 816
5c1d3fc9 817 if (event == DHCP_EVENT_EXPIRED && link->network->ipv4ll) {
aba496a5
UTL
818 if (!sd_ipv4ll_is_running(link->ipv4ll))
819 r = sd_ipv4ll_start(link->ipv4ll);
820 else if (ipv4ll_is_bound(link->ipv4ll))
821 r = ipv4ll_address_update(link, false);
5c1d3fc9
UTL
822 if (r < 0) {
823 link_enter_failed(link);
824 return;
825 }
826 }
827
c07aeadf
TG
828 break;
829 case DHCP_EVENT_IP_ACQUIRE:
830 r = dhcp_lease_acquired(client, link);
831 if (r < 0) {
832 link_enter_failed(link);
833 return;
834 }
5c1d3fc9 835 if (link->ipv4ll) {
aba496a5
UTL
836 if (ipv4ll_is_bound(link->ipv4ll))
837 r = ipv4ll_address_update(link, true);
838 else
839 r = sd_ipv4ll_stop(link->ipv4ll);
5c1d3fc9
UTL
840 if (r < 0) {
841 link_enter_failed(link);
842 return;
843 }
844 }
c07aeadf
TG
845 break;
846 default:
847 if (event < 0)
848 log_warning_link(link, "DHCP error: %s", strerror(-event));
849 else
850 log_warning_link(link, "DHCP unknown event: %d", event);
c07aeadf 851 break;
ff254138
TG
852 }
853
854 return;
855}
856
aba496a5
UTL
857static int ipv4ll_address_update(Link *link, bool deprecate) {
858 int r;
859 struct in_addr addr;
860
861 assert(link);
862
863 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
864 if (r >= 0) {
865 _cleanup_address_free_ Address *address = NULL;
866
867 log_debug_link(link, "IPv4 link-local %s %u.%u.%u.%u",
868 deprecate ? "deprecate" : "approve",
869 ADDRESS_FMT_VAL(addr));
870
871 r = address_new_dynamic(&address);
872 if (r < 0) {
873 log_error_link(link, "Could not allocate address: %s", strerror(-r));
874 return r;
875 }
876
877 address->family = AF_INET;
878 address->in_addr.in = addr;
879 address->prefixlen = 16;
880 address->scope = RT_SCOPE_LINK;
881 address->cinfo.ifa_prefered = deprecate ? 0 : CACHE_INFO_INFINITY_LIFE_TIME;
882 address->broadcast.s_addr = address->in_addr.in.s_addr | htonl(0xfffffffflu >> address->prefixlen);
883
884 address_update(address, link, &address_update_handler);
885 }
886
887 return 0;
888
889}
890
891static int ipv4ll_address_lost(Link *link) {
5c1d3fc9
UTL
892 int r;
893 struct in_addr addr;
894
5c1d3fc9
UTL
895 assert(link);
896
897 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
898 if (r >= 0) {
899 _cleanup_address_free_ Address *address = NULL;
900 _cleanup_route_free_ Route *route = NULL;
901
902 log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
903 ADDRESS_FMT_VAL(addr));
904
905 r = address_new_dynamic(&address);
906 if (r < 0) {
907 log_error_link(link, "Could not allocate address: %s", strerror(-r));
908 return r;
909 }
910
911 address->family = AF_INET;
912 address->in_addr.in = addr;
913 address->prefixlen = 16;
914 address->scope = RT_SCOPE_LINK;
915
916 address_drop(address, link, &address_drop_handler);
917
918 r = route_new_dynamic(&route);
919 if (r < 0) {
920 log_error_link(link, "Could not allocate route: %s",
921 strerror(-r));
922 return r;
923 }
924
925 route->family = AF_INET;
926 route->scope = RT_SCOPE_LINK;
927 route->metrics = 99;
928
929 route_drop(route, link, &route_drop_handler);
930 }
931
932 return 0;
933}
934
aba496a5
UTL
935static bool ipv4ll_is_bound(sd_ipv4ll *ll) {
936 int r;
937 struct in_addr addr;
938
939 assert(ll);
940
941 r = sd_ipv4ll_get_address(ll, &addr);
942 if (r < 0)
943 return false;
944 return true;
945}
946
5c1d3fc9
UTL
947static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
948 struct in_addr address;
949 int r;
950
951 assert(ll);
952 assert(link);
953
954 r = sd_ipv4ll_get_address(ll, &address);
955 if (r < 0)
956 return r;
957
958 log_struct_link(LOG_INFO, link,
959 "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
960 link->ifname,
961 ADDRESS_FMT_VAL(address),
962 NULL);
963
964 link_enter_set_addresses(link);
965
966 return 0;
967}
968
969static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
970 Link *link = userdata;
971 int r;
972
973 assert(link);
974 assert(link->network);
975 assert(link->manager);
976
977 switch(event) {
978 case IPV4LL_EVENT_STOP:
979 case IPV4LL_EVENT_CONFLICT:
aba496a5 980 r = ipv4ll_address_lost(link);
5c1d3fc9
UTL
981 if (r < 0) {
982 link_enter_failed(link);
983 return;
984 }
985 break;
986 case IPV4LL_EVENT_BIND:
987 r = ipv4ll_address_claimed(ll, link);
988 if (r < 0) {
989 link_enter_failed(link);
990 return;
991 }
992 break;
993 default:
994 if (event < 0)
995 log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
996 else
997 log_warning_link(link, "IPv4 link-local unknown event: %d", event);
998 break;
999 }
1000}
1001
ff254138
TG
1002static int link_acquire_conf(Link *link) {
1003 int r;
1004
1005 assert(link);
1006 assert(link->network);
ff254138
TG
1007 assert(link->manager);
1008 assert(link->manager->event);
1009
5c1d3fc9 1010 if (link->network->ipv4ll) {
eb34d4af 1011 assert(link->ipv4ll);
ff254138 1012
5c1d3fc9
UTL
1013 log_debug_link(link, "acquiring IPv4 link-local address");
1014
1015 r = sd_ipv4ll_start(link->ipv4ll);
ff254138
TG
1016 if (r < 0)
1017 return r;
5c1d3fc9
UTL
1018 }
1019
1020 if (link->network->dhcp) {
eb34d4af 1021 assert(link->dhcp_client);
ff254138 1022
5c1d3fc9 1023 log_debug_link(link, "acquiring DHCPv4 lease");
ab47d620 1024
5c1d3fc9
UTL
1025 r = sd_dhcp_client_start(link->dhcp_client);
1026 if (r < 0)
1027 return r;
1028 }
ff254138
TG
1029
1030 return 0;
1031}
1032
1033static int link_update_flags(Link *link, unsigned flags) {
1034 int r;
1035
1036 assert(link);
1037 assert(link->network);
1038
1039 if (link->state == LINK_STATE_FAILED)
1040 return 0;
1041
a748b692 1042 if (link->flags == flags)
efbc88b8 1043 return 0;
efbc88b8 1044
c49b33ac
TG
1045 log_debug_link(link, "link status updated: %#.8x -> %#.8x",
1046 link->flags, flags);
1047
3333d748
ZJS
1048 if ((link->flags & IFF_UP) != (flags & IFF_UP))
1049 log_info_link(link,
e6674986 1050 "link is %s", flags & IFF_UP ? "up": "down");
efbc88b8
TG
1051
1052 if ((link->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
1053 if (flags & IFF_LOWER_UP) {
39032b87 1054 log_info_link(link, "carrier on");
efbc88b8 1055
5c1d3fc9 1056 if (link->network->dhcp || link->network->ipv4ll) {
efbc88b8
TG
1057 r = link_acquire_conf(link);
1058 if (r < 0) {
5c1d3fc9 1059 log_warning_link(link, "Could not acquire configuration: %s", strerror(-r));
efbc88b8
TG
1060 link_enter_failed(link);
1061 return r;
1062 }
ff254138 1063 }
efbc88b8 1064 } else {
39032b87 1065 log_info_link(link, "carrier off");
efbc88b8
TG
1066
1067 if (link->network->dhcp) {
a6cc569e 1068 r = sd_dhcp_client_stop(link->dhcp_client);
efbc88b8 1069 if (r < 0) {
1f6d9bc9 1070 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
efbc88b8
TG
1071 link_enter_failed(link);
1072 return r;
1073 }
ff254138 1074 }
5c1d3fc9
UTL
1075
1076 if (link->network->ipv4ll) {
1077 r = sd_ipv4ll_stop(link->ipv4ll);
1078 if (r < 0) {
1079 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
1080 link_enter_failed(link);
1081 return r;
1082 }
1083 }
ff254138
TG
1084 }
1085 }
1086
1087 link->flags = flags;
1088
1089 return 0;
1090}
1091
dd3efc09
TG
1092static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1093 Link *link = userdata;
1094 int r;
1095
1746cf2a
TG
1096 assert(link);
1097
1098 if (link->state == LINK_STATE_FAILED)
1099 return 1;
1100
dd3efc09 1101 r = sd_rtnl_message_get_errno(m);
58b12917
ZJS
1102 if (r >= 0)
1103 link_update_flags(link, link->flags | IFF_UP);
1104 else
76800848 1105 log_struct_link(LOG_WARNING, link,
c9ccc19f
TG
1106 "MESSAGE=%s: could not bring up interface: %s",
1107 link->ifname, strerror(-r),
1108 "ERRNO=%d", -r,
1109 NULL);
f882c247
TG
1110 return 1;
1111}
1112
1113static int link_up(Link *link) {
cf6a8911 1114 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1115 int r;
1116
f882c247
TG
1117 assert(link);
1118 assert(link->manager);
1119 assert(link->manager->rtnl);
1120
39032b87 1121 log_debug_link(link, "bringing link up");
449f7554 1122
151b9b96
LP
1123 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1124 RTM_SETLINK, link->ifindex);
f579559b 1125 if (r < 0) {
39032b87 1126 log_error_link(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1127 return r;
1128 }
1129
5d4795f3 1130 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1131 if (r < 0) {
3333d748 1132 log_error_link(link, "Could not set link flags: %s", strerror(-r));
fc25d7f8
TG
1133 return r;
1134 }
1135
dd3efc09 1136 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
f579559b 1137 if (r < 0) {
3333d748
ZJS
1138 log_error_link(link,
1139 "Could not send rtnetlink message: %s", strerror(-r));
f579559b
TG
1140 return r;
1141 }
1142
f882c247
TG
1143 return 0;
1144}
1145
52433f6b 1146static int link_enslaved(Link *link) {
f882c247
TG
1147 int r;
1148
ef1ba606 1149 assert(link);
52433f6b 1150 assert(link->state == LINK_STATE_ENSLAVING);
f5be5601 1151 assert(link->network);
dd3efc09 1152
f882c247 1153 r = link_up(link);
ef1ba606
TG
1154 if (r < 0) {
1155 link_enter_failed(link);
1156 return r;
1157 }
f882c247 1158
5c1d3fc9 1159 if (!link->network->dhcp && !link->network->ipv4ll)
1746cf2a 1160 return link_enter_set_addresses(link);
ef1ba606
TG
1161
1162 return 0;
02b59d57
TG
1163}
1164
52433f6b 1165static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
02b59d57
TG
1166 Link *link = userdata;
1167 int r;
1168
1746cf2a 1169 assert(link);
52433f6b 1170 assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED);
ef1ba606 1171 assert(link->network);
02b59d57 1172
52433f6b
TG
1173 link->enslaving --;
1174
02b59d57
TG
1175 if (link->state == LINK_STATE_FAILED)
1176 return 1;
1177
1178 r = sd_rtnl_message_get_errno(m);
ef1ba606 1179 if (r < 0) {
c9ccc19f
TG
1180 log_struct_link(LOG_ERR, link,
1181 "MESSAGE=%s: could not enslave: %s",
1182 link->ifname, strerror(-r),
1183 "ERRNO=%d", -r,
1184 NULL);
ef1ba606
TG
1185 link_enter_failed(link);
1186 return 1;
3333d748 1187 }
02b59d57 1188
52433f6b 1189 log_debug_link(link, "enslaved");
ab47d620 1190
52433f6b
TG
1191 if (link->enslaving == 0)
1192 link_enslaved(link);
02b59d57
TG
1193
1194 return 1;
1195}
1196
52433f6b 1197static int link_enter_enslave(Link *link) {
fe6b2d55 1198 NetDev *vlan, *macvlan;
672682a6 1199 Iterator i;
02b59d57
TG
1200 int r;
1201
1202 assert(link);
1203 assert(link->network);
ef1ba606 1204 assert(link->state == _LINK_STATE_INVALID);
02b59d57 1205
52433f6b 1206 link->state = LINK_STATE_ENSLAVING;
02b59d57 1207
fe8db0c5
TG
1208 link_save(link);
1209
63ffa720 1210 if (!link->network->bridge && !link->network->bond &&
fe6b2d55
TG
1211 hashmap_isempty(link->network->vlans) &&
1212 hashmap_isempty(link->network->macvlans))
52433f6b 1213 return link_enslaved(link);
02b59d57 1214
52433f6b
TG
1215 if (link->network->bridge) {
1216 log_struct_link(LOG_DEBUG, link,
1217 "MESSAGE=%s: enslaving by '%s'",
c9ccc19f 1218 link->ifname, link->network->bridge->name,
52433f6b
TG
1219 NETDEV(link->network->bridge),
1220 NULL);
449f7554 1221
52433f6b
TG
1222 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1223 if (r < 0) {
1224 log_struct_link(LOG_WARNING, link,
1225 "MESSAGE=%s: could not enslave by '%s': %s",
c9ccc19f 1226 link->ifname, link->network->bridge->name, strerror(-r),
52433f6b
TG
1227 NETDEV(link->network->bridge),
1228 NULL);
1229 link_enter_failed(link);
1230 return r;
1231 }
1232
0ad6148e
MO
1233 link->enslaving ++;
1234 }
1235
1236 if (link->network->bond) {
1237 log_struct_link(LOG_DEBUG, link,
1238 "MESSAGE=%s: enslaving by '%s'",
1239 link->ifname, link->network->bond->name,
1240 NETDEV(link->network->bond),
1241 NULL);
1242
1243 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1244 if (r < 0) {
1245 log_struct_link(LOG_WARNING, link,
1246 "MESSAGE=%s: could not enslave by '%s': %s",
1247 link->ifname, link->network->bond->name, strerror(-r),
1248 NETDEV(link->network->bond),
1249 NULL);
1250 link_enter_failed(link);
1251 return r;
1252 }
1253
52433f6b
TG
1254 link->enslaving ++;
1255 }
1256
672682a6 1257 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
52433f6b
TG
1258 log_struct_link(LOG_DEBUG, link,
1259 "MESSAGE=%s: enslaving by '%s'",
672682a6 1260 link->ifname, vlan->name, NETDEV(vlan), NULL);
52433f6b 1261
672682a6 1262 r = netdev_enslave(vlan, link, &enslave_handler);
52433f6b
TG
1263 if (r < 0) {
1264 log_struct_link(LOG_WARNING, link,
1265 "MESSAGE=%s: could not enslave by '%s': %s",
672682a6
TG
1266 link->ifname, vlan->name, strerror(-r),
1267 NETDEV(vlan), NULL);
52433f6b
TG
1268 link_enter_failed(link);
1269 return r;
1270 }
1271
1272 link->enslaving ++;
ef1ba606
TG
1273 }
1274
fe6b2d55
TG
1275 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1276 log_struct_link(LOG_DEBUG, link,
1277 "MESSAGE=%s: enslaving by '%s'",
1278 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1279
1280 r = netdev_enslave(macvlan, link, &enslave_handler);
1281 if (r < 0) {
1282 log_struct_link(LOG_WARNING, link,
1283 "MESSAGE=%s: could not enslave by '%s': %s",
1284 link->ifname, macvlan->name, strerror(-r),
1285 NETDEV(macvlan), NULL);
1286 link_enter_failed(link);
1287 return r;
1288 }
1289
1290 link->enslaving ++;
1291 }
1292
ef1ba606
TG
1293 return 0;
1294}
1295
11a7f229
TG
1296static int link_getlink_handler(sd_rtnl *rtnl, sd_rtnl_message *m,
1297 void *userdata) {
ef1ba606
TG
1298 Link *link = userdata;
1299 int r;
1300
1746cf2a 1301 assert(link);
7ff8f4b5 1302 assert(link->ifname);
1746cf2a
TG
1303
1304 if (link->state == LINK_STATE_FAILED)
1305 return 1;
1306
ef1ba606
TG
1307 r = sd_rtnl_message_get_errno(m);
1308 if (r < 0) {
c9ccc19f
TG
1309 log_struct_link(LOG_ERR, link,
1310 "MESSAGE=%s: could not get state: %s",
1311 link->ifname, strerror(-r),
1312 "ERRNO=%d", -r,
1313 NULL);
ef1ba606 1314 link_enter_failed(link);
c9ccc19f 1315 return 1;
ef1ba606
TG
1316 }
1317
5eb036ca
TG
1318 link_update(link, m);
1319
ef1ba606
TG
1320 return 1;
1321}
1322
11a7f229 1323static int link_getlink(Link *link) {
cf6a8911 1324 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
ef1ba606
TG
1325 int r;
1326
1327 assert(link);
1328 assert(link->manager);
1329 assert(link->manager->rtnl);
1330
39032b87 1331 log_debug_link(link, "requesting link status");
449f7554 1332
151b9b96
LP
1333 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1334 RTM_GETLINK, link->ifindex);
ef1ba606 1335 if (r < 0) {
39032b87 1336 log_error_link(link, "Could not allocate RTM_GETLINK message");
ef1ba606
TG
1337 return r;
1338 }
1339
11a7f229
TG
1340 r = sd_rtnl_call_async(link->manager->rtnl, req, link_getlink_handler,
1341 link, 0, NULL);
ef1ba606 1342 if (r < 0) {
3333d748
ZJS
1343 log_error_link(link,
1344 "Could not send rtnetlink message: %s", strerror(-r));
ef1ba606 1345 return r;
dd3efc09 1346 }
02b59d57
TG
1347
1348 return 0;
1349}
1350
a748b692 1351static int link_configure(Link *link) {
02b59d57
TG
1352 int r;
1353
ef1ba606 1354 assert(link);
ef1ba606
TG
1355 assert(link->state == _LINK_STATE_INVALID);
1356
11a7f229 1357 r = link_getlink(link);
a748b692 1358 if (r < 0)
ef1ba606 1359 return r;
dd3efc09 1360
52433f6b 1361 return link_enter_enslave(link);
f579559b 1362}
dd3efc09 1363
a748b692
TG
1364int link_add(Manager *m, struct udev_device *device, Link **ret) {
1365 Link *link = NULL;
1366 Network *network;
1367 int r;
1368
1369 assert(m);
1370 assert(device);
1371
1372 r = link_new(m, device, &link);
1373 if (r < 0)
1374 return r;
1375
1376 *ret = link;
1377
1378 r = network_get(m, device, &network);
1379 if (r < 0)
1380 return r == -ENOENT ? 0 : r;
1381
1382 r = network_apply(m, network, link);
1383 if (r < 0)
1384 return r;
1385
eb34d4af 1386 if (link->network->ipv4ll) {
b5db00e5 1387 uint8_t seed[8];
eb34d4af
TG
1388 r = sd_ipv4ll_new(&link->ipv4ll);
1389 if (r < 0)
1390 return r;
1391
b5db00e5
UTL
1392 r = net_get_unique_predictable_data(link->udev_device, seed);
1393 if (r >= 0) {
1394 r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
1395 if (r < 0)
1396 return r;
1397 }
1398
eb34d4af
TG
1399 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1400 if (r < 0)
1401 return r;
1402
1403 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1404 if (r < 0)
1405 return r;
1406
1407 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1408 if (r < 0)
1409 return r;
1410 }
1411
1412 if (link->network->dhcp) {
1413 r = sd_dhcp_client_new(&link->dhcp_client);
1414 if (r < 0)
1415 return r;
1416
1417 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1418 if (r < 0)
1419 return r;
1420
1421 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1422 if (r < 0)
1423 return r;
1424
1425 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1426 if (r < 0)
1427 return r;
1428
1429 if (link->network->dhcp_mtu) {
1430 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1431 if (r < 0)
1432 return r;
1433 }
1434 }
1435
a748b692
TG
1436 r = link_configure(link);
1437 if (r < 0)
1438 return r;
1439
1440 return 0;
1441}
1442
22936833
TG
1443int link_update(Link *link, sd_rtnl_message *m) {
1444 unsigned flags;
c49b33ac 1445 struct ether_addr mac;
22936833
TG
1446 int r;
1447
dd3efc09 1448 assert(link);
a748b692 1449 assert(link->network);
22936833
TG
1450 assert(m);
1451
1746cf2a
TG
1452 if (link->state == LINK_STATE_FAILED)
1453 return 0;
1454
9842de0d
TG
1455 if (link->network->dhcp && link->network->dhcp_mtu &&
1456 !link->original_mtu) {
1457 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1458 if (r >= 0)
1459 log_debug_link(link, "saved original MTU: %"
1460 PRIu16, link->original_mtu);
1461 }
69629de9 1462
c49b33ac 1463 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
20861203
TG
1464 if (r < 0)
1465 log_debug_link(link, "Could not get MAC address: %s", strerror(-r));
1466 else {
1467 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
c49b33ac 1468
20861203 1469 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
c49b33ac 1470
20861203
TG
1471 log_debug_link(link, "MAC address: "
1472 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1473 mac.ether_addr_octet[0],
1474 mac.ether_addr_octet[1],
1475 mac.ether_addr_octet[2],
1476 mac.ether_addr_octet[3],
1477 mac.ether_addr_octet[4],
1478 mac.ether_addr_octet[5]);
c49b33ac 1479
20861203
TG
1480 if (link->ipv4ll) {
1481 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1482 if (r < 0) {
1483 log_warning_link(link, "Could not update MAC "
1484 "address in IPv4LL client: %s",
1485 strerror(-r));
1486 return r;
1487 }
c49b33ac 1488 }
c49b33ac 1489
20861203
TG
1490 if (link->dhcp_client) {
1491 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1492 if (r < 0) {
1493 log_warning_link(link, "Could not update MAC "
1494 "address in DHCP client: %s",
1495 strerror(-r));
1496 return r;
1497 }
c49b33ac
TG
1498 }
1499 }
4f882b2a
TG
1500 }
1501
a748b692
TG
1502 r = sd_rtnl_message_link_get_flags(m, &flags);
1503 if (r < 0) {
1504 log_warning_link(link, "Could not get link flags");
1505 return r;
1506 }
1507
ff254138 1508 return link_update_flags(link, flags);
dd3efc09 1509}
fe8db0c5
TG
1510
1511int link_save(Link *link) {
1512 _cleanup_free_ char *temp_path = NULL;
1513 _cleanup_fclose_ FILE *f = NULL;
7ff8f4b5 1514 const char *state;
fe8db0c5
TG
1515 int r;
1516
1517 assert(link);
1518 assert(link->state_file);
1519
7ff8f4b5
TG
1520 state = link_state_to_string(link->state);
1521 if (!state)
1522 goto finish;
1523
fe8db0c5
TG
1524 r = fopen_temporary(link->state_file, &f, &temp_path);
1525 if (r < 0)
1526 goto finish;
1527
1528 fchmod(fileno(f), 0644);
1529
1530 fprintf(f,
1531 "# This is private data. Do not parse.\n"
7ff8f4b5 1532 "STATE=%s\n", state);
fe8db0c5
TG
1533
1534 if (link->dhcp_lease) {
fd88eb8a 1535 _cleanup_free_ char *lease_file = NULL;
2a1763ed 1536
315db1a8
ZJS
1537 r = asprintf(&lease_file, "/run/systemd/network/leases/%"PRIu64,
1538 link->ifindex);
2a1763ed 1539 if (r < 0)
315db1a8 1540 return -ENOMEM;
fe8db0c5
TG
1541
1542 r = dhcp_lease_save(link->dhcp_lease, lease_file);
1543 if (r < 0)
1544 goto finish;
1545
1546 fprintf(f, "DHCP_LEASE=%s\n", lease_file);
1547 }
1548
1549 fflush(f);
1550
1551 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1552 r = -errno;
1553 unlink(link->state_file);
1554 unlink(temp_path);
1555 }
1556
1557finish:
1558 if (r < 0)
1559 log_error("Failed to save link data %s: %s", link->state_file, strerror(-r));
1560
1561 return r;
1562}
1563
1564static const char* const link_state_table[_LINK_STATE_MAX] = {
1565 [LINK_STATE_ENSLAVING] = "configuring",
1566 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1567 [LINK_STATE_SETTING_ROUTES] = "configuring",
1568 [LINK_STATE_CONFIGURED] = "configured",
1569 [LINK_STATE_FAILED] = "failed",
1570};
1571
1572DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);