]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link.c
socket: add support for TCP fast Open
[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
383 link_enter_configured(link);
384
385 return;
386}
387
f882c247 388static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 389 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
390 int r;
391
3c9b8860 392 assert(link->link_messages > 0);
370e9930
TG
393 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
394 LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED,
395 LINK_STATE_LINGER));
f882c247 396
3c9b8860 397 link->link_messages --;
f882c247 398
77a008c0 399 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
400 return 1;
401
402 r = sd_rtnl_message_get_errno(m);
c166a070 403 if (r < 0 && r != -EEXIST)
c9ccc19f 404 log_struct_link(LOG_WARNING, link,
97578344 405 "MESSAGE=%-*s: could not set route: %s",
987efa17 406 IFNAMSIZ,
c9ccc19f
TG
407 link->ifname, strerror(-r),
408 "ERRNO=%d", -r,
409 NULL);
f882c247 410
3c9b8860 411 if (link->link_messages == 0) {
39032b87 412 log_debug_link(link, "routes set");
3c9b8860
TG
413 link->static_configured = true;
414 link_client_handler(link);
dd3efc09 415 }
f882c247
TG
416
417 return 1;
418}
419
420static int link_enter_set_routes(Link *link) {
a6cc569e 421 Route *rt;
f882c247
TG
422 int r;
423
424 assert(link);
425 assert(link->network);
ef1ba606 426 assert(link->state == LINK_STATE_SETTING_ADDRESSES);
f882c247 427
ef1ba606 428 link->state = LINK_STATE_SETTING_ROUTES;
f882c247 429
3d3d4255 430 LIST_FOREACH(routes, rt, link->network->static_routes) {
a6cc569e 431 r = route_configure(rt, link, &route_handler);
dd3efc09 432 if (r < 0) {
3333d748 433 log_warning_link(link,
3c9b8860 434 "could not set routes: %s",
b1666580 435 strerror(-r));
3c9b8860 436 link_enter_failed(link);
a6cc569e
TG
437 return r;
438 }
439
3c9b8860 440 link->link_messages ++;
8ddbeaa2 441 }
f5be5601 442
3c9b8860
TG
443 if (link->link_messages == 0) {
444 link->static_configured = true;
445 link_client_handler(link);
431ca2ce
TG
446 } else
447 log_debug_link(link, "setting routes");
f882c247
TG
448
449 return 0;
450}
451
b22d8a00 452int link_route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 453 _cleanup_link_unref_ Link *link = userdata;
5c1d3fc9
UTL
454 int r;
455
456 assert(m);
457 assert(link);
458 assert(link->ifname);
459
5da8149f 460 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
5c1d3fc9
UTL
461 return 1;
462
463 r = sd_rtnl_message_get_errno(m);
b90b025a 464 if (r < 0 && r != -ESRCH)
5c1d3fc9 465 log_struct_link(LOG_WARNING, link,
97578344 466 "MESSAGE=%-*s: could not drop route: %s",
987efa17 467 IFNAMSIZ,
5c1d3fc9
UTL
468 link->ifname, strerror(-r),
469 "ERRNO=%d", -r,
470 NULL);
471
5bdd314c 472 return 1;
5c1d3fc9
UTL
473}
474
b22d8a00 475int link_get_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
4958aee4
TG
476 _cleanup_link_unref_ Link *link = userdata;
477 int r;
478
479 assert(rtnl);
480 assert(m);
481 assert(link);
482 assert(link->manager);
483
484 for (; m; m = sd_rtnl_message_next(m)) {
485 r = sd_rtnl_message_get_errno(m);
486 if (r < 0) {
3c9b8860
TG
487 log_debug_link(link, "getting address failed: %s",
488 strerror(-r));
4958aee4
TG
489 continue;
490 }
491
492 r = link_rtnl_process_address(rtnl, m, link->manager);
493 if (r < 0)
3c9b8860
TG
494 log_warning_link(link, "could not process address: %s",
495 strerror(-r));
4958aee4
TG
496 }
497
498 return 1;
499}
500
f882c247 501static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 502 _cleanup_link_unref_ Link *link = userdata;
f882c247
TG
503 int r;
504
4958aee4 505 assert(rtnl);
f5be5601
TG
506 assert(m);
507 assert(link);
508 assert(link->ifname);
3c9b8860 509 assert(link->link_messages > 0);
370e9930
TG
510 assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES,
511 LINK_STATE_FAILED, LINK_STATE_LINGER));
f882c247 512
3c9b8860 513 link->link_messages --;
f882c247 514
5da8149f 515 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
f882c247
TG
516 return 1;
517
518 r = sd_rtnl_message_get_errno(m);
c166a070 519 if (r < 0 && r != -EEXIST)
c9ccc19f 520 log_struct_link(LOG_WARNING, link,
97578344 521 "MESSAGE=%-*s: could not set address: %s",
987efa17 522 IFNAMSIZ,
3333d748
ZJS
523 link->ifname, strerror(-r),
524 "ERRNO=%d", -r,
525 NULL);
5bdd314c 526 else if (r >= 0) {
4958aee4
TG
527 /* calling handler directly so take a ref */
528 link_ref(link);
529 link_get_address_handler(rtnl, m, link);
530 }
f882c247 531
3c9b8860 532 if (link->link_messages == 0) {
39032b87 533 log_debug_link(link, "addresses set");
ef1ba606 534 link_enter_set_routes(link);
dd3efc09 535 }
f882c247
TG
536
537 return 1;
538}
539
540static int link_enter_set_addresses(Link *link) {
a6cc569e 541 Address *ad;
f882c247
TG
542 int r;
543
544 assert(link);
545 assert(link->network);
f5be5601 546 assert(link->state != _LINK_STATE_INVALID);
f882c247 547
ef1ba606 548 link->state = LINK_STATE_SETTING_ADDRESSES;
f882c247 549
3d3d4255 550 LIST_FOREACH(addresses, ad, link->network->static_addresses) {
a6cc569e 551 r = address_configure(ad, link, &address_handler);
dd3efc09 552 if (r < 0) {
3333d748 553 log_warning_link(link,
3c9b8860 554 "could not set addresses: %s",
a6cc569e 555 strerror(-r));
f5be5601
TG
556 link_enter_failed(link);
557 return r;
558 }
559
3c9b8860 560 link->link_messages ++;
f882c247
TG
561 }
562
3c9b8860 563 if (link->link_messages == 0) {
431ca2ce
TG
564 link_enter_set_routes(link);
565 } else
566 log_debug_link(link, "setting addresses");
567
f882c247
TG
568 return 0;
569}
570
b22d8a00 571int link_address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 572 _cleanup_link_unref_ Link *link = userdata;
ff254138
TG
573 int r;
574
575 assert(m);
576 assert(link);
577 assert(link->ifname);
578
5da8149f 579 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
ff254138
TG
580 return 1;
581
582 r = sd_rtnl_message_get_errno(m);
b90b025a 583 if (r < 0 && r != -EADDRNOTAVAIL)
c9ccc19f 584 log_struct_link(LOG_WARNING, link,
97578344 585 "MESSAGE=%-*s: could not drop address: %s",
987efa17 586 IFNAMSIZ,
c9ccc19f
TG
587 link->ifname, strerror(-r),
588 "ERRNO=%d", -r,
589 NULL);
ff254138 590
5bdd314c 591 return 1;
ff254138
TG
592}
593
3c9b8860
TG
594static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata,
595 sd_bus_error *ret_error) {
5da8149f 596 _cleanup_link_unref_ Link *link = userdata;
1346b1f0
TG
597 int r;
598
b226d99b
TG
599 assert(link);
600
5da8149f 601 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
370e9930 602 return 1;
370e9930 603
1346b1f0
TG
604 r = sd_bus_message_get_errno(m);
605 if (r < 0)
70b34f5d
MM
606 r = -r;
607 if (r > 0)
3c9b8860
TG
608 log_warning_link(link, "Could not set hostname: %s",
609 strerror(r));
1346b1f0
TG
610
611 return 1;
612}
613
3c9b8860 614int link_set_hostname(Link *link, const char *hostname) {
1346b1f0
TG
615 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
616 int r = 0;
617
b226d99b
TG
618 assert(link);
619 assert(link->manager);
1346b1f0
TG
620 assert(hostname);
621
b226d99b 622 log_debug_link(link, "Setting transient hostname: '%s'", hostname);
1346b1f0 623
3c9b8860
TG
624 if (!link->manager->bus) {
625 /* TODO: replace by assert when we can rely on kdbus */
626 log_info_link(link,
627 "Not connected to system bus, ignoring transient hostname.");
bcbca829
TG
628 return 0;
629 }
630
1346b1f0 631 r = sd_bus_message_new_method_call(
b226d99b 632 link->manager->bus,
151b9b96 633 &m,
1346b1f0
TG
634 "org.freedesktop.hostname1",
635 "/org/freedesktop/hostname1",
636 "org.freedesktop.hostname1",
151b9b96 637 "SetHostname");
1346b1f0
TG
638 if (r < 0)
639 return r;
640
641 r = sd_bus_message_append(m, "sb", hostname, false);
642 if (r < 0)
643 return r;
644
3c9b8860
TG
645 r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler,
646 link, 0);
5da8149f 647 if (r < 0) {
3c9b8860
TG
648 log_error_link(link, "Could not set transient hostname: %s",
649 strerror(-r));
5da8149f
TG
650 return r;
651 }
b226d99b
TG
652
653 link_ref(link);
1346b1f0 654
5da8149f 655 return 0;
1346b1f0
TG
656}
657
4f882b2a 658static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 659 _cleanup_link_unref_ Link *link = userdata;
4f882b2a
TG
660 int r;
661
662 assert(m);
663 assert(link);
664 assert(link->ifname);
665
5da8149f 666 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
4f882b2a
TG
667 return 1;
668
669 r = sd_rtnl_message_get_errno(m);
c9ccc19f
TG
670 if (r < 0)
671 log_struct_link(LOG_WARNING, link,
97578344
TG
672 "MESSAGE=%-*s: could not set MTU: %s",
673 IFNAMSIZ, link->ifname, strerror(-r),
c9ccc19f
TG
674 "ERRNO=%d", -r,
675 NULL);
4f882b2a
TG
676
677 return 1;
678}
679
3c9b8860 680int link_set_mtu(Link *link, uint32_t mtu) {
cf6a8911 681 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
4f882b2a
TG
682 int r;
683
684 assert(link);
685 assert(link->manager);
686 assert(link->manager->rtnl);
687
688 log_debug_link(link, "setting MTU: %" PRIu32, mtu);
689
151b9b96
LP
690 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
691 RTM_SETLINK, link->ifindex);
4f882b2a
TG
692 if (r < 0) {
693 log_error_link(link, "Could not allocate RTM_SETLINK message");
694 return r;
695 }
696
697 r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu);
698 if (r < 0) {
699 log_error_link(link, "Could not append MTU: %s", strerror(-r));
700 return r;
701 }
702
3c9b8860
TG
703 r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link,
704 0, NULL);
4f882b2a
TG
705 if (r < 0) {
706 log_error_link(link,
3c9b8860
TG
707 "Could not send rtnetlink message: %s",
708 strerror(-r));
4f882b2a
TG
709 return r;
710 }
711
ae941762 712 link_ref(link);
b226d99b 713
4f882b2a
TG
714 return 0;
715}
716
4138fb2c
PF
717static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
718 Link *link = userdata;
719
720 assert(link);
721 assert(link->network);
722 assert(link->manager);
723
724 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
725 return;
726
727 switch(event) {
728 case DHCP6_EVENT_STOP:
729 case DHCP6_EVENT_RESEND_EXPIRE:
730 case DHCP6_EVENT_RETRANS_MAX:
731 case DHCP6_EVENT_IP_ACQUIRE:
732 log_debug_link(link, "DHCPv6 event %d", event);
733
734 break;
735
736 default:
737 if (event < 0)
738 log_warning_link(link, "DHCPv6 error: %s",
739 strerror(-event));
740 else
741 log_warning_link(link, "DHCPv6 unknown event: %d",
742 event);
743 return;
744 }
745}
746
747static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
748 Link *link = userdata;
749 int r;
750
751 assert(link);
752 assert(link->network);
753 assert(link->manager);
754
755 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
756 return;
757
758 switch(event) {
759 case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
760 case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
761 return;
762
763 case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
764 case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
765 break;
766
767 default:
768 if (event < 0)
769 log_warning_link(link, "ICMPv6 error: %s",
770 strerror(-event));
771 else
772 log_warning_link(link, "ICMPv6 unknown event: %d",
773 event);
774
775 return;
776 }
777
778 if (link->dhcp6_client)
779 return;
780
781 r = sd_dhcp6_client_new(&link->dhcp6_client);
782 if (r < 0)
783 return;
784
785 r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
786 if (r < 0) {
787 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
788 return;
789 }
790
791 r = sd_dhcp6_client_set_mac(link->dhcp6_client, &link->mac);
792 if (r < 0) {
793 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
794 return;
795 }
796
797 r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
798 if (r < 0) {
799 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
800 return;
801 }
802
803 r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
804 link);
805 if (r < 0) {
806 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
807 return;
808 }
809
810 r = sd_dhcp6_client_start(link->dhcp6_client);
811 if (r < 0)
812 link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
813}
814
ff254138
TG
815static int link_acquire_conf(Link *link) {
816 int r;
817
818 assert(link);
819 assert(link->network);
ff254138
TG
820 assert(link->manager);
821 assert(link->manager->event);
822
5c1d3fc9 823 if (link->network->ipv4ll) {
eb34d4af 824 assert(link->ipv4ll);
ff254138 825
5c1d3fc9
UTL
826 log_debug_link(link, "acquiring IPv4 link-local address");
827
828 r = sd_ipv4ll_start(link->ipv4ll);
124fa2c6
TG
829 if (r < 0) {
830 log_warning_link(link, "could not acquire IPv4 "
831 "link-local address");
ff254138 832 return r;
124fa2c6 833 }
5c1d3fc9
UTL
834 }
835
ed942a9e 836 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V4)) {
eb34d4af 837 assert(link->dhcp_client);
ff254138 838
5c1d3fc9 839 log_debug_link(link, "acquiring DHCPv4 lease");
ab47d620 840
5c1d3fc9 841 r = sd_dhcp_client_start(link->dhcp_client);
124fa2c6
TG
842 if (r < 0) {
843 log_warning_link(link, "could not acquire DHCPv4 "
844 "lease");
5c1d3fc9 845 return r;
124fa2c6 846 }
5c1d3fc9 847 }
ff254138 848
ed942a9e 849 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V6)) {
4138fb2c
PF
850 assert(link->icmp6_router_discovery);
851
852 log_debug_link(link, "discovering IPv6 routers");
853
854 r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery);
855 if (r < 0) {
3c9b8860
TG
856 log_warning_link(link,
857 "could not start IPv6 router discovery");
4138fb2c
PF
858 return r;
859 }
860 }
861
ff254138
TG
862 return 0;
863}
864
bbf7c048 865bool link_has_carrier(unsigned flags, uint8_t operstate) {
deb2e523
TG
866 /* see Documentation/networking/operstates.txt in the kernel sources */
867
868 if (operstate == IF_OPER_UP)
869 return true;
870
871 if (operstate == IF_OPER_UNKNOWN)
872 /* operstate may not be implemented, so fall back to flags */
873 if ((flags & IFF_LOWER_UP) && !(flags & IFF_DORMANT))
874 return true;
875
876 return false;
877}
878
389cc5f7
TG
879#define FLAG_STRING(string, flag, old, new) \
880 (((old ^ new) & flag) \
881 ? ((old & flag) ? (" -" string) : (" +" string)) \
882 : "")
883
1e9be60b 884static int link_update_flags(Link *link, sd_rtnl_message *m) {
389cc5f7 885 unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags;
1e9be60b
TG
886 uint8_t operstate;
887 bool carrier_gained = false, carrier_lost = false;
ff254138
TG
888 int r;
889
890 assert(link);
ff254138 891
1e9be60b
TG
892 r = sd_rtnl_message_link_get_flags(m, &flags);
893 if (r < 0) {
894 log_warning_link(link, "Could not get link flags");
895 return r;
896 }
897
898 r = sd_rtnl_message_read_u8(m, IFLA_OPERSTATE, &operstate);
899 if (r < 0)
900 /* if we got a message without operstate, take it to mean
901 the state was unchanged */
e375dcde 902 operstate = link->kernel_operstate;
1e9be60b 903
e375dcde 904 if ((link->flags == flags) && (link->kernel_operstate == operstate))
efbc88b8 905 return 0;
efbc88b8 906
389cc5f7
TG
907 if (link->flags != flags) {
908 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",
909 FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags),
910 FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags),
911 FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags),
912 FLAG_STRING("UP", IFF_UP, link->flags, flags),
913 FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags),
914 FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags),
915 FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags),
916 FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags),
917 FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags),
918 FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags),
919 FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags),
920 FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags),
921 FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags),
922 FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags),
923 FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags),
924 FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags),
925 FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags),
926 FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags),
927 FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags));
928
929 unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP |
930 IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING |
931 IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT |
932 IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL |
933 IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP |
934 IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO);
935 unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags);
936 unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags);
937
3c9b8860
TG
938 /* link flags are currently at most 18 bits, let's align to
939 * printing 20 */
389cc5f7 940 if (unknown_flags_added)
3c9b8860
TG
941 log_debug_link(link,
942 "unknown link flags gained: %#.5x (ignoring)",
389cc5f7
TG
943 unknown_flags_added);
944
945 if (unknown_flags_removed)
3c9b8860
TG
946 log_debug_link(link,
947 "unknown link flags lost: %#.5x (ignoring)",
389cc5f7
TG
948 unknown_flags_removed);
949 }
505f8da7 950
e375dcde 951 carrier_gained = !link_has_carrier(link->flags, link->kernel_operstate) &&
1e9be60b 952 link_has_carrier(flags, operstate);
e375dcde 953 carrier_lost = link_has_carrier(link->flags, link->kernel_operstate) &&
1e9be60b
TG
954 !link_has_carrier(flags, operstate);
955
956 link->flags = flags;
e375dcde 957 link->kernel_operstate = operstate;
1e9be60b 958
deb2e523
TG
959 link_save(link);
960
99b4cc3e
TG
961 if (link->state == LINK_STATE_FAILED ||
962 link->state == LINK_STATE_UNMANAGED)
963 return 0;
964
7cc832b9
TG
965 if (carrier_gained) {
966 log_info_link(link, "gained carrier");
ffba6166 967
1e9be60b 968 if (link->network) {
ffba6166
TG
969 r = link_acquire_conf(link);
970 if (r < 0) {
ffba6166
TG
971 link_enter_failed(link);
972 return r;
ff254138 973 }
ffba6166 974 }
7cc832b9
TG
975 } else if (carrier_lost) {
976 log_info_link(link, "lost carrier");
efbc88b8 977
1e9be60b
TG
978 r = link_stop_clients(link);
979 if (r < 0) {
980 link_enter_failed(link);
981 return r;
ff254138
TG
982 }
983 }
984
ff254138
TG
985 return 0;
986}
987
dd3efc09 988static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
5da8149f 989 _cleanup_link_unref_ Link *link = userdata;
dd3efc09
TG
990 int r;
991
1746cf2a
TG
992 assert(link);
993
5da8149f 994 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1746cf2a
TG
995 return 1;
996
dd3efc09 997 r = sd_rtnl_message_get_errno(m);
45ad2c13 998 if (r < 0) {
9b86b393
TG
999 /* we warn but don't fail the link, as it may
1000 be brought up later */
76800848 1001 log_struct_link(LOG_WARNING, link,
97578344 1002 "MESSAGE=%-*s: could not bring up interface: %s",
987efa17 1003 IFNAMSIZ,
c9ccc19f
TG
1004 link->ifname, strerror(-r),
1005 "ERRNO=%d", -r,
1006 NULL);
45ad2c13
TG
1007 }
1008
f882c247
TG
1009 return 1;
1010}
1011
1012static int link_up(Link *link) {
cf6a8911 1013 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
f579559b
TG
1014 int r;
1015
f882c247
TG
1016 assert(link);
1017 assert(link->manager);
1018 assert(link->manager->rtnl);
1019
39032b87 1020 log_debug_link(link, "bringing link up");
449f7554 1021
151b9b96
LP
1022 r = sd_rtnl_message_new_link(link->manager->rtnl, &req,
1023 RTM_SETLINK, link->ifindex);
f579559b 1024 if (r < 0) {
39032b87 1025 log_error_link(link, "Could not allocate RTM_SETLINK message");
f579559b
TG
1026 return r;
1027 }
1028
5d4795f3 1029 r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
fc25d7f8 1030 if (r < 0) {
3c9b8860
TG
1031 log_error_link(link, "Could not set link flags: %s",
1032 strerror(-r));
fc25d7f8
TG
1033 return r;
1034 }
1035
3c9b8860
TG
1036 r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link,
1037 0, NULL);
f579559b 1038 if (r < 0) {
3333d748 1039 log_error_link(link,
3c9b8860
TG
1040 "Could not send rtnetlink message: %s",
1041 strerror(-r));
f579559b
TG
1042 return r;
1043 }
1044
b226d99b
TG
1045 link_ref(link);
1046
f882c247
TG
1047 return 0;
1048}
1049
3f265037 1050static int link_joined(Link *link) {
f882c247
TG
1051 int r;
1052
ef1ba606 1053 assert(link);
52433f6b 1054 assert(link->state == LINK_STATE_ENSLAVING);
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);
370e9930
TG
1074 assert(IN_SET(link->state, LINK_STATE_ENSLAVING, LINK_STATE_FAILED,
1075 LINK_STATE_LINGER));
ef1ba606 1076 assert(link->network);
02b59d57 1077
52433f6b
TG
1078 link->enslaving --;
1079
5da8149f 1080 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
02b59d57
TG
1081 return 1;
1082
1083 r = sd_rtnl_message_get_errno(m);
856f962c 1084 if (r < 0 && r != -EEXIST) {
c9ccc19f 1085 log_struct_link(LOG_ERR, link,
3f265037 1086 "MESSAGE=%-*s: could not join netdev: %s",
987efa17 1087 IFNAMSIZ,
c9ccc19f
TG
1088 link->ifname, strerror(-r),
1089 "ERRNO=%d", -r,
1090 NULL);
ef1ba606
TG
1091 link_enter_failed(link);
1092 return 1;
ba179154
TG
1093 } else
1094 log_debug_link(link, "joined netdev");
02b59d57 1095
856f962c 1096 if (link->enslaving <= 0)
3f265037 1097 link_joined(link);
02b59d57
TG
1098
1099 return 1;
1100}
1101
3f265037 1102static int link_enter_join_netdev(Link *link) {
6a0a2f86 1103 NetDev *netdev;
672682a6 1104 Iterator i;
02b59d57
TG
1105 int r;
1106
1107 assert(link);
1108 assert(link->network);
8434fd5c 1109 assert(link->state == LINK_STATE_PENDING);
02b59d57 1110
52433f6b 1111 link->state = LINK_STATE_ENSLAVING;
02b59d57 1112
fe8db0c5
TG
1113 link_save(link);
1114
7951dea2
SS
1115 if (!link->network->bridge &&
1116 !link->network->bond &&
6a0a2f86 1117 hashmap_isempty(link->network->stacked_netdevs))
3f265037 1118 return link_joined(link);
02b59d57 1119
d9c67ea1 1120 if (link->network->bond) {
52433f6b 1121 log_struct_link(LOG_DEBUG, link,
97578344 1122 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1123 IFNAMSIZ,
af4e9e2c 1124 link->ifname, link->network->bond->ifname,
aa9f1140 1125 NETDEVIF(link->network->bond),
52433f6b 1126 NULL);
449f7554 1127
3f265037 1128 r = netdev_join(link->network->bond, link, &netdev_join_handler);
52433f6b
TG
1129 if (r < 0) {
1130 log_struct_link(LOG_WARNING, link,
3f265037 1131 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1132 IFNAMSIZ,
3c9b8860
TG
1133 link->ifname, link->network->bond->ifname,
1134 strerror(-r),
aa9f1140 1135 NETDEVIF(link->network->bond),
52433f6b
TG
1136 NULL);
1137 link_enter_failed(link);
1138 return r;
1139 }
1140
0ad6148e
MO
1141 link->enslaving ++;
1142 }
1143
d9c67ea1 1144 if (link->network->bridge) {
0ad6148e 1145 log_struct_link(LOG_DEBUG, link,
97578344 1146 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1147 IFNAMSIZ,
af4e9e2c 1148 link->ifname, link->network->bridge->ifname,
aa9f1140 1149 NETDEVIF(link->network->bridge),
0ad6148e
MO
1150 NULL);
1151
3c9b8860
TG
1152 r = netdev_join(link->network->bridge, link,
1153 &netdev_join_handler);
0ad6148e
MO
1154 if (r < 0) {
1155 log_struct_link(LOG_WARNING, link,
3f265037 1156 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1157 IFNAMSIZ,
3c9b8860
TG
1158 link->ifname, link->network->bridge->ifname,
1159 strerror(-r),
aa9f1140 1160 NETDEVIF(link->network->bridge),
0ad6148e
MO
1161 NULL);
1162 link_enter_failed(link);
1163 return r;
1164 }
1165
52433f6b
TG
1166 link->enslaving ++;
1167 }
1168
6a0a2f86 1169 HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
7951dea2 1170 log_struct_link(LOG_DEBUG, link,
97578344 1171 "MESSAGE=%-*s: enslaving by '%s'",
987efa17 1172 IFNAMSIZ,
3c9b8860
TG
1173 link->ifname, netdev->ifname, NETDEVIF(netdev),
1174 NULL);
7951dea2 1175
6a0a2f86 1176 r = netdev_join(netdev, link, &netdev_join_handler);
7951dea2
SS
1177 if (r < 0) {
1178 log_struct_link(LOG_WARNING, link,
3f265037 1179 "MESSAGE=%-*s: could not join netdev '%s': %s",
987efa17 1180 IFNAMSIZ,
3c9b8860
TG
1181 link->ifname, netdev->ifname,
1182 strerror(-r),
6a0a2f86 1183 NETDEVIF(netdev), NULL);
326cb406
SS
1184 link_enter_failed(link);
1185 return r;
1186 }
1187
326cb406
SS
1188 link->enslaving ++;
1189 }
1190
ef1ba606
TG
1191 return 0;
1192}
1193
a748b692 1194static int link_configure(Link *link) {
02b59d57
TG
1195 int r;
1196
ef1ba606 1197 assert(link);
b22d8a00 1198 assert(link->network);
8434fd5c 1199 assert(link->state == LINK_STATE_PENDING);
a748b692 1200
eb34d4af 1201 if (link->network->ipv4ll) {
b22d8a00 1202 r = ipv4ll_configure(link);
eb34d4af
TG
1203 if (r < 0)
1204 return r;
1205 }
1206
ed942a9e 1207 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V4)) {
3c9b8860 1208 r = dhcp4_configure(link);
eb34d4af
TG
1209 if (r < 0)
1210 return r;
eb34d4af
TG
1211 }
1212
dd43110f 1213 if (link->network->dhcp_server) {
dd43110f
TG
1214 r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex);
1215 if (r < 0)
1216 return r;
1217
1218 r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0);
1219 if (r < 0)
1220 return r;
dd43110f
TG
1221 }
1222
ed942a9e 1223 if (IN_SET(link->network->dhcp, DHCP_SUPPORT_BOTH, DHCP_SUPPORT_V6)) {
4138fb2c
PF
1224 r = sd_icmp6_nd_new(&link->icmp6_router_discovery);
1225 if (r < 0)
1226 return r;
1227
1228 r = sd_icmp6_nd_attach_event(link->icmp6_router_discovery,
1229 NULL, 0);
1230 if (r < 0)
1231 return r;
1232
1233 r = sd_icmp6_nd_set_mac(link->icmp6_router_discovery,
1234 &link->mac);
1235 if (r < 0)
1236 return r;
1237
1238 r = sd_icmp6_nd_set_index(link->icmp6_router_discovery,
1239 link->ifindex);
1240 if (r < 0)
1241 return r;
1242
1243 r = sd_icmp6_nd_set_callback(link->icmp6_router_discovery,
1244 icmp6_router_handler, link);
1245 if (r < 0)
1246 return r;
1247 }
1248
bf0308cb 1249 if (link_has_carrier(link->flags, link->kernel_operstate)) {
1e9be60b
TG
1250 r = link_acquire_conf(link);
1251 if (r < 0)
1252 return r;
cc544d5f 1253 }
1e9be60b 1254
3f265037 1255 return link_enter_join_netdev(link);
505f8da7
TG
1256}
1257
3c9b8860
TG
1258static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m,
1259 void *userdata) {
5da8149f 1260 _cleanup_link_unref_ Link *link = userdata;
505f8da7 1261 Network *network;
505f8da7
TG
1262 int r;
1263
1264 assert(link);
1265 assert(link->ifname);
1266 assert(link->manager);
1267
8434fd5c 1268 if (link->state != LINK_STATE_PENDING)
5da8149f 1269 return 1;
505f8da7 1270
4f561e8e 1271 log_debug_link(link, "link state is up-to-date");
505f8da7 1272
3c9b8860
TG
1273 r = network_get(link->manager, link->udev_device, link->ifname,
1274 &link->mac, &network);
57bd6899
TG
1275 if (r == -ENOENT) {
1276 link_enter_unmanaged(link);
5da8149f 1277 return 1;
57bd6899
TG
1278 } else if (r < 0)
1279 return r;
505f8da7
TG
1280
1281 r = network_apply(link->manager, network, link);
1282 if (r < 0)
1283 return r;
1284
a748b692
TG
1285 r = link_configure(link);
1286 if (r < 0)
1287 return r;
1288
5da8149f 1289 return 1;
505f8da7
TG
1290}
1291
4f561e8e
TG
1292int link_initialized(Link *link, struct udev_device *device) {
1293 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
1294 int r;
1295
1296 assert(link);
1297 assert(link->manager);
1298 assert(link->manager->rtnl);
1299 assert(device);
1300
8434fd5c 1301 if (link->state != LINK_STATE_PENDING)
4f561e8e
TG
1302 return 0;
1303
679b3605
TG
1304 if (link->udev_device)
1305 return 0;
1306
4f561e8e
TG
1307 log_debug_link(link, "udev initialized link");
1308
1309 link->udev_device = udev_device_ref(device);
1310
3c9b8860
TG
1311 /* udev has initialized the link, but we don't know if we have yet
1312 * processed the NEWLINK messages with the latest state. Do a GETLINK,
1313 * when it returns we know that the pending NEWLINKs have already been
1314 * processed and that we are up-to-date */
4f561e8e 1315
3c9b8860
TG
1316 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
1317 link->ifindex);
4f561e8e
TG
1318 if (r < 0)
1319 return r;
1320
3c9b8860
TG
1321 r = sd_rtnl_call_async(link->manager->rtnl, req,
1322 link_initialized_and_synced, link, 0, NULL);
4f561e8e
TG
1323 if (r < 0)
1324 return r;
1325
5da8149f
TG
1326 link_ref(link);
1327
4f561e8e
TG
1328 return 0;
1329}
1330
3c9b8860
TG
1331int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message,
1332 void *userdata) {
fbbeb65a
TG
1333 Manager *m = userdata;
1334 Link *link = NULL;
1335 uint16_t type;
1336 _cleanup_address_free_ Address *address = NULL;
428fd0a7 1337 Address *ad;
fbbeb65a 1338 char buf[INET6_ADDRSTRLEN];
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
428fd0a7
TG
1422 LIST_FOREACH(addresses, ad, link->addresses) {
1423 if (address_equal(ad, address)) {
1424 LIST_REMOVE(addresses, link->addresses, ad);
1425
1426 address_free(ad);
1427
1428 address_dropped = true;
1429
1430 break;
1431 }
1432 }
1433
fbbeb65a
TG
1434 switch (type) {
1435 case RTM_NEWADDR:
428fd0a7
TG
1436 if (!address_dropped)
1437 log_debug_link(link, "added address: %s/%u", buf,
393c0c5e
TG
1438 address->prefixlen);
1439 else
1440 log_debug_link(link, "updated address: %s/%u", buf,
1441 address->prefixlen);
fbbeb65a 1442
428fd0a7
TG
1443 LIST_PREPEND(addresses, link->addresses, address);
1444 address = NULL;
1445
f5602be9
TG
1446 link_save(link);
1447
428fd0a7 1448 break;
fbbeb65a 1449 case RTM_DELADDR:
f5602be9 1450 if (address_dropped) {
428fd0a7 1451 log_debug_link(link, "removed address: %s/%u", buf,
393c0c5e 1452 address->prefixlen);
428fd0a7 1453
f5602be9 1454 link_save(link);
393c0c5e 1455 } else
3c9b8860
TG
1456 log_warning_link(link,
1457 "removing non-existent address: %s/%u",
393c0c5e 1458 buf, address->prefixlen);
f5602be9 1459
fbbeb65a
TG
1460 break;
1461 default:
1462 assert_not_reached("Received invalid RTNL message type");
1463 }
1464
1465 return 1;
1466}
1467
505f8da7
TG
1468int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
1469 Link *link;
fbbeb65a 1470 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
505f8da7
TG
1471 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
1472 char ifindex_str[2 + DECIMAL_STR_MAX(int)];
1473 int r;
1474
1475 assert(m);
fbbeb65a 1476 assert(m->rtnl);
505f8da7
TG
1477 assert(message);
1478 assert(ret);
1479
1480 r = link_new(m, message, ret);
1481 if (r < 0)
1482 return r;
1483
1484 link = *ret;
1485
ae06ab10 1486 log_debug_link(link, "link %d added", link->ifindex);
505f8da7 1487
3c9b8860
TG
1488 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex,
1489 0);
fbbeb65a
TG
1490 if (r < 0)
1491 return r;
1492
3c9b8860
TG
1493 r = sd_rtnl_call_async(m->rtnl, req, link_get_address_handler, link, 0,
1494 NULL);
fbbeb65a
TG
1495 if (r < 0)
1496 return r;
1497
5da8149f
TG
1498 link_ref(link);
1499
505f8da7
TG
1500 if (detect_container(NULL) <= 0) {
1501 /* not in a container, udev will be around */
ae06ab10 1502 sprintf(ifindex_str, "n%d", link->ifindex);
505f8da7
TG
1503 device = udev_device_new_from_device_id(m->udev, ifindex_str);
1504 if (!device) {
3c9b8860
TG
1505 log_warning_link(link,
1506 "could not find udev device: %m");
9fecce80 1507 return -errno;
505f8da7
TG
1508 }
1509
3c4cb064 1510 if (udev_device_get_is_initialized(device) <= 0) {
505f8da7 1511 /* not yet ready */
8434fd5c 1512 log_debug_link(link, "link pending udev initialization...");
505f8da7 1513 return 0;
3c4cb064 1514 }
505f8da7 1515
4f561e8e
TG
1516 r = link_initialized(link, device);
1517 if (r < 0)
1518 return r;
1519 } else {
5da8149f
TG
1520 /* we are calling a callback directly, so must take a ref */
1521 link_ref(link);
1522
4f561e8e
TG
1523 r = link_initialized_and_synced(m->rtnl, NULL, link);
1524 if (r < 0)
1525 return r;
1526 }
505f8da7 1527
a748b692
TG
1528 return 0;
1529}
1530
22936833 1531int link_update(Link *link, sd_rtnl_message *m) {
c49b33ac 1532 struct ether_addr mac;
ca4e095a 1533 const char *ifname;
afe7fd56 1534 uint32_t mtu;
22936833
TG
1535 int r;
1536
dd3efc09 1537 assert(link);
b8941f74 1538 assert(link->ifname);
22936833
TG
1539 assert(m);
1540
7619683b
TG
1541 if (link->state == LINK_STATE_LINGER) {
1542 link_ref(link);
1543 log_info_link(link, "link readded");
1544 link->state = LINK_STATE_ENSLAVING;
1545 }
1546
b8941f74
TG
1547 r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
1548 if (r >= 0 && !streq(ifname, link->ifname)) {
1549 log_info_link(link, "renamed to %s", ifname);
1550
1551 free(link->ifname);
1552 link->ifname = strdup(ifname);
1553 if (!link->ifname)
1554 return -ENOMEM;
1555 }
1556
afe7fd56
TG
1557 r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu);
1558 if (r >= 0 && mtu > 0) {
1559 link->mtu = mtu;
1560 if (!link->original_mtu) {
1561 link->original_mtu = mtu;
9842de0d 1562 log_debug_link(link, "saved original MTU: %"
afe7fd56
TG
1563 PRIu32, link->original_mtu);
1564 }
1565
1566 if (link->dhcp_client) {
3c9b8860
TG
1567 r = sd_dhcp_client_set_mtu(link->dhcp_client,
1568 link->mtu);
afe7fd56 1569 if (r < 0) {
3c9b8860
TG
1570 log_warning_link(link,
1571 "Could not update MTU in DHCP client: %s",
afe7fd56
TG
1572 strerror(-r));
1573 return r;
1574 }
1575 }
9842de0d 1576 }
69629de9 1577
e9189a1f
TG
1578 /* The kernel may broadcast NEWLINK messages without the MAC address
1579 set, simply ignore them. */
c49b33ac 1580 r = sd_rtnl_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
e9189a1f 1581 if (r >= 0) {
3c9b8860
TG
1582 if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet,
1583 ETH_ALEN)) {
c49b33ac 1584
3c9b8860
TG
1585 memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet,
1586 ETH_ALEN);
c49b33ac 1587
20861203
TG
1588 log_debug_link(link, "MAC address: "
1589 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
1590 mac.ether_addr_octet[0],
1591 mac.ether_addr_octet[1],
1592 mac.ether_addr_octet[2],
1593 mac.ether_addr_octet[3],
1594 mac.ether_addr_octet[4],
1595 mac.ether_addr_octet[5]);
c49b33ac 1596
20861203
TG
1597 if (link->ipv4ll) {
1598 r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
1599 if (r < 0) {
3c9b8860
TG
1600 log_warning_link(link,
1601 "Could not update MAC address in IPv4LL client: %s",
20861203
TG
1602 strerror(-r));
1603 return r;
1604 }
c49b33ac 1605 }
c49b33ac 1606
20861203 1607 if (link->dhcp_client) {
3c9b8860
TG
1608 r = sd_dhcp_client_set_mac(link->dhcp_client,
1609 &link->mac);
20861203 1610 if (r < 0) {
3c9b8860
TG
1611 log_warning_link(link,
1612 "Could not update MAC address in DHCP client: %s",
20861203
TG
1613 strerror(-r));
1614 return r;
1615 }
c49b33ac 1616 }
4138fb2c
PF
1617
1618 if (link->dhcp6_client) {
1619 r = sd_dhcp6_client_set_mac(link->dhcp6_client,
1620 &link->mac);
1621 if (r < 0) {
3c9b8860
TG
1622 log_warning_link(link,
1623 "Could not update MAC address in DHCPv6 client: %s",
4138fb2c
PF
1624 strerror(-r));
1625 return r;
1626 }
1627 }
c49b33ac 1628 }
4f882b2a
TG
1629 }
1630
1e9be60b 1631 return link_update_flags(link, m);
dd3efc09 1632}
fe8db0c5 1633
e375dcde
TG
1634static void link_update_operstate(Link *link) {
1635
1636 assert(link);
1637
1638 if (link->kernel_operstate == IF_OPER_DORMANT)
1639 link->operstate = LINK_OPERSTATE_DORMANT;
1640 else if (link_has_carrier(link->flags, link->kernel_operstate)) {
1641 Address *address;
1642 uint8_t scope = RT_SCOPE_NOWHERE;
1643
1644 /* if we have carrier, check what addresses we have */
1645 LIST_FOREACH(addresses, address, link->addresses) {
1646 if (address->scope < scope)
1647 scope = address->scope;
1648 }
1649
1650 if (scope < RT_SCOPE_SITE)
1651 /* universally accessible addresses found */
1652 link->operstate = LINK_OPERSTATE_ROUTABLE;
1653 else if (scope < RT_SCOPE_HOST)
1654 /* only link or site local addresses found */
1655 link->operstate = LINK_OPERSTATE_DEGRADED;
1656 else
1657 /* no useful addresses found */
1658 link->operstate = LINK_OPERSTATE_CARRIER;
54cba0b1 1659 } else if (link->flags & IFF_UP)
d3df0e39 1660 link->operstate = LINK_OPERSTATE_NO_CARRIER;
54cba0b1 1661 else
d3df0e39 1662 link->operstate = LINK_OPERSTATE_OFF;
e375dcde
TG
1663}
1664
fe8db0c5 1665int link_save(Link *link) {
68a8723c 1666 _cleanup_free_ char *temp_path = NULL;
fe8db0c5 1667 _cleanup_fclose_ FILE *f = NULL;
e375dcde 1668 const char *admin_state, *oper_state;
fe8db0c5
TG
1669 int r;
1670
1671 assert(link);
1672 assert(link->state_file);
68a8723c 1673 assert(link->lease_file);
bbf7c048
TG
1674 assert(link->manager);
1675
e375dcde
TG
1676 link_update_operstate(link);
1677
bbf7c048
TG
1678 r = manager_save(link->manager);
1679 if (r < 0)
1680 return r;
fe8db0c5 1681
370e9930
TG
1682 if (link->state == LINK_STATE_LINGER) {
1683 unlink(link->state_file);
1684 return 0;
1685 }
1686
deb2e523
TG
1687 admin_state = link_state_to_string(link->state);
1688 assert(admin_state);
1689
e375dcde
TG
1690 oper_state = link_operstate_to_string(link->operstate);
1691 assert(oper_state);
deb2e523 1692
fe8db0c5
TG
1693 r = fopen_temporary(link->state_file, &f, &temp_path);
1694 if (r < 0)
c2d6bd61 1695 return r;
fe8db0c5
TG
1696
1697 fchmod(fileno(f), 0644);
1698
1699 fprintf(f,
1700 "# This is private data. Do not parse.\n"
deb2e523 1701 "ADMIN_STATE=%s\n"
6dcaa6f5
TG
1702 "OPER_STATE=%s\n",
1703 admin_state, oper_state);
fe8db0c5 1704
bcb7a07e 1705 if (link->network) {
b0e39c82
TG
1706 char **address;
1707
1708 fputs("DNS=", f);
1709
1710 if (link->network->dhcp_dns &&
1711 link->dhcp_lease) {
1712 const struct in_addr *addresses;
1713
1714 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
1715 if (r > 0) {
1716 serialize_in_addrs(f, addresses, r);
1717 if (link->network->dns)
1718 fputs(" ", f);
1719 }
1720 }
1721
1722 STRV_FOREACH(address, link->network->dns)
1723 fprintf(f, "%s%s", *address,
1724 (address + 1 ? " " : ""));
1725
1726 fputs("\n", f);
1727
1728 fprintf(f, "NTP=");
1729
1730 if (link->network->dhcp_ntp &&
1731 link->dhcp_lease) {
1732 const struct in_addr *addresses;
1733
1734 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
1735 if (r > 0) {
1736 serialize_in_addrs(f, addresses, r);
1737 if (link->network->ntp)
1738 fputs(" ", f);
1739 }
1740 }
1741
1742 STRV_FOREACH(address, link->network->ntp)
1743 fprintf(f, "%s%s", *address,
1744 (address + 1 ? " " : ""));
1745
1746 fputs("\n", f);
bd8f6538 1747
3c9b8860
TG
1748 fprintf(f, "LLMNR=%s\n",
1749 llmnr_support_to_string(link->network->llmnr));
bcb7a07e 1750 }
7374f9d8 1751
fe8db0c5 1752 if (link->dhcp_lease) {
d9876a52
TG
1753 assert(link->network);
1754
68a8723c 1755 r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
fe8db0c5 1756 if (r < 0)
c2d6bd61 1757 goto fail;
fe8db0c5 1758
7374f9d8 1759 fprintf(f,
b0e39c82
TG
1760 "DHCP_LEASE=%s\n",
1761 link->lease_file);
deb2e523 1762 } else
68a8723c 1763 unlink(link->lease_file);
fe8db0c5 1764
c2d6bd61
LP
1765 r = fflush_and_check(f);
1766 if (r < 0)
1767 goto fail;
fe8db0c5 1768
c2d6bd61 1769 if (rename(temp_path, link->state_file) < 0) {
fe8db0c5 1770 r = -errno;
c2d6bd61 1771 goto fail;
fe8db0c5
TG
1772 }
1773
c2d6bd61 1774 return 0;
c2d6bd61
LP
1775fail:
1776 log_error_link(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r));
1777 unlink(link->state_file);
1778 unlink(temp_path);
fe8db0c5
TG
1779 return r;
1780}
1781
1782static const char* const link_state_table[_LINK_STATE_MAX] = {
8434fd5c 1783 [LINK_STATE_PENDING] = "pending",
fe8db0c5
TG
1784 [LINK_STATE_ENSLAVING] = "configuring",
1785 [LINK_STATE_SETTING_ADDRESSES] = "configuring",
1786 [LINK_STATE_SETTING_ROUTES] = "configuring",
1787 [LINK_STATE_CONFIGURED] = "configured",
57bd6899 1788 [LINK_STATE_UNMANAGED] = "unmanaged",
fe8db0c5 1789 [LINK_STATE_FAILED] = "failed",
370e9930 1790 [LINK_STATE_LINGER] = "linger",
fe8db0c5
TG
1791};
1792
1793DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);
e375dcde
TG
1794
1795static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
d3df0e39
TG
1796 [LINK_OPERSTATE_OFF] = "off",
1797 [LINK_OPERSTATE_NO_CARRIER] = "no-carrier",
e375dcde
TG
1798 [LINK_OPERSTATE_DORMANT] = "dormant",
1799 [LINK_OPERSTATE_CARRIER] = "carrier",
1800 [LINK_OPERSTATE_DEGRADED] = "degraded",
1801 [LINK_OPERSTATE_ROUTABLE] = "routable",
1802};
1803
1804DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);