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