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