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