]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
sd-dhcp-client: improve logging when stopping 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"
505f8da7 27#include "udev-util.h"
f579559b 28#include "util.h"
505f8da7 29#include "virt.h"
1346b1f0 30#include "bus-util.h"
c6f7c917 31#include "network-internal.h"
f579559b 32
3a67e927 33#include "network-util.h"
fe8db0c5
TG
34#include "dhcp-lease-internal.h"
35
aba496a5
UTL
36static int ipv4ll_address_update(Link *link, bool deprecate);
37static bool ipv4ll_is_bound(sd_ipv4ll *ll);
38
505f8da7 39static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
14b746f7 40 _cleanup_link_unref_ Link *link = NULL;
505f8da7
TG
41 uint16_t type;
42 char *ifname;
43 int r, ifindex;
f579559b 44
0c2f9b84
TG
45 assert(manager);
46 assert(manager->links);
505f8da7 47 assert(message);
f579559b
TG
48 assert(ret);
49
505f8da7
TG
50 r = sd_rtnl_message_get_type(message, &type);
51 if (r < 0)
52 return r;
53 else if (type != RTM_NEWLINK)
54 return -EINVAL;
55
56 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
57 if (r < 0)
58 return r;
59 else if (ifindex <= 0)
60 return -EINVAL;
61
62 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &ifname);
63 if (r < 0)
64 return r;
65
f579559b
TG
66 link = new0(Link, 1);
67 if (!link)
68 return -ENOMEM;
69
14b746f7 70 link->n_ref = 1;
5a3eb5a7 71 link->manager = manager;
505f8da7
TG
72 link->state = LINK_STATE_INITIALIZING;
73 link->ifindex = ifindex;
74 link->ifname = strdup(ifname);
75 if (!link->ifname)
76 return -ENOMEM;
f579559b 77
315db1a8
ZJS
78 r = asprintf(&link->state_file, "/run/systemd/network/links/%"PRIu64,
79 link->ifindex);
fe8db0c5 80 if (r < 0)
315db1a8 81 return -ENOMEM;
fe8db0c5 82
68a8723c
TG
83 r = asprintf(&link->lease_file, "/run/systemd/network/leases/%"PRIu64,
84 link->ifindex);
85 if (r < 0)
86 return -ENOMEM;
87
0617ffab 88 r = hashmap_put(manager->links, &link->ifindex, link);
f579559b
TG
89 if (r < 0)
90 return r;
91
92 *ret = link;
93 link = NULL;
94
95 return 0;
96}
97
14b746f7 98static void link_free(Link *link) {
f579559b
TG
99 if (!link)
100 return;
101
0617ffab 102 assert(link->manager);
f579559b 103
e5b04c8d 104 sd_dhcp_client_unref(link->dhcp_client);
a6cc569e 105 sd_dhcp_lease_unref(link->dhcp_lease);
f5be5601 106
68a8723c
TG
107 unlink(link->lease_file);
108 free(link->lease_file);
109
56cd007a 110 sd_ipv4ll_unref(link->ipv4ll);
5c1d3fc9 111
0617ffab 112 hashmap_remove(link->manager->links, &link->ifindex);
f579559b 113
c166a070 114 free(link->ifname);
68a8723c
TG
115
116 unlink(link->state_file);
fe8db0c5 117 free(link->state_file);
c166a070 118
b5db00e5
UTL
119 udev_device_unref(link->udev_device);
120
f579559b
TG
121 free(link);
122}
123
14b746f7
TG
124Link *link_unref(Link *link) {
125 if (link && (-- link->n_ref <= 0))
126 link_free(link);
127
128 return NULL;
129}
130
131Link *link_ref(Link *link) {
132 if (link)
133 assert_se(++ link->n_ref >= 2);
134
135 return link;
136}
137
11a7f229
TG
138int link_get(Manager *m, int ifindex, Link **ret) {
139 Link *link;
140 uint64_t ifindex_64;
141
142 assert(m);
143 assert(m->links);
144 assert(ifindex);
145 assert(ret);
146
147 ifindex_64 = ifindex;
148 link = hashmap_get(m->links, &ifindex_64);
149 if (!link)
150 return -ENODEV;
151
152 *ret = link;
153
154 return 0;
155}
156
370e9930
TG
157void link_drop(Link *link) {
158 if (!link || link->state == LINK_STATE_LINGER)
159 return;
160
161 link->state = LINK_STATE_LINGER;
162
163 log_debug_link(link, "dropped");
164
165 link_unref(link);
166
167 return;
168}
169
f882c247 170static int link_enter_configured(Link *link) {
ef1ba606
TG
171 assert(link);
172 assert(link->state == LINK_STATE_SETTING_ROUTES);
173
39032b87 174 log_info_link(link, "link configured");
f882c247
TG
175
176 link->state = LINK_STATE_CONFIGURED;
177
fe8db0c5
TG
178 link_save(link);
179
f882c247
TG
180 return 0;
181}
182
57bd6899
TG
183static void link_enter_unmanaged(Link *link) {
184 assert(link);
185
df9aa406 186 log_debug_link(link, "unmanaged");
57bd6899
TG
187
188 link->state = LINK_STATE_UNMANAGED;
189
190 link_save(link);
191}
192
111bb8f9
TG
193static int link_stop_clients(Link *link) {
194 int r = 0, k;
195
196 assert(link);
197 assert(link->manager);
198 assert(link->manager->event);
199
200 if (!link->network)
201 return 0;
202
203 if (link->network->dhcp) {
204 assert(link->dhcp_client);
205
206 k = sd_dhcp_client_stop(link->dhcp_client);
207 if (k < 0) {
208 log_warning_link(link, "Could not stop DHCPv4 client: %s", strerror(-r));
209 r = k;
210 }
211 }
212
213 if (link->network->ipv4ll) {
214 assert(link->ipv4ll);
215
216 k = sd_ipv4ll_stop(link->ipv4ll);
217 if (k < 0) {
218 log_warning_link(link, "Could not stop IPv4 link-local: %s", strerror(-r));
219 r = k;
220 }
221 }
222
223 return r;
224}
225
ef1ba606
TG
226static void link_enter_failed(Link *link) {
227 assert(link);
f882c247 228
370e9930 229 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
2139694e
TG
230 return;
231
39032b87 232 log_warning_link(link, "failed");
449f7554 233
ef1ba606 234 link->state = LINK_STATE_FAILED;
fe8db0c5 235
111bb8f9
TG
236 link_stop_clients(link);
237
fe8db0c5 238 link_save(link);
f882c247
TG
239}
240
f882c247
TG
241static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
242 Link *link = userdata;
243 int r;
244
f5be5601 245 assert(link->route_messages > 0);
370e9930
TG
246 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
247 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
248 LINK_STATE_LINGER));
f882c247 249
f5be5601 250 link->route_messages --;
f882c247 251
370e9930 252 if (IN_SET(LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 253 link_unref(link);
f882c247 254 return 1;
b226d99b 255 }
f882c247
TG
256
257 r = sd_rtnl_message_get_errno(m);
c166a070 258 if (r < 0 && r != -EEXIST)
c9ccc19f
TG
259 log_struct_link(LOG_WARNING, link,
260 "MESSAGE=%s: could not set route: %s",
261 link->ifname, strerror(-r),
262 "ERRNO=%d", -r,
263 NULL);
f882c247 264
f5be5601
TG
265 /* we might have received an old reply after moving back to SETTING_ADDRESSES,
266 * ignore it */
267 if (link->route_messages == 0 && link->state == LINK_STATE_SETTING_ROUTES) {
39032b87 268 log_debug_link(link, "routes set");
dd3efc09
TG
269 link_enter_configured(link);
270 }
f882c247 271
b226d99b
TG
272 link_unref(link);
273
f882c247
TG
274 return 1;
275}
276
277static int link_enter_set_routes(Link *link) {
a6cc569e 278 Route *rt;
f882c247
TG
279 int r;
280
281 assert(link);
282 assert(link->network);
ef1ba606 283 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 284
ef1ba606 285 link->state = LINK_STATE_SETTING_ROUTES;
f882c247 286
5c1d3fc9 287 if (!link->network->static_routes && !link->dhcp_lease &&
370e9930 288 (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false))
dd3efc09 289 return link_enter_configured(link);
f882c247 290
39032b87 291 log_debug_link(link, "setting routes");
449f7554 292
a6cc569e
TG
293 LIST_FOREACH(static_routes, rt, link->network->static_routes) {
294 r = route_configure(rt, link, &route_handler);
dd3efc09 295 if (r < 0) {
3333d748
ZJS
296 log_warning_link(link,
297 "could not set routes: %s", strerror(-r));
ef1ba606
TG
298 link_enter_failed(link);
299 return r;
dd3efc09 300 }
c166a070 301
b226d99b 302 link_ref(link);
f5be5601
TG
303 link->route_messages ++;
304 }
305
5c1d3fc9
UTL
306 if (link->ipv4ll && !link->dhcp_lease) {
307 _cleanup_route_free_ Route *route = NULL;
308 struct in_addr addr;
309
310 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
311 if (r < 0 && r != -ENOENT) {
312 log_warning_link(link, "IPV4LL error: no address: %s",
313 strerror(-r));
314 return r;
315 }
316
317 if (r != -ENOENT) {
318 r = route_new_dynamic(&route);
319 if (r < 0) {
320 log_error_link(link, "Could not allocate route: %s",
321 strerror(-r));
322 return r;
323 }
324
325 route->family = AF_INET;
326 route->scope = RT_SCOPE_LINK;
327 route->metrics = 99;
328
329 r = route_configure(route, link, &route_handler);
330 if (r < 0) {
331 log_warning_link(link,
332 "could not set routes: %s", strerror(-r));
333 link_enter_failed(link);
334 return r;
335 }
336
b226d99b 337 link_ref(link);
5c1d3fc9
UTL
338 link->route_messages ++;
339 }
340 }
341
a6cc569e
TG
342 if (link->dhcp_lease) {
343 _cleanup_route_free_ Route *route = NULL;
9765ce69 344 _cleanup_route_free_ Route *route_gw = NULL;
a6cc569e
TG
345 struct in_addr gateway;
346
347 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
8ddbeaa2
UTL
348 if (r < 0 && r != -ENOENT) {
349 log_warning_link(link, "DHCP error: %s", strerror(-r));
a6cc569e
TG
350 return r;
351 }
352
8ddbeaa2
UTL
353 if (r >= 0) {
354 r = route_new_dynamic(&route);
355 if (r < 0) {
356 log_error_link(link, "Could not allocate route: %s",
357 strerror(-r));
358 return r;
359 }
a6cc569e 360
8ddbeaa2
UTL
361 r = route_new_dynamic(&route_gw);
362 if (r < 0) {
363 log_error_link(link, "Could not allocate route: %s",
364 strerror(-r));
365 return r;
366 }
9765ce69 367
8ddbeaa2
UTL
368 /* The dhcp netmask may mask out the gateway. Add an explicit
369 * route for the gw host so that we can route no matter the
370 * netmask or existing kernel route tables. */
371 route_gw->family = AF_INET;
372 route_gw->dst_addr.in = gateway;
373 route_gw->dst_prefixlen = 32;
374 route_gw->scope = RT_SCOPE_LINK;
9765ce69 375
8ddbeaa2
UTL
376 r = route_configure(route_gw, link, &route_handler);
377 if (r < 0) {
378 log_warning_link(link,
379 "could not set host route: %s", strerror(-r));
380 return r;
381 }
9765ce69 382
b226d99b 383 link_ref(link);
8ddbeaa2 384 link->route_messages ++;
9765ce69 385
8ddbeaa2
UTL
386 route->family = AF_INET;
387 route->in_addr.in = gateway;
a6cc569e 388
8ddbeaa2
UTL
389 r = route_configure(route, link, &route_handler);
390 if (r < 0) {
391 log_warning_link(link,
392 "could not set routes: %s", strerror(-r));
393 link_enter_failed(link);
394 return r;
395 }
396
b226d99b 397 link_ref(link);
8ddbeaa2 398 link->route_messages ++;
f5be5601 399 }
8ddbeaa2 400 }
f5be5601 401
8ddbeaa2
UTL
402 if (link->route_messages == 0) {
403 link_enter_configured(link);
f882c247
TG
404 }
405
406 return 0;
407}
408
5c1d3fc9
UTL
409static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
410 Link *link = userdata;
411 int r;
412
413 assert(m);
414 assert(link);
415 assert(link->ifname);
416
370e9930 417 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 418 link_unref(link);
5c1d3fc9 419 return 1;
b226d99b 420 }
5c1d3fc9
UTL
421
422 r = sd_rtnl_message_get_errno(m);
423 if (r < 0 && r != -ENOENT)
424 log_struct_link(LOG_WARNING, link,
425 "MESSAGE=%s: could not drop route: %s",
426 link->ifname, strerror(-r),
427 "ERRNO=%d", -r,
428 NULL);
429
b226d99b
TG
430 link_unref(link);
431
5c1d3fc9
UTL
432 return 0;
433}
434
f882c247
TG
435static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
436 Link *link = userdata;
437 int r;
438
f5be5601
TG
439 assert(m);
440 assert(link);
441 assert(link->ifname);
442 assert(link->addr_messages > 0);
370e9930
TG
443 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
444 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 445
f5be5601 446 link->addr_messages --;
f882c247 447
370e9930 448 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 449 link_unref(link);
f882c247 450 return 1;
b226d99b 451 }
f882c247
TG
452
453 r = sd_rtnl_message_get_errno(m);
c166a070 454 if (r < 0 && r != -EEXIST)
c9ccc19f 455 log_struct_link(LOG_WARNING, link,
3333d748
ZJS
456 "MESSAGE=%s: could not set address: %s",
457 link->ifname, strerror(-r),
458 "ERRNO=%d", -r,
459 NULL);
f882c247 460
f5be5601 461 if (link->addr_messages == 0) {
39032b87 462 log_debug_link(link, "addresses set");
ef1ba606 463 link_enter_set_routes(link);
dd3efc09 464 }
f882c247 465
b226d99b
TG
466 link_unref(link);
467
f882c247
TG
468 return 1;
469}
470
471static int link_enter_set_addresses(Link *link) {
a6cc569e 472 Address *ad;
f882c247
TG
473 int r;
474
475 assert(link);
476 assert(link->network);
f5be5601 477 assert(link->state != _LINK_STATE_INVALID);
f882c247 478
ef1ba606 479 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 480
5c1d3fc9 481 if (!link->network->static_addresses && !link->dhcp_lease &&
aba496a5 482 (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false))
ef1ba606 483 return link_enter_set_routes(link);
f882c247 484
39032b87 485 log_debug_link(link, "setting addresses");
449f7554 486
a6cc569e
TG
487 LIST_FOREACH(static_addresses, ad, link->network->static_addresses) {
488 r = address_configure(ad, link, &address_handler);
dd3efc09 489 if (r < 0) {
3333d748
ZJS
490 log_warning_link(link,
491 "could not set addresses: %s", strerror(-r));
ef1ba606
TG
492 link_enter_failed(link);
493 return r;
dd3efc09 494 }
c166a070 495
b226d99b 496 link_ref(link);
f5be5601
TG
497 link->addr_messages ++;
498 }
499
5c1d3fc9
UTL
500 if (link->ipv4ll && !link->dhcp_lease) {
501 _cleanup_address_free_ Address *ll_addr = NULL;
502 struct in_addr addr;
503
504 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
505 if (r < 0 && r != -ENOENT) {
506 log_warning_link(link, "IPV4LL error: no address: %s",
507 strerror(-r));
508 return r;
509 }
510
511 if (r != -ENOENT) {
512 r = address_new_dynamic(&ll_addr);
513 if (r < 0) {
514 log_error_link(link, "Could not allocate address: %s", strerror(-r));
515 return r;
516 }
517
518 ll_addr->family = AF_INET;
519 ll_addr->in_addr.in = addr;
520 ll_addr->prefixlen = 16;
521 ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
522 ll_addr->scope = RT_SCOPE_LINK;
523
524 r = address_configure(ll_addr, link, &address_handler);
525 if (r < 0) {
526 log_warning_link(link,
527 "could not set addresses: %s", strerror(-r));
528 link_enter_failed(link);
529 return r;
530 }
531
b226d99b 532 link_ref(link);
5c1d3fc9
UTL
533 link->addr_messages ++;
534 }
535 }
536
a6cc569e
TG
537 if (link->dhcp_lease) {
538 _cleanup_address_free_ Address *address = NULL;
539 struct in_addr addr;
540 struct in_addr netmask;
541 unsigned prefixlen;
542
543 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
544 if (r < 0) {
545 log_warning_link(link, "DHCP error: no address: %s",
546 strerror(-r));
547 return r;
548 }
549
550 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
551 if (r < 0) {
552 log_warning_link(link, "DHCP error: no netmask: %s",
553 strerror(-r));
554 return r;
555 }
556
557 prefixlen = net_netmask_to_prefixlen(&netmask);
558
559 r = address_new_dynamic(&address);
560 if (r < 0) {
561 log_error_link(link, "Could not allocate address: %s",
562 strerror(-r));
563 return r;
564 }
565
566 address->family = AF_INET;
567 address->in_addr.in = addr;
568 address->prefixlen = prefixlen;
569 address->broadcast.s_addr = addr.s_addr | ~netmask.s_addr;
570
571 r = address_configure(address, link, &address_handler);
f5be5601 572 if (r < 0) {
3333d748
ZJS
573 log_warning_link(link,
574 "could not set addresses: %s", strerror(-r));
f5be5601
TG
575 link_enter_failed(link);
576 return r;
577 }
578
b226d99b 579 link_ref(link);
f5be5601 580 link->addr_messages ++;
f882c247
TG
581 }
582
583 return 0;
584}
585
aba496a5
UTL
586static int address_update_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
587 Link *link = userdata;
588 int r;
589
590 assert(m);
591 assert(link);
592 assert(link->ifname);
593
370e9930 594 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 595 link_unref(link);
aba496a5 596 return 1;
b226d99b 597 }
aba496a5
UTL
598
599 r = sd_rtnl_message_get_errno(m);
600 if (r < 0 && r != -ENOENT)
601 log_struct_link(LOG_WARNING, link,
602 "MESSAGE=%s: could not update address: %s",
603 link->ifname, strerror(-r),
604 "ERRNO=%d", -r,
605 NULL);
606
b226d99b
TG
607 link_unref(link);
608
aba496a5
UTL
609 return 0;
610}
611
ff254138
TG
612static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
613 Link *link = userdata;
614 int r;
615
616 assert(m);
617 assert(link);
618 assert(link->ifname);
619
370e9930 620 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 621 link_unref(link);
ff254138 622 return 1;
b226d99b 623 }
ff254138
TG
624
625 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
626 if (r < 0 && r != -ENOENT)
627 log_struct_link(LOG_WARNING, link,
628 "MESSAGE=%s: could not drop address: %s",
629 link->ifname, strerror(-r),
630 "ERRNO=%d", -r,
631 NULL);
ff254138 632
b226d99b
TG
633 link_unref(link);
634
5c1d3fc9 635 return 0;
ff254138
TG
636}
637
1346b1f0 638static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
b226d99b 639 Link *link = userdata;
1346b1f0
TG
640 int r;
641
b226d99b
TG
642 assert(link);
643
370e9930
TG
644 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
645 link_unref(link);
646 return 1;
647 }
648
1346b1f0
TG
649 r = sd_bus_message_get_errno(m);
650 if (r < 0)
651 log_warning("Could not set hostname: %s", strerror(-r));
652
b226d99b
TG
653 link_unref(link);
654
1346b1f0
TG
655 return 1;
656}
657
b226d99b 658static int link_set_hostname(Link *link, const char *hostname) {
1346b1f0
TG
659 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
660 int r = 0;
661
b226d99b
TG
662 assert(link);
663 assert(link->manager);
1346b1f0
TG
664 assert(hostname);
665
b226d99b 666 log_debug_link(link, "Setting transient hostname: '%s'", hostname);
1346b1f0 667
b226d99b
TG
668 if (!link->manager->bus) { /* TODO: replace by assert when we can rely on kdbus */
669 log_info_link(link, "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
670 return 0;
671 }
672
1346b1f0 673 r = sd_bus_message_new_method_call(
b226d99b 674 link->manager->bus,
151b9b96 675 &m,
1346b1f0
TG
676 "org.freedesktop.hostname1",
677 "/org/freedesktop/hostname1",
678 "org.freedesktop.hostname1",
151b9b96 679 "SetHostname");
1346b1f0
TG
680 if (r < 0)
681 return r;
682
683 r = sd_bus_message_append(m, "sb", hostname, false);
684 if (r < 0)
685 return r;
686
b226d99b 687 r = sd_bus_call_async(link->manager->bus, m, set_hostname_handler, link, 0, NULL);
1346b1f0 688 if (r < 0)
b226d99b
TG
689 log_error_link(link, "Could not set transient hostname: %s", strerror(-r));
690
691 link_ref(link);
1346b1f0
TG
692
693 return r;
694}
695
4f882b2a
TG
696static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
697 Link *link = userdata;
698 int r;
699
700 assert(m);
701 assert(link);
702 assert(link->ifname);
703
370e9930 704 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 705 link_unref(link);
4f882b2a 706 return 1;
b226d99b 707 }
4f882b2a
TG
708
709 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
710 if (r < 0)
711 log_struct_link(LOG_WARNING, link,
712 "MESSAGE=%s: could not set MTU: %s",
713 link->ifname, strerror(-r),
714 "ERRNO=%d", -r,
715 NULL);
4f882b2a 716
b226d99b
TG
717 link_unref(link);
718
4f882b2a
TG
719 return 1;
720}
721
722static int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 723 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
724 int r;
725
726 assert(link);
727 assert(link->manager);
728 assert(link->manager->rtnl);
729
730 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
731
151b9b96
LP
732 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
733 RTM_SETLINK, link->ifindex);
4f882b2a
TG
734 if (r < 0) {
735 log_error_link(link, "Could not allocate RTM_SETLINK message");
736 return r;
737 }
738
739 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
740 if (r < 0) {
741 log_error_link(link, "Could not append MTU: %s", strerror(-r));
742 return r;
743 }
744
745 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL);
746 if (r < 0) {
747 log_error_link(link,
748 "Could not send rtnetlink message: %s", strerror(-r));
749 return r;
750 }
751
b226d99b
TG
752 link_unref(link);
753
4f882b2a
TG
754 return 0;
755}
756
a6cc569e
TG
757static int dhcp_lease_lost(Link *link) {
758 _cleanup_address_free_ Address *address = NULL;
3e790eae
UTL
759 _cleanup_route_free_ Route *route_gw = NULL;
760 _cleanup_route_free_ Route *route = NULL;
a6cc569e
TG
761 struct in_addr addr;
762 struct in_addr netmask;
3e790eae 763 struct in_addr gateway;
a6cc569e 764 unsigned prefixlen;
ff254138
TG
765 int r;
766
767 assert(link);
a6cc569e 768 assert(link->dhcp_lease);
ff254138 769
14efd761
TG
770 log_warning_link(link, "DHCP lease lost");
771
a6cc569e
TG
772 r = address_new_dynamic(&address);
773 if (r >= 0) {
8ddbeaa2 774 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
3e790eae 775 if (r >= 0) {
8ddbeaa2
UTL
776 r = route_new_dynamic(&route_gw);
777 if (r >= 0) {
778 route_gw->family = AF_INET;
779 route_gw->dst_addr.in = gateway;
780 route_gw->dst_prefixlen = 32;
781 route_gw->scope = RT_SCOPE_LINK;
782
783 route_drop(route_gw, link, &route_drop_handler);
b226d99b 784 link_ref(link);
8ddbeaa2 785 }
3e790eae 786
8ddbeaa2
UTL
787 r = route_new_dynamic(&route);
788 if (r >= 0) {
789 route->family = AF_INET;
790 route->in_addr.in = gateway;
3e790eae 791
8ddbeaa2 792 route_drop(route, link, &route_drop_handler);
b226d99b 793 link_ref(link);
8ddbeaa2 794 }
3e790eae
UTL
795 }
796
8ddbeaa2
UTL
797 sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
798 sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
799 prefixlen = net_netmask_to_prefixlen(&netmask);
800
a6cc569e
TG
801 address->family = AF_INET;
802 address->in_addr.in = addr;
803 address->prefixlen = prefixlen;
ff254138 804
5c1d3fc9 805 address_drop(address, link, &address_drop_handler);
b226d99b 806 link_ref(link);
c07aeadf 807 }
eb27aeca 808
c07aeadf
TG
809 if (link->network->dhcp_mtu) {
810 uint16_t mtu;
ff254138 811
a6cc569e 812 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
c07aeadf
TG
813 if (r >= 0 && link->original_mtu != mtu) {
814 r = link_set_mtu(link, link->original_mtu);
815 if (r < 0) {
816 log_warning_link(link, "DHCP error: could not reset MTU");
817 link_enter_failed(link);
818 return r;
819 }
ff254138 820 }
c07aeadf 821 }
ff254138 822
c07aeadf 823 if (link->network->dhcp_hostname) {
216816c6
TG
824 const char *hostname = NULL;
825
826 r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
827 if (r >= 0 && hostname) {
b226d99b 828 r = link_set_hostname(link, "");
216816c6
TG
829 if (r < 0)
830 log_error("Failed to reset transient hostname");
831 }
c07aeadf 832 }
4f882b2a 833
a6cc569e
TG
834 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
835
c07aeadf
TG
836 return 0;
837}
4f882b2a 838
c07aeadf 839static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
a6cc569e 840 sd_dhcp_lease *lease;
c07aeadf
TG
841 struct in_addr address;
842 struct in_addr netmask;
843 struct in_addr gateway;
844 unsigned prefixlen;
c07aeadf
TG
845 struct in_addr *nameservers;
846 size_t nameservers_size;
847 int r;
1346b1f0 848
c07aeadf
TG
849 assert(client);
850 assert(link);
ff254138 851
a6cc569e
TG
852 r = sd_dhcp_client_get_lease(client, &lease);
853 if (r < 0) {
854 log_warning_link(link, "DHCP error: no lease: %s",
855 strerror(-r));
856 return r;
857 }
858
859 r = sd_dhcp_lease_get_address(lease, &address);
ff254138 860 if (r < 0) {
c07aeadf
TG
861 log_warning_link(link, "DHCP error: no address: %s",
862 strerror(-r));
863 return r;
ff254138
TG
864 }
865
a6cc569e 866 r = sd_dhcp_lease_get_netmask(lease, &netmask);
ff254138 867 if (r < 0) {
c07aeadf
TG
868 log_warning_link(link, "DHCP error: no netmask: %s",
869 strerror(-r));
870 return r;
ff254138
TG
871 }
872
377a218f 873 prefixlen = net_netmask_to_prefixlen(&netmask);
ff254138 874
a6cc569e 875 r = sd_dhcp_lease_get_router(lease, &gateway);
8ddbeaa2
UTL
876 if (r < 0 && r != -ENOENT) {
877 log_warning_link(link, "DHCP error: %s", strerror(-r));
c07aeadf 878 return r;
ff254138
TG
879 }
880
8ddbeaa2
UTL
881 if (r >= 0)
882 log_struct_link(LOG_INFO, link,
883 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
884 link->ifname,
885 ADDRESS_FMT_VAL(address),
886 prefixlen,
887 ADDRESS_FMT_VAL(gateway),
888 "ADDRESS=%u.%u.%u.%u",
889 ADDRESS_FMT_VAL(address),
890 "PREFIXLEN=%u",
891 prefixlen,
892 "GATEWAY=%u.%u.%u.%u",
893 ADDRESS_FMT_VAL(gateway),
894 NULL);
895 else
896 log_struct_link(LOG_INFO, link,
897 "MESSAGE=%s: DHCPv4 address %u.%u.%u.%u/%u",
898 link->ifname,
899 ADDRESS_FMT_VAL(address),
900 prefixlen,
901 "ADDRESS=%u.%u.%u.%u",
902 ADDRESS_FMT_VAL(address),
903 "PREFIXLEN=%u",
904 prefixlen,
905 NULL);
c07aeadf 906
d50cf59b
TG
907 link->dhcp_lease = lease;
908
c07aeadf 909 if (link->network->dhcp_dns) {
a6cc569e 910 r = sd_dhcp_lease_get_dns(lease, &nameservers, &nameservers_size);
c07aeadf
TG
911 if (r >= 0) {
912 r = manager_update_resolv_conf(link->manager);
913 if (r < 0)
914 log_error("Failed to update resolv.conf");
ff254138 915 }
c07aeadf 916 }
ff254138 917
c07aeadf
TG
918 if (link->network->dhcp_mtu) {
919 uint16_t mtu;
920
a6cc569e 921 r = sd_dhcp_lease_get_mtu(lease, &mtu);
c07aeadf
TG
922 if (r >= 0) {
923 r = link_set_mtu(link, mtu);
924 if (r < 0)
925 log_error_link(link, "Failed to set MTU "
926 "to %" PRIu16, mtu);
927 }
928 }
ff254138 929
c07aeadf
TG
930 if (link->network->dhcp_hostname) {
931 const char *hostname;
ff254138 932
a6cc569e 933 r = sd_dhcp_lease_get_hostname(lease, &hostname);
c07aeadf 934 if (r >= 0) {
b226d99b 935 r = link_set_hostname(link, hostname);
c07aeadf
TG
936 if (r < 0)
937 log_error("Failed to set transient hostname "
938 "to '%s'", hostname);
3bef724f 939 }
c07aeadf 940 }
3bef724f 941
c07aeadf
TG
942 link_enter_set_addresses(link);
943
944 return 0;
945}
946
947static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
948 Link *link = userdata;
aba496a5 949 int r = 0;
c07aeadf
TG
950
951 assert(link);
952 assert(link->network);
953 assert(link->manager);
954
370e9930 955 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
c07aeadf
TG
956 return;
957
958 switch (event) {
959 case DHCP_EVENT_NO_LEASE:
960 log_debug_link(link, "IP address in use.");
961 break;
962 case DHCP_EVENT_EXPIRED:
963 case DHCP_EVENT_STOP:
964 case DHCP_EVENT_IP_CHANGE:
965 if (link->network->dhcp_critical) {
966 log_error_link(link, "DHCPv4 connection considered system critical, "
967 "ignoring request to reconfigure it.");
968 return;
4f882b2a 969 }
4f882b2a 970
17256461
UTL
971 if (link->dhcp_lease) {
972 r = dhcp_lease_lost(link);
973 if (r < 0) {
974 link_enter_failed(link);
975 return;
976 }
c07aeadf 977 }
1346b1f0 978
c07aeadf
TG
979 if (event == DHCP_EVENT_IP_CHANGE) {
980 r = dhcp_lease_acquired(client, link);
981 if (r < 0) {
982 link_enter_failed(link);
983 return;
984 }
1346b1f0 985 }
1346b1f0 986
5c1d3fc9 987 if (event == DHCP_EVENT_EXPIRED && link->network->ipv4ll) {
aba496a5
UTL
988 if (!sd_ipv4ll_is_running(link->ipv4ll))
989 r = sd_ipv4ll_start(link->ipv4ll);
990 else if (ipv4ll_is_bound(link->ipv4ll))
991 r = ipv4ll_address_update(link, false);
5c1d3fc9
UTL
992 if (r < 0) {
993 link_enter_failed(link);
994 return;
995 }
996 }
997
c07aeadf
TG
998 break;
999 case DHCP_EVENT_IP_ACQUIRE:
1000 r = dhcp_lease_acquired(client, link);
1001 if (r < 0) {
1002 link_enter_failed(link);
1003 return;
1004 }
5c1d3fc9 1005 if (link->ipv4ll) {
aba496a5
UTL
1006 if (ipv4ll_is_bound(link->ipv4ll))
1007 r = ipv4ll_address_update(link, true);
1008 else
1009 r = sd_ipv4ll_stop(link->ipv4ll);
5c1d3fc9
UTL
1010 if (r < 0) {
1011 link_enter_failed(link);
1012 return;
1013 }
1014 }
c07aeadf
TG
1015 break;
1016 default:
1017 if (event < 0)
1018 log_warning_link(link, "DHCP error: %s", strerror(-event));
1019 else
1020 log_warning_link(link, "DHCP unknown event: %d", event);
c07aeadf 1021 break;
ff254138
TG
1022 }
1023
1024 return;
1025}
1026
aba496a5
UTL
1027static int ipv4ll_address_update(Link *link, bool deprecate) {
1028 int r;
1029 struct in_addr addr;
1030
1031 assert(link);
1032
1033 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
1034 if (r >= 0) {
1035 _cleanup_address_free_ Address *address = NULL;
1036
1037 log_debug_link(link, "IPv4 link-local %s %u.%u.%u.%u",
1038 deprecate ? "deprecate" : "approve",
1039 ADDRESS_FMT_VAL(addr));
1040
1041 r = address_new_dynamic(&address);
1042 if (r < 0) {
1043 log_error_link(link, "Could not allocate address: %s", strerror(-r));
1044 return r;
1045 }
1046
1047 address->family = AF_INET;
1048 address->in_addr.in = addr;
1049 address->prefixlen = 16;
1050 address->scope = RT_SCOPE_LINK;
1051 address->cinfo.ifa_prefered = deprecate ? 0 : CACHE_INFO_INFINITY_LIFE_TIME;
1052 address->broadcast.s_addr = address->in_addr.in.s_addr | htonl(0xfffffffflu >> address->prefixlen);
1053
1054 address_update(address, link, &address_update_handler);
b226d99b 1055 link_ref(link);
aba496a5
UTL
1056 }
1057
1058 return 0;
1059
1060}
1061
1062static int ipv4ll_address_lost(Link *link) {
5c1d3fc9
UTL
1063 int r;
1064 struct in_addr addr;
1065
5c1d3fc9
UTL
1066 assert(link);
1067
1068 r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
1069 if (r >= 0) {
1070 _cleanup_address_free_ Address *address = NULL;
1071 _cleanup_route_free_ Route *route = NULL;
1072
1073 log_debug_link(link, "IPv4 link-local release %u.%u.%u.%u",
1074 ADDRESS_FMT_VAL(addr));
1075
1076 r = address_new_dynamic(&address);
1077 if (r < 0) {
1078 log_error_link(link, "Could not allocate address: %s", strerror(-r));
1079 return r;
1080 }
1081
1082 address->family = AF_INET;
1083 address->in_addr.in = addr;
1084 address->prefixlen = 16;
1085 address->scope = RT_SCOPE_LINK;
1086
1087 address_drop(address, link, &address_drop_handler);
b226d99b 1088 link_ref(link);
5c1d3fc9
UTL
1089
1090 r = route_new_dynamic(&route);
1091 if (r < 0) {
1092 log_error_link(link, "Could not allocate route: %s",
1093 strerror(-r));
1094 return r;
1095 }
1096
1097 route->family = AF_INET;
1098 route->scope = RT_SCOPE_LINK;
1099 route->metrics = 99;
1100
1101 route_drop(route, link, &route_drop_handler);
b226d99b 1102 link_ref(link);
5c1d3fc9
UTL
1103 }
1104
1105 return 0;
1106}
1107
aba496a5
UTL
1108static bool ipv4ll_is_bound(sd_ipv4ll *ll) {
1109 int r;
1110 struct in_addr addr;
1111
1112 assert(ll);
1113
1114 r = sd_ipv4ll_get_address(ll, &addr);
1115 if (r < 0)
1116 return false;
1117 return true;
1118}
1119
5c1d3fc9
UTL
1120static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
1121 struct in_addr address;
1122 int r;
1123
1124 assert(ll);
1125 assert(link);
1126
1127 r = sd_ipv4ll_get_address(ll, &address);
1128 if (r < 0)
1129 return r;
1130
1131 log_struct_link(LOG_INFO, link,
1132 "MESSAGE=%s: IPv4 link-local address %u.%u.%u.%u",
1133 link->ifname,
1134 ADDRESS_FMT_VAL(address),
1135 NULL);
1136
1137 link_enter_set_addresses(link);
1138
1139 return 0;
1140}
1141
1142static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
1143 Link *link = userdata;
1144 int r;
1145
1146 assert(link);
1147 assert(link->network);
1148 assert(link->manager);
1149
370e9930
TG
1150 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1151 return;
1152
5c1d3fc9
UTL
1153 switch(event) {
1154 case IPV4LL_EVENT_STOP:
1155 case IPV4LL_EVENT_CONFLICT:
aba496a5 1156 r = ipv4ll_address_lost(link);
5c1d3fc9
UTL
1157 if (r < 0) {
1158 link_enter_failed(link);
1159 return;
1160 }
1161 break;
1162 case IPV4LL_EVENT_BIND:
1163 r = ipv4ll_address_claimed(ll, link);
1164 if (r < 0) {
1165 link_enter_failed(link);
1166 return;
1167 }
1168 break;
1169 default:
1170 if (event < 0)
1171 log_warning_link(link, "IPv4 link-local error: %s", strerror(-event));
1172 else
1173 log_warning_link(link, "IPv4 link-local unknown event: %d", event);
1174 break;
1175 }
1176}
1177
ff254138
TG
1178static int link_acquire_conf(Link *link) {
1179 int r;
1180
1181 assert(link);
1182 assert(link->network);
ff254138
TG
1183 assert(link->manager);
1184 assert(link->manager->event);
1185
5c1d3fc9 1186 if (link->network->ipv4ll) {
eb34d4af 1187 assert(link->ipv4ll);
ff254138 1188
5c1d3fc9
UTL
1189 log_debug_link(link, "acquiring IPv4 link-local address");
1190
1191 r = sd_ipv4ll_start(link->ipv4ll);
124fa2c6
TG
1192 if (r < 0) {
1193 log_warning_link(link, "could not acquire IPv4 "
1194 "link-local address");
ff254138 1195 return r;
124fa2c6 1196 }
5c1d3fc9
UTL
1197 }
1198
1199 if (link->network->dhcp) {
eb34d4af 1200 assert(link->dhcp_client);
ff254138 1201
5c1d3fc9 1202 log_debug_link(link, "acquiring DHCPv4 lease");
ab47d620 1203
5c1d3fc9 1204 r = sd_dhcp_client_start(link->dhcp_client);
124fa2c6
TG
1205 if (r < 0) {
1206 log_warning_link(link, "could not acquire DHCPv4 "
1207 "lease");
5c1d3fc9 1208 return r;
124fa2c6 1209 }
5c1d3fc9 1210 }
ff254138
TG
1211
1212 return 0;
1213}
1214
bbf7c048 1215bool link_has_carrier(unsigned flags, uint8_t operstate) {
deb2e523
TG
1216 /* see Documentation/networking/operstates.txt in the kernel sources */
1217
1218 if (operstate == IF_OPER_UP)
1219 return true;
1220
1221 if (operstate == IF_OPER_UNKNOWN)
1222 /* operstate may not be implemented, so fall back to flags */
1223 if ((flags & IFF_LOWER_UP) && !(flags & IFF_DORMANT))
1224 return true;
1225
1226 return false;
1227}
1228
1e9be60b
TG
1229static int link_update_flags(Link *link, sd_rtnl_message *m) {
1230 unsigned flags, flags_added, flags_removed, generic_flags;
1231 uint8_t operstate;
1232 bool carrier_gained = false, carrier_lost = false;
ff254138
TG
1233 int r;
1234
1235 assert(link);
ff254138 1236
1e9be60b
TG
1237 r = sd_rtnl_message_link_get_flags(m, &flags);
1238 if (r < 0) {
1239 log_warning_link(link, "Could not get link flags");
1240 return r;
1241 }
1242
1243 r = sd_rtnl_message_read_u8(m, IFLA_OPERSTATE, &operstate);
1244 if (r < 0)
1245 /* if we got a message without operstate, take it to mean
1246 the state was unchanged */
1247 operstate = link->operstate;
1248
1249 if ((link->flags == flags) && (link->operstate == operstate))
efbc88b8 1250 return 0;
efbc88b8 1251
ffba6166
TG
1252 flags_added = (link->flags ^ flags) & flags;
1253 flags_removed = (link->flags ^ flags) & link->flags;
c6a1eb79
TG
1254 generic_flags = ~(IFF_UP | IFF_LOWER_UP | IFF_DORMANT | IFF_DEBUG |
1255 IFF_MULTICAST | IFF_BROADCAST | IFF_PROMISC |
d96e629f 1256 IFF_NOARP | IFF_MASTER | IFF_SLAVE | IFF_RUNNING);
c49b33ac 1257
ffba6166 1258 if (flags_added & IFF_UP)
df9aa406 1259 log_debug_link(link, "link is up");
ffba6166 1260 else if (flags_removed & IFF_UP)
df9aa406 1261 log_debug_link(link, "link is down");
ffba6166
TG
1262
1263 if (flags_added & IFF_LOWER_UP)
3379e257 1264 log_debug_link(link, "link is lower up");
ffba6166 1265 else if (flags_removed & IFF_LOWER_UP)
3379e257 1266 log_debug_link(link, "link is lower down");
ffba6166 1267
75ee87c8
TG
1268 if (flags_added & IFF_DORMANT)
1269 log_debug_link(link, "link is dormant");
1270 else if (flags_removed & IFF_DORMANT)
1271 log_debug_link(link, "link is not dormant");
ffba6166 1272
c6a1eb79
TG
1273 if (flags_added & IFF_DEBUG)
1274 log_debug_link(link, "debugging enabled in the kernel");
1275 else if (flags_removed & IFF_DEBUG)
1276 log_debug_link(link, "debugging disabled in the kernel");
1277
1278 if (flags_added & IFF_MULTICAST)
1279 log_debug_link(link, "multicast enabled");
1280 else if (flags_removed & IFF_MULTICAST)
1281 log_debug_link(link, "multicast disabled");
1282
1283 if (flags_added & IFF_BROADCAST)
1284 log_debug_link(link, "broadcast enabled");
1285 else if (flags_removed & IFF_BROADCAST)
1286 log_debug_link(link, "broadcast disabled");
1287
1288 if (flags_added & IFF_PROMISC)
1289 log_debug_link(link, "promiscuous mode enabled");
1290 else if (flags_removed & IFF_PROMISC)
1291 log_debug_link(link, "promiscuous mode disabled");
1292
1293 if (flags_added & IFF_NOARP)
1294 log_debug_link(link, "ARP protocol disabled");
1295 else if (flags_removed & IFF_NOARP)
1296 log_debug_link(link, "ARP protocol enabled");
1297
1298 if (flags_added & IFF_MASTER)
1299 log_debug_link(link, "link is master");
1300 else if (flags_removed & IFF_MASTER)
1301 log_debug_link(link, "link is no longer master");
1302
1303 if (flags_added & IFF_SLAVE)
1304 log_debug_link(link, "link is slave");
1305 else if (flags_removed & IFF_SLAVE)
1306 log_debug_link(link, "link is no longer slave");
1307
069e10a0 1308 /* link flags are currently at most 18 bits, let's default to printing 20 */
505f8da7 1309 if (flags_added & generic_flags)
069e10a0 1310 log_debug_link(link, "unknown link flags gained: %#.5x (ignoring)",
505f8da7
TG
1311 flags_added & generic_flags);
1312
1313 if (flags_removed & generic_flags)
069e10a0 1314 log_debug_link(link, "unknown link flags lost: %#.5x (ignoring)",
75ee87c8 1315 flags_removed & generic_flags);
505f8da7 1316
1e9be60b
TG
1317 carrier_gained = !link_has_carrier(link->flags, link->operstate) &&
1318 link_has_carrier(flags, operstate);
1319 carrier_lost = link_has_carrier(link->flags, link->operstate) &&
1320 !link_has_carrier(flags, operstate);
1321
1322 link->flags = flags;
1323 link->operstate = operstate;
1324
deb2e523
TG
1325 link_save(link);
1326
99b4cc3e
TG
1327 if (link->state == LINK_STATE_FAILED ||
1328 link->state == LINK_STATE_UNMANAGED)
1329 return 0;
1330
7cc832b9
TG
1331 if (carrier_gained) {
1332 log_info_link(link, "gained carrier");
ffba6166 1333
1e9be60b 1334 if (link->network) {
ffba6166
TG
1335 r = link_acquire_conf(link);
1336 if (r < 0) {
ffba6166
TG
1337 link_enter_failed(link);
1338 return r;
ff254138 1339 }
ffba6166 1340 }
7cc832b9
TG
1341 } else if (carrier_lost) {
1342 log_info_link(link, "lost carrier");
efbc88b8 1343
1e9be60b
TG
1344 r = link_stop_clients(link);
1345 if (r < 0) {
1346 link_enter_failed(link);
1347 return r;
ff254138
TG
1348 }
1349 }
1350
ff254138
TG
1351 return 0;
1352}
1353
dd3efc09
TG
1354static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1355 Link *link = userdata;
1356 int r;
1357
1746cf2a
TG
1358 assert(link);
1359
370e9930 1360 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 1361 link_unref(link);
1746cf2a 1362 return 1;
b226d99b 1363 }
1746cf2a 1364
dd3efc09 1365 r = sd_rtnl_message_get_errno(m);
45ad2c13 1366 if (r < 0) {
9b86b393
TG
1367 /* we warn but don't fail the link, as it may
1368 be brought up later */
76800848 1369 log_struct_link(LOG_WARNING, link,
c9ccc19f
TG
1370 "MESSAGE=%s: could not bring up interface: %s",
1371 link->ifname, strerror(-r),
1372 "ERRNO=%d", -r,
1373 NULL);
45ad2c13
TG
1374 }
1375
b226d99b
TG
1376 link_unref(link);
1377
f882c247
TG
1378 return 1;
1379}
1380
1381static int link_up(Link *link) {
cf6a8911 1382 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1383 int r;
1384
f882c247
TG
1385 assert(link);
1386 assert(link->manager);
1387 assert(link->manager->rtnl);
1388
39032b87 1389 log_debug_link(link, "bringing link up");
449f7554 1390
151b9b96
LP
1391 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1392 RTM_SETLINK, link->ifindex);
f579559b 1393 if (r < 0) {
39032b87 1394 log_error_link(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1395 return r;
1396 }
1397
5d4795f3 1398 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1399 if (r < 0) {
3333d748 1400 log_error_link(link, "Could not set link flags: %s", strerror(-r));
fc25d7f8
TG
1401 return r;
1402 }
1403
dd3efc09 1404 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
f579559b 1405 if (r < 0) {
3333d748
ZJS
1406 log_error_link(link,
1407 "Could not send rtnetlink message: %s", strerror(-r));
f579559b
TG
1408 return r;
1409 }
1410
b226d99b
TG
1411 link_ref(link);
1412
f882c247
TG
1413 return 0;
1414}
1415
52433f6b 1416static int link_enslaved(Link *link) {
f882c247
TG
1417 int r;
1418
ef1ba606 1419 assert(link);
52433f6b 1420 assert(link->state == LINK_STATE_ENSLAVING);
f5be5601 1421 assert(link->network);
dd3efc09 1422
505f8da7
TG
1423 if (!(link->flags & IFF_UP)) {
1424 r = link_up(link);
1425 if (r < 0) {
1426 link_enter_failed(link);
1427 return r;
1428 }
ef1ba606 1429 }
f882c247 1430
5c1d3fc9 1431 if (!link->network->dhcp && !link->network->ipv4ll)
1746cf2a 1432 return link_enter_set_addresses(link);
ef1ba606
TG
1433
1434 return 0;
02b59d57
TG
1435}
1436
52433f6b 1437static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
02b59d57
TG
1438 Link *link = userdata;
1439 int r;
1440
1746cf2a 1441 assert(link);
370e9930
TG
1442 assert(IN_SET(link->state, LINK_STATE_ENSLAVING, LINK_STATE_FAILED,
1443 LINK_STATE_LINGER));
ef1ba606 1444 assert(link->network);
02b59d57 1445
52433f6b
TG
1446 link->enslaving --;
1447
370e9930 1448 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) {
b226d99b 1449 link_unref(link);
02b59d57 1450 return 1;
b226d99b 1451 }
02b59d57
TG
1452
1453 r = sd_rtnl_message_get_errno(m);
ef1ba606 1454 if (r < 0) {
c9ccc19f
TG
1455 log_struct_link(LOG_ERR, link,
1456 "MESSAGE=%s: could not enslave: %s",
1457 link->ifname, strerror(-r),
1458 "ERRNO=%d", -r,
1459 NULL);
ef1ba606 1460 link_enter_failed(link);
b226d99b 1461 link_unref(link);
ef1ba606 1462 return 1;
3333d748 1463 }
02b59d57 1464
52433f6b 1465 log_debug_link(link, "enslaved");
ab47d620 1466
52433f6b
TG
1467 if (link->enslaving == 0)
1468 link_enslaved(link);
02b59d57 1469
b226d99b
TG
1470 link_unref(link);
1471
02b59d57
TG
1472 return 1;
1473}
1474
52433f6b 1475static int link_enter_enslave(Link *link) {
fe6b2d55 1476 NetDev *vlan, *macvlan;
672682a6 1477 Iterator i;
02b59d57
TG
1478 int r;
1479
1480 assert(link);
1481 assert(link->network);
505f8da7 1482 assert(link->state == LINK_STATE_INITIALIZING);
02b59d57 1483
52433f6b 1484 link->state = LINK_STATE_ENSLAVING;
02b59d57 1485
fe8db0c5
TG
1486 link_save(link);
1487
63ffa720 1488 if (!link->network->bridge && !link->network->bond &&
fe6b2d55
TG
1489 hashmap_isempty(link->network->vlans) &&
1490 hashmap_isempty(link->network->macvlans))
52433f6b 1491 return link_enslaved(link);
02b59d57 1492
52433f6b
TG
1493 if (link->network->bridge) {
1494 log_struct_link(LOG_DEBUG, link,
1495 "MESSAGE=%s: enslaving by '%s'",
c9ccc19f 1496 link->ifname, link->network->bridge->name,
52433f6b
TG
1497 NETDEV(link->network->bridge),
1498 NULL);
449f7554 1499
52433f6b
TG
1500 r = netdev_enslave(link->network->bridge, link, &enslave_handler);
1501 if (r < 0) {
1502 log_struct_link(LOG_WARNING, link,
1503 "MESSAGE=%s: could not enslave by '%s': %s",
c9ccc19f 1504 link->ifname, link->network->bridge->name, strerror(-r),
52433f6b
TG
1505 NETDEV(link->network->bridge),
1506 NULL);
1507 link_enter_failed(link);
1508 return r;
1509 }
1510
b226d99b 1511 link_ref(link);
0ad6148e
MO
1512 link->enslaving ++;
1513 }
1514
1515 if (link->network->bond) {
1516 log_struct_link(LOG_DEBUG, link,
1517 "MESSAGE=%s: enslaving by '%s'",
1518 link->ifname, link->network->bond->name,
1519 NETDEV(link->network->bond),
1520 NULL);
1521
1522 r = netdev_enslave(link->network->bond, link, &enslave_handler);
1523 if (r < 0) {
1524 log_struct_link(LOG_WARNING, link,
1525 "MESSAGE=%s: could not enslave by '%s': %s",
1526 link->ifname, link->network->bond->name, strerror(-r),
1527 NETDEV(link->network->bond),
1528 NULL);
1529 link_enter_failed(link);
1530 return r;
1531 }
1532
b226d99b 1533 link_ref(link);
52433f6b
TG
1534 link->enslaving ++;
1535 }
1536
672682a6 1537 HASHMAP_FOREACH(vlan, link->network->vlans, i) {
52433f6b
TG
1538 log_struct_link(LOG_DEBUG, link,
1539 "MESSAGE=%s: enslaving by '%s'",
672682a6 1540 link->ifname, vlan->name, NETDEV(vlan), NULL);
52433f6b 1541
672682a6 1542 r = netdev_enslave(vlan, link, &enslave_handler);
52433f6b
TG
1543 if (r < 0) {
1544 log_struct_link(LOG_WARNING, link,
1545 "MESSAGE=%s: could not enslave by '%s': %s",
672682a6
TG
1546 link->ifname, vlan->name, strerror(-r),
1547 NETDEV(vlan), NULL);
52433f6b
TG
1548 link_enter_failed(link);
1549 return r;
1550 }
1551
b226d99b 1552 link_ref(link);
52433f6b 1553 link->enslaving ++;
ef1ba606
TG
1554 }
1555
fe6b2d55
TG
1556 HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
1557 log_struct_link(LOG_DEBUG, link,
1558 "MESSAGE=%s: enslaving by '%s'",
1559 link->ifname, macvlan->name, NETDEV(macvlan), NULL);
1560
1561 r = netdev_enslave(macvlan, link, &enslave_handler);
1562 if (r < 0) {
1563 log_struct_link(LOG_WARNING, link,
1564 "MESSAGE=%s: could not enslave by '%s': %s",
1565 link->ifname, macvlan->name, strerror(-r),
1566 NETDEV(macvlan), NULL);
1567 link_enter_failed(link);
1568 return r;
1569 }
1570
b226d99b 1571 link_ref(link);
fe6b2d55
TG
1572 link->enslaving ++;
1573 }
1574
ef1ba606
TG
1575 return 0;
1576}
1577
a748b692 1578static int link_configure(Link *link) {
02b59d57
TG
1579 int r;
1580
ef1ba606 1581 assert(link);
505f8da7 1582 assert(link->state == LINK_STATE_INITIALIZING);
a748b692 1583
eb34d4af 1584 if (link->network->ipv4ll) {
b5db00e5 1585 uint8_t seed[8];
45ad2c13 1586
eb34d4af
TG
1587 r = sd_ipv4ll_new(&link->ipv4ll);
1588 if (r < 0)
1589 return r;
1590
505f8da7
TG
1591 if (link->udev_device) {
1592 r = net_get_unique_predictable_data(link->udev_device, seed);
1593 if (r >= 0) {
1594 r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
1595 if (r < 0)
1596 return r;
1597 }
b5db00e5
UTL
1598 }
1599
eb34d4af
TG
1600 r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0);
1601 if (r < 0)
1602 return r;
1603
4bb40e81
TG
1604 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1605 if (r < 0)
1606 return r;
1607
eb34d4af
TG
1608 r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
1609 if (r < 0)
1610 return r;
1611
1612 r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link);
1613 if (r < 0)
1614 return r;
1615 }
1616
1617 if (link->network->dhcp) {
1618 r = sd_dhcp_client_new(&link->dhcp_client);
1619 if (r < 0)
1620 return r;
1621
1622 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
1623 if (r < 0)
1624 return r;
1625
4bb40e81
TG
1626 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1627 if (r < 0)
1628 return r;
1629
eb34d4af
TG
1630 r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
1631 if (r < 0)
1632 return r;
1633
1634 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp_handler, link);
1635 if (r < 0)
1636 return r;
1637
1638 if (link->network->dhcp_mtu) {
1639 r = sd_dhcp_client_set_request_option(link->dhcp_client, 26);
1640 if (r < 0)
1641 return r;
1642 }
1643 }
1644
deb2e523 1645 if (link_has_carrier(link->flags, link->operstate)) {
1e9be60b
TG
1646 r = link_acquire_conf(link);
1647 if (r < 0)
1648 return r;
cc544d5f 1649 }
1e9be60b 1650
505f8da7
TG
1651 return link_enter_enslave(link);
1652}
1653
1654int link_initialized(Link *link, struct udev_device *device) {
1655 Network *network;
505f8da7
TG
1656 int r;
1657
1658 assert(link);
1659 assert(link->ifname);
1660 assert(link->manager);
1661
1662 if (link->state != LINK_STATE_INITIALIZING)
1663 return 0;
1664
1665 if (device)
1666 link->udev_device = udev_device_ref(device);
1667
1668 log_debug_link(link, "link initialized");
1669
1670 r = network_get(link->manager, device, link->ifname, &link->mac, &network);
57bd6899
TG
1671 if (r == -ENOENT) {
1672 link_enter_unmanaged(link);
1673 return 0;
1674 } else if (r < 0)
1675 return r;
505f8da7
TG
1676
1677 r = network_apply(link->manager, network, link);
1678 if (r < 0)
1679 return r;
1680
a748b692
TG
1681 r = link_configure(link);
1682 if (r < 0)
1683 return r;
1684
505f8da7
TG
1685 return 0;
1686}
1687
1688int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1689 Link *link;
1690 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1691 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1692 int r;
1693
1694 assert(m);
1695 assert(message);
1696 assert(ret);
1697
1698 r = link_new(m, message, ret);
1699 if (r < 0)
1700 return r;
1701
1702 link = *ret;
1703
df9aa406 1704 log_debug_link(link, "link added");
505f8da7
TG
1705
1706 if (detect_container(NULL) <= 0) {
1707 /* not in a container, udev will be around */
1708 sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
1709 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1710 if (!device) {
1711 log_warning_link(link, "could not find udev device");
1712 return -errno;
1713 }
1714
1715 if (udev_device_get_is_initialized(device) <= 0)
1716 /* not yet ready */
1717 return 0;
1718 }
1719
1720 r = link_initialized(link, device);
1721 if (r < 0)
1722 return r;
1723
a748b692
TG
1724 return 0;
1725}
1726
22936833 1727int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1728 struct ether_addr mac;
b8941f74 1729 char *ifname;
22936833
TG
1730 int r;
1731
dd3efc09 1732 assert(link);
b8941f74 1733 assert(link->ifname);
22936833
TG
1734 assert(m);
1735
b8941f74
TG
1736 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1737 if (r >= 0 && !streq(ifname, link->ifname)) {
1738 log_info_link(link, "renamed to %s", ifname);
1739
1740 free(link->ifname);
1741 link->ifname = strdup(ifname);
1742 if (!link->ifname)
1743 return -ENOMEM;
1744 }
1745
505f8da7 1746 if (!link->original_mtu) {
9842de0d
TG
1747 r = sd_rtnl_message_read_u16(m, IFLA_MTU, &link->original_mtu);
1748 if (r >= 0)
1749 log_debug_link(link, "saved original MTU: %"
1750 PRIu16, link->original_mtu);
1751 }
69629de9 1752
e9189a1f
TG
1753 /* The kernel may broadcast NEWLINK messages without the MAC address
1754 set, simply ignore them. */
c49b33ac 1755 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1756 if (r >= 0) {
20861203 1757 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN)) {
c49b33ac 1758
20861203 1759 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
c49b33ac 1760
20861203
TG
1761 log_debug_link(link, "MAC address: "
1762 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1763 mac.ether_addr_octet[0],
1764 mac.ether_addr_octet[1],
1765 mac.ether_addr_octet[2],
1766 mac.ether_addr_octet[3],
1767 mac.ether_addr_octet[4],
1768 mac.ether_addr_octet[5]);
c49b33ac 1769
20861203
TG
1770 if (link->ipv4ll) {
1771 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1772 if (r < 0) {
1773 log_warning_link(link, "Could not update MAC "
1774 "address in IPv4LL client: %s",
1775 strerror(-r));
1776 return r;
1777 }
c49b33ac 1778 }
c49b33ac 1779
20861203
TG
1780 if (link->dhcp_client) {
1781 r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
1782 if (r < 0) {
1783 log_warning_link(link, "Could not update MAC "
1784 "address in DHCP client: %s",
1785 strerror(-r));
1786 return r;
1787 }
c49b33ac
TG
1788 }
1789 }
4f882b2a
TG
1790 }
1791
1e9be60b 1792 return link_update_flags(link, m);
dd3efc09 1793}
fe8db0c5
TG
1794
1795int link_save(Link *link) {
68a8723c 1796 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1797 _cleanup_fclose_ FILE *f = NULL;
deb2e523 1798 const char *admin_state, *oper_state = "unknown";
fe8db0c5
TG
1799 int r;
1800
1801 assert(link);
1802 assert(link->state_file);
68a8723c 1803 assert(link->lease_file);
bbf7c048
TG
1804 assert(link->manager);
1805
1806 r = manager_save(link->manager);
1807 if (r < 0)
1808 return r;
fe8db0c5 1809
370e9930
TG
1810 if (link->state == LINK_STATE_LINGER) {
1811 unlink(link->state_file);
1812 return 0;
1813 }
1814
deb2e523
TG
1815 admin_state = link_state_to_string(link->state);
1816 assert(admin_state);
1817
75adc218 1818 if (link->operstate == IF_OPER_DORMANT)
deb2e523
TG
1819 oper_state = "dormant";
1820 else if (link_has_carrier(link->flags, link->operstate))
1821 oper_state = "carrier";
1822
fe8db0c5
TG
1823 r = fopen_temporary(link->state_file, &f, &temp_path);
1824 if (r < 0)
1825 goto finish;
1826
1827 fchmod(fileno(f), 0644);
1828
1829 fprintf(f,
1830 "# This is private data. Do not parse.\n"
deb2e523
TG
1831 "ADMIN_STATE=%s\n"
1832 "OPER_STATE=%s\n"
1833 "FLAGS=%u\n",
1834 admin_state, oper_state, link->flags);
fe8db0c5
TG
1835
1836 if (link->dhcp_lease) {
68a8723c 1837 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5
TG
1838 if (r < 0)
1839 goto finish;
1840
68a8723c 1841 fprintf(f, "DHCP_LEASE=%s\n", link->lease_file);
deb2e523 1842 } else
68a8723c 1843 unlink(link->lease_file);
fe8db0c5
TG
1844
1845 fflush(f);
1846
1847 if (ferror(f) || rename(temp_path, link->state_file) < 0) {
1848 r = -errno;
1849 unlink(link->state_file);
1850 unlink(temp_path);
1851 }
1852
1853finish:
1854 if (r < 0)
bbf7c048 1855 log_error("Failed to save link data to %s: %s", link->state_file, strerror(-r));
fe8db0c5
TG
1856
1857 return r;
1858}
1859
1860static const char* const link_state_table[_LINK_STATE_MAX] = {
deb2e523 1861 [LINK_STATE_INITIALIZING] = "initializing",
fe8db0c5
TG
1862 [LINK_STATE_ENSLAVING] = "configuring",
1863 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1864 [LINK_STATE_SETTING_ROUTES] = "configuring",
1865 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 1866 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 1867 [LINK_STATE_FAILED] = "failed",
370e9930 1868 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
1869};
1870
1871DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);