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