]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-dhcp4.c
network: make all failures in route configuration fatal
[thirdparty/systemd.git] / src / network / networkd-dhcp4.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <netinet/in.h>
4 #include <linux/if.h>
5
6 #include "alloc-util.h"
7 #include "hostname-util.h"
8 #include "parse-util.h"
9 #include "network-internal.h"
10 #include "networkd-link.h"
11 #include "networkd-manager.h"
12 #include "networkd-network.h"
13 #include "string-util.h"
14 #include "sysctl-util.h"
15
16 static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
17 int r;
18
19 assert(link);
20 assert(link->dhcp4_messages > 0);
21
22 link->dhcp4_messages--;
23
24 r = sd_netlink_message_get_errno(m);
25 if (r < 0 && r != -EEXIST) {
26 log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");
27 link_enter_failed(link);
28 }
29
30 if (link->dhcp4_messages == 0) {
31 link->dhcp4_configured = true;
32 link_check_ready(link);
33 }
34
35 return 1;
36 }
37
38 static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
39 assert(route);
40 assert(self_addr);
41
42 if (in_addr_is_localhost(AF_INET, &route->dst) ||
43 (self_addr->s_addr && route->dst.in.s_addr == self_addr->s_addr))
44 return RT_SCOPE_HOST;
45 else if (in4_addr_is_null(&route->gw.in))
46 return RT_SCOPE_LINK;
47 else
48 return RT_SCOPE_UNIVERSE;
49 }
50
51 static int link_set_dhcp_routes(Link *link) {
52 _cleanup_free_ sd_dhcp_route **static_routes = NULL;
53 bool classless_route = false, static_route = false;
54 const struct in_addr *router;
55 struct in_addr address;
56 int r, n, i;
57 uint32_t table;
58
59 assert(link);
60
61 if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */
62 return 0;
63
64 if (!link->network) /* link went down while we configured the IP addresses? */
65 return 0;
66
67 if (!link->network->dhcp_use_routes)
68 return 0;
69
70 table = link_get_dhcp_route_table(link);
71
72 r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
73 if (r < 0)
74 return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
75
76 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
77 if (n == -ENODATA)
78 log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m");
79 else if (n < 0)
80 log_link_debug_errno(link, n, "DHCP error: could not get routes: %m");
81
82 for (i = 0; i < n; i++) {
83 switch (sd_dhcp_route_get_option(static_routes[i])) {
84 case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
85 classless_route = true;
86 break;
87 case SD_DHCP_OPTION_STATIC_ROUTE:
88 static_route = true;
89 break;
90 }
91 }
92
93 for (i = 0; i < n; i++) {
94 _cleanup_(route_freep) Route *route = NULL;
95
96 /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
97 the DHCP client MUST ignore the Static Routes option. */
98 if (classless_route &&
99 sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE)
100 continue;
101
102 r = route_new(&route);
103 if (r < 0)
104 return log_link_error_errno(link, r, "Could not allocate route: %m");
105
106 route->family = AF_INET;
107 route->protocol = RTPROT_DHCP;
108 assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
109 assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
110 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
111 route->priority = link->network->dhcp_route_metric;
112 route->table = table;
113 route->scope = route_scope_from_address(route, &address);
114
115 r = route_configure(route, link, dhcp4_route_handler);
116 if (r < 0)
117 return log_link_error_errno(link, r, "Could not set host route: %m");
118
119 link->dhcp4_messages++;
120 }
121
122 r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
123 if (IN_SET(r, 0, -ENODATA))
124 log_link_info(link, "DHCP: No gateway received from DHCP server.");
125 else if (r < 0)
126 log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
127 else if (in4_addr_is_null(&router[0]))
128 log_link_info(link, "DHCP: Received gateway is null.");
129
130 /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
131 a Router option, the DHCP client MUST ignore the Router option. */
132 if (classless_route && static_route)
133 log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option");
134
135 if (r > 0 && !classless_route && !in4_addr_is_null(&router[0])) {
136 _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL;
137
138 r = route_new(&route_gw);
139 if (r < 0)
140 return log_link_error_errno(link, r, "Could not allocate route: %m");
141
142 /* The dhcp netmask may mask out the gateway. Add an explicit
143 * route for the gw host so that we can route no matter the
144 * netmask or existing kernel route tables. */
145 route_gw->family = AF_INET;
146 route_gw->dst.in = router[0];
147 route_gw->dst_prefixlen = 32;
148 route_gw->prefsrc.in = address;
149 route_gw->scope = RT_SCOPE_LINK;
150 route_gw->protocol = RTPROT_DHCP;
151 route_gw->priority = link->network->dhcp_route_metric;
152 route_gw->table = table;
153
154 r = route_configure(route_gw, link, dhcp4_route_handler);
155 if (r < 0)
156 return log_link_error_errno(link, r, "Could not set host route: %m");
157
158 link->dhcp4_messages++;
159
160 r = route_new(&route);
161 if (r < 0)
162 return log_link_error_errno(link, r, "Could not allocate route: %m");
163
164 route->family = AF_INET;
165 route->gw.in = router[0];
166 route->prefsrc.in = address;
167 route->protocol = RTPROT_DHCP;
168 route->priority = link->network->dhcp_route_metric;
169 route->table = table;
170
171 r = route_configure(route, link, dhcp4_route_handler);
172 if (r < 0)
173 return log_link_error_errno(link, r, "Could not set routes: %m");
174
175 link->dhcp4_messages++;
176 }
177
178 return 0;
179 }
180
181 static int dhcp_remove_routes(Link *link, struct in_addr *address) {
182 _cleanup_free_ sd_dhcp_route **routes = NULL;
183 uint32_t table;
184 int n, i, r;
185
186 assert(link);
187 assert(address);
188
189 if (!link->network->dhcp_use_routes)
190 return 0;
191
192 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
193 if (IN_SET(n, 0, -ENODATA)) {
194 log_link_debug(link, "DHCP: No routes received from DHCP server: %m");
195 return 0;
196 } else if (n < 0)
197 return log_link_error_errno(link, n, "DHCP error: could not get routes: %m");
198
199 table = link_get_dhcp_route_table(link);
200
201 for (i = 0; i < n; i++) {
202 _cleanup_(route_freep) Route *route = NULL;
203
204 r = route_new(&route);
205 if (r < 0)
206 return log_oom();
207
208 route->family = AF_INET;
209 assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
210 assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
211 assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
212 route->priority = link->network->dhcp_route_metric;
213 route->table = table;
214 route->scope = route_scope_from_address(route, address);
215
216 (void) route_remove(route, link, NULL);
217 }
218
219 return n;
220 }
221
222 static int dhcp_remove_router(Link *link, struct in_addr *address) {
223 _cleanup_(route_freep) Route *route_gw = NULL, *route = NULL;
224 const struct in_addr *router;
225 uint32_t table;
226 int r;
227
228 assert(link);
229 assert(address);
230
231 if (!link->network->dhcp_use_routes)
232 return 0;
233
234 r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
235 if (IN_SET(r, 0, -ENODATA)) {
236 log_link_debug(link, "DHCP: No gateway received from DHCP server.");
237 return 0;
238 } else if (r < 0)
239 return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
240 else if (in4_addr_is_null(&router[0])) {
241 log_link_info(link, "DHCP: Received gateway is null, ignoring.");
242 return 0;
243 }
244
245 table = link_get_dhcp_route_table(link);
246
247 r = route_new(&route_gw);
248 if (r < 0)
249 return log_oom();
250
251 route_gw->family = AF_INET;
252 route_gw->dst.in = router[0];
253 route_gw->dst_prefixlen = 32;
254 route_gw->prefsrc.in = *address;
255 route_gw->scope = RT_SCOPE_LINK;
256 route_gw->protocol = RTPROT_DHCP;
257 route_gw->priority = link->network->dhcp_route_metric;
258 route_gw->table = table;
259
260 (void) route_remove(route_gw, link, NULL);
261
262 r = route_new(&route);
263 if (r < 0)
264 return log_oom();
265
266 route->family = AF_INET;
267 route->gw.in = router[0];
268 route->prefsrc.in = *address;
269 route->protocol = RTPROT_DHCP;
270 route->priority = link->network->dhcp_route_metric;
271 route->table = table;
272
273 (void) route_remove(route, link, NULL);
274
275 return 0;
276 }
277
278 static int dhcp_remove_address(Link *link, struct in_addr *address) {
279 _cleanup_(address_freep) Address *a = NULL;
280 struct in_addr netmask;
281 int r;
282
283 assert(link);
284 assert(address);
285
286 if (in4_addr_is_null(address))
287 return 0;
288
289 r = address_new(&a);
290 if (r < 0)
291 return log_oom();
292
293 a->family = AF_INET;
294 a->in_addr.in = *address;
295
296 if (sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask) >= 0)
297 a->prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
298
299 (void) address_remove(a, link, NULL);
300
301 return 0;
302 }
303
304 static int dhcp_reset_mtu(Link *link) {
305 uint16_t mtu;
306 int r;
307
308 assert(link);
309
310 if (!link->network->dhcp_use_mtu)
311 return 0;
312
313 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
314 if (r < 0)
315 return r;
316
317 if (link->original_mtu == mtu)
318 return 0;
319
320 r = link_set_mtu(link, link->original_mtu);
321 if (r < 0) {
322 log_link_error_errno(link, r, "DHCP error: could not reset MTU: %m");
323 link_enter_failed(link);
324 return r;
325 }
326
327 return 0;
328 }
329
330 static int dhcp_reset_hostname(Link *link) {
331 const char *hostname;
332 int r;
333
334 assert(link);
335
336 if (!link->network->dhcp_use_hostname)
337 return 0;
338
339 hostname = link->network->dhcp_hostname;
340 if (!hostname)
341 (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
342
343 if (!hostname)
344 return 0;
345
346 /* If a hostname was set due to the lease, then unset it now. */
347 r = manager_set_hostname(link->manager, NULL);
348 if (r < 0)
349 return log_link_error_errno(link, r, "DHCP error: Failed to reset transient hostname: %m");
350
351 return 0;
352 }
353
354 static int dhcp_lease_lost(Link *link) {
355 struct in_addr address = {};
356
357 assert(link);
358 assert(link->dhcp_lease);
359
360 log_link_warning(link, "DHCP lease lost");
361
362 link->dhcp4_configured = false;
363
364 (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
365 (void) dhcp_remove_routes(link, &address);
366 (void) dhcp_remove_router(link, &address);
367 (void) dhcp_remove_address(link, &address);
368 (void) dhcp_reset_mtu(link);
369 (void) dhcp_reset_hostname(link);
370
371 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
372 link_dirty(link);
373
374 return 0;
375 }
376
377 static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
378 int r;
379
380 assert(link);
381
382 r = sd_netlink_message_get_errno(m);
383 if (r < 0 && r != -EEXIST) {
384 log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
385 link_enter_failed(link);
386 } else if (r >= 0)
387 manager_rtnl_process_address(rtnl, m, link->manager);
388
389 r = link_set_dhcp_routes(link);
390 if (r < 0) {
391 link_enter_failed(link);
392 return 1;
393 }
394
395 /* Add back static routes since kernel removes while DHCPv4 address is removed from when lease expires */
396 link_request_set_routes(link);
397
398 if (link->dhcp4_messages == 0) {
399 link->dhcp4_configured = true;
400 link_check_ready(link);
401 }
402
403 return 1;
404 }
405
406 static int dhcp4_update_address(Link *link,
407 struct in_addr *address,
408 struct in_addr *netmask,
409 uint32_t lifetime) {
410 _cleanup_(address_freep) Address *addr = NULL;
411 unsigned prefixlen;
412 int r;
413
414 assert(address);
415 assert(netmask);
416 assert(lifetime);
417
418 prefixlen = in4_addr_netmask_to_prefixlen(netmask);
419
420 r = address_new(&addr);
421 if (r < 0)
422 return r;
423
424 addr->family = AF_INET;
425 addr->in_addr.in.s_addr = address->s_addr;
426 addr->cinfo.ifa_prefered = lifetime;
427 addr->cinfo.ifa_valid = lifetime;
428 addr->prefixlen = prefixlen;
429 addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
430
431 /* allow reusing an existing address and simply update its lifetime
432 * in case it already exists */
433 r = address_configure(addr, link, dhcp4_address_handler, true);
434 if (r < 0)
435 return r;
436
437 return 0;
438 }
439
440 static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
441 sd_dhcp_lease *lease;
442 struct in_addr address;
443 struct in_addr netmask;
444 uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
445 int r;
446
447 assert(link);
448 assert(client);
449 assert(link->network);
450
451 r = sd_dhcp_client_get_lease(client, &lease);
452 if (r < 0)
453 return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
454
455 sd_dhcp_lease_unref(link->dhcp_lease);
456 link->dhcp4_configured = false;
457 link->dhcp_lease = sd_dhcp_lease_ref(lease);
458 link_dirty(link);
459
460 r = sd_dhcp_lease_get_address(lease, &address);
461 if (r < 0)
462 return log_link_warning_errno(link, r, "DHCP error: no address: %m");
463
464 r = sd_dhcp_lease_get_netmask(lease, &netmask);
465 if (r < 0)
466 return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
467
468 if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
469 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
470 if (r < 0)
471 return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
472 }
473
474 r = dhcp4_update_address(link, &address, &netmask, lifetime);
475 if (r < 0) {
476 log_link_warning_errno(link, r, "Could not update IP address: %m");
477 link_enter_failed(link);
478 return r;
479 }
480
481 return 0;
482 }
483
484 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
485 const struct in_addr *router;
486 sd_dhcp_lease *lease;
487 struct in_addr address;
488 struct in_addr netmask;
489 unsigned prefixlen;
490 uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
491 int r;
492
493 assert(client);
494 assert(link);
495
496 link->dhcp4_configured = false;
497
498 r = sd_dhcp_client_get_lease(client, &lease);
499 if (r < 0)
500 return log_link_error_errno(link, r, "DHCP error: No lease: %m");
501
502 r = sd_dhcp_lease_get_address(lease, &address);
503 if (r < 0)
504 return log_link_error_errno(link, r, "DHCP error: No address: %m");
505
506 r = sd_dhcp_lease_get_netmask(lease, &netmask);
507 if (r < 0)
508 return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
509
510 prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
511
512 r = sd_dhcp_lease_get_router(lease, &router);
513 if (r < 0 && r != -ENODATA)
514 return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
515
516 if (r > 0 && !in4_addr_is_null(&router[0]))
517 log_struct(LOG_INFO,
518 LOG_LINK_INTERFACE(link),
519 LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
520 ADDRESS_FMT_VAL(address),
521 prefixlen,
522 ADDRESS_FMT_VAL(router[0])),
523 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
524 "PREFIXLEN=%u", prefixlen,
525 "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(router[0]));
526 else
527 log_struct(LOG_INFO,
528 LOG_LINK_INTERFACE(link),
529 LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
530 ADDRESS_FMT_VAL(address),
531 prefixlen),
532 "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
533 "PREFIXLEN=%u", prefixlen);
534
535 link->dhcp_lease = sd_dhcp_lease_ref(lease);
536 link_dirty(link);
537
538 if (link->network->dhcp_use_mtu) {
539 uint16_t mtu;
540
541 r = sd_dhcp_lease_get_mtu(lease, &mtu);
542 if (r >= 0) {
543 r = link_set_mtu(link, mtu);
544 if (r < 0)
545 log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
546 }
547 }
548
549 if (link->network->dhcp_use_hostname) {
550 const char *dhcpname = NULL;
551 _cleanup_free_ char *hostname = NULL;
552
553 if (link->network->dhcp_hostname)
554 dhcpname = link->network->dhcp_hostname;
555 else
556 (void) sd_dhcp_lease_get_hostname(lease, &dhcpname);
557
558 if (dhcpname) {
559 r = shorten_overlong(dhcpname, &hostname);
560 if (r < 0)
561 log_link_warning_errno(link, r, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname);
562 if (r == 1)
563 log_link_notice(link, "Overlong DHCP hostname received, shortened from '%s' to '%s'", dhcpname, hostname);
564 }
565
566 if (hostname) {
567 r = manager_set_hostname(link->manager, hostname);
568 if (r < 0)
569 log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
570 }
571 }
572
573 if (link->network->dhcp_use_timezone) {
574 const char *tz = NULL;
575
576 (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
577
578 if (tz) {
579 r = manager_set_timezone(link->manager, tz);
580 if (r < 0)
581 log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
582 }
583 }
584
585 if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
586 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
587 if (r < 0)
588 return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
589 }
590
591 r = dhcp4_update_address(link, &address, &netmask, lifetime);
592 if (r < 0) {
593 log_link_warning_errno(link, r, "Could not update IP address: %m");
594 link_enter_failed(link);
595 return r;
596 }
597
598 return 0;
599 }
600
601 static int dhcp_server_is_black_listed(Link *link, sd_dhcp_client *client) {
602 sd_dhcp_lease *lease;
603 struct in_addr addr;
604 int r;
605
606 assert(link);
607 assert(link->network);
608 assert(client);
609
610 r = sd_dhcp_client_get_lease(client, &lease);
611 if (r < 0)
612 return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
613
614 r = sd_dhcp_lease_get_server_identifier(lease, &addr);
615 if (r < 0)
616 return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
617
618 if (set_contains(link->network->dhcp_black_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
619 log_struct(LOG_DEBUG,
620 LOG_LINK_INTERFACE(link),
621 LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in black listed ip addresses, ignoring offer",
622 ADDRESS_FMT_VAL(addr)));
623 return true;
624 }
625
626 return false;
627 }
628
629 static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
630 Link *link = userdata;
631 int r;
632
633 assert(link);
634 assert(link->network);
635 assert(link->manager);
636
637 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
638 return 0;
639
640 switch (event) {
641 case SD_DHCP_CLIENT_EVENT_STOP:
642
643 if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4)) {
644 assert(link->ipv4ll);
645
646 log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
647
648 r = sd_ipv4ll_start(link->ipv4ll);
649 if (r < 0)
650 return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
651 }
652
653 if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
654 log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it.");
655 return 0;
656 }
657
658 if (link->network->dhcp_send_release)
659 (void) sd_dhcp_client_send_release(client);
660
661 if (link->dhcp_lease) {
662 r = dhcp_lease_lost(link);
663 if (r < 0) {
664 link_enter_failed(link);
665 return r;
666 }
667 }
668
669 break;
670 case SD_DHCP_CLIENT_EVENT_EXPIRED:
671 case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
672
673 if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
674 log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it.");
675 return 0;
676 }
677
678 if (link->dhcp_lease) {
679 r = dhcp_lease_lost(link);
680 if (r < 0) {
681 link_enter_failed(link);
682 return r;
683 }
684 }
685
686 if (event == SD_DHCP_CLIENT_EVENT_IP_CHANGE) {
687 r = dhcp_lease_acquired(client, link);
688 if (r < 0) {
689 link_enter_failed(link);
690 return r;
691 }
692 }
693
694 break;
695 case SD_DHCP_CLIENT_EVENT_RENEW:
696 r = dhcp_lease_renew(client, link);
697 if (r < 0) {
698 link_enter_failed(link);
699 return r;
700 }
701 break;
702 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
703 r = dhcp_lease_acquired(client, link);
704 if (r < 0) {
705 link_enter_failed(link);
706 return r;
707 }
708 break;
709 case SD_DHCP_CLIENT_EVENT_SELECTING:
710 r = dhcp_server_is_black_listed(link, client);
711 if (r < 0)
712 return r;
713 if (r != 0)
714 return -ENOMSG;
715 break;
716 default:
717 if (event < 0)
718 log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
719 else
720 log_link_warning(link, "DHCP unknown event: %i", event);
721 break;
722 }
723
724 return 0;
725 }
726
727 static int dhcp4_set_hostname(Link *link) {
728 _cleanup_free_ char *hostname = NULL;
729 const char *hn;
730 int r;
731
732 assert(link);
733
734 if (!link->network->dhcp_send_hostname)
735 hn = NULL;
736 else if (link->network->dhcp_hostname)
737 hn = link->network->dhcp_hostname;
738 else {
739 r = gethostname_strict(&hostname);
740 if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */
741 return r;
742
743 hn = hostname;
744 }
745
746 r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
747 if (r == -EINVAL && hostname)
748 /* Ignore error when the machine's hostname is not suitable to send in DHCP packet. */
749 log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set hostname from kernel hostname, ignoring: %m");
750 else if (r < 0)
751 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set hostname: %m");
752
753 return 0;
754 }
755
756 static bool promote_secondaries_enabled(const char *ifname) {
757 _cleanup_free_ char *promote_secondaries_sysctl = NULL;
758 char *promote_secondaries_path;
759 int r;
760
761 promote_secondaries_path = strjoina("net/ipv4/conf/", ifname, "/promote_secondaries");
762 r = sysctl_read(promote_secondaries_path, &promote_secondaries_sysctl);
763 if (r < 0) {
764 log_debug_errno(r, "Cannot read sysctl %s", promote_secondaries_path);
765 return false;
766 }
767
768 truncate_nl(promote_secondaries_sysctl);
769 r = parse_boolean(promote_secondaries_sysctl);
770 if (r < 0)
771 log_warning_errno(r, "Cannot parse sysctl %s with content %s as boolean", promote_secondaries_path, promote_secondaries_sysctl);
772 return r > 0;
773 }
774
775 /* dhcp4_set_promote_secondaries will ensure this interface has
776 * the "promote_secondaries" option in the kernel set. If this sysctl
777 * is not set DHCP will work only as long as the IP address does not
778 * changes between leases. The kernel will remove all secondary IP
779 * addresses of an interface otherwise. The way systemd-network works
780 * is that the new IP of a lease is added as a secondary IP and when
781 * the primary one expires it relies on the kernel to promote the
782 * secondary IP. See also https://github.com/systemd/systemd/issues/7163
783 */
784 int dhcp4_set_promote_secondaries(Link *link) {
785 int r;
786
787 assert(link);
788 assert(link->network);
789 assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
790
791 /* check if the kernel has promote_secondaries enabled for our
792 * interface. If it is not globally enabled or enabled for the
793 * specific interface we must either enable it.
794 */
795 if (!(promote_secondaries_enabled("all") || promote_secondaries_enabled(link->ifname))) {
796 char *promote_secondaries_path = NULL;
797
798 log_link_debug(link, "promote_secondaries is unset, setting it");
799 promote_secondaries_path = strjoina("net/ipv4/conf/", link->ifname, "/promote_secondaries");
800 r = sysctl_write(promote_secondaries_path, "1");
801 if (r < 0)
802 log_link_warning_errno(link, r, "cannot set sysctl %s to 1", promote_secondaries_path);
803 return r > 0;
804 }
805
806 return 0;
807 }
808
809 int dhcp4_set_client_identifier(Link *link) {
810 int r;
811
812 assert(link);
813 assert(link->network);
814 assert(link->dhcp_client);
815
816 switch (link->network->dhcp_client_identifier) {
817 case DHCP_CLIENT_ID_DUID: {
818 /* If configured, apply user specified DUID and IAID */
819 const DUID *duid = link_get_duid(link);
820
821 if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
822 r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client,
823 link->network->iaid_set,
824 link->network->iaid,
825 duid->llt_time);
826 else
827 r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
828 link->network->iaid_set,
829 link->network->iaid,
830 duid->type,
831 duid->raw_data_len > 0 ? duid->raw_data : NULL,
832 duid->raw_data_len);
833 if (r < 0)
834 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IAID+DUID: %m");
835 break;
836 }
837 case DHCP_CLIENT_ID_DUID_ONLY: {
838 /* If configured, apply user specified DUID */
839 const DUID *duid = link_get_duid(link);
840
841 if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
842 r = sd_dhcp_client_set_duid_llt(link->dhcp_client,
843 duid->llt_time);
844 else
845 r = sd_dhcp_client_set_duid(link->dhcp_client,
846 duid->type,
847 duid->raw_data_len > 0 ? duid->raw_data : NULL,
848 duid->raw_data_len);
849 if (r < 0)
850 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
851 break;
852 }
853 case DHCP_CLIENT_ID_MAC:
854 r = sd_dhcp_client_set_client_id(link->dhcp_client,
855 ARPHRD_ETHER,
856 (const uint8_t *) &link->mac,
857 sizeof(link->mac));
858 if (r < 0)
859 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m");
860 break;
861 default:
862 assert_not_reached("Unknown client identifier type.");
863 }
864
865 return 0;
866 }
867
868 int dhcp4_configure(Link *link) {
869 int r;
870
871 assert(link);
872 assert(link->network);
873 assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
874
875 if (!link->dhcp_client) {
876 r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
877 if (r == -ENOMEM)
878 return log_oom();
879 if (r < 0)
880 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to create DHCP4 client: %m");
881 }
882
883 r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
884 if (r < 0)
885 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to attach event: %m");
886
887 r = sd_dhcp_client_set_mac(link->dhcp_client,
888 (const uint8_t *) &link->mac,
889 sizeof (link->mac), ARPHRD_ETHER);
890 if (r < 0)
891 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MAC address: %m");
892
893 r = sd_dhcp_client_set_ifindex(link->dhcp_client, link->ifindex);
894 if (r < 0)
895 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ifindex: %m");
896
897 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
898 if (r < 0)
899 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set callback: %m");
900
901 r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
902 link->network->dhcp_broadcast);
903 if (r < 0)
904 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for broadcast: %m");
905
906 if (link->mtu) {
907 r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
908 if (r < 0)
909 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MTU: %m");
910 }
911
912 if (link->network->dhcp_use_mtu) {
913 r = sd_dhcp_client_set_request_option(link->dhcp_client,
914 SD_DHCP_OPTION_INTERFACE_MTU);
915 if (r < 0)
916 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for MTU: %m");
917 }
918
919 /* NOTE: even if this variable is called "use", it also "sends" PRL
920 * options, maybe there should be a different configuration variable
921 * to send or not route options?. */
922 /* NOTE: when using Anonymize=yes, routes PRL options are sent
923 * by default, so they don't need to be added here. */
924 if (link->network->dhcp_use_routes && !link->network->dhcp_anonymize) {
925 r = sd_dhcp_client_set_request_option(link->dhcp_client,
926 SD_DHCP_OPTION_STATIC_ROUTE);
927 if (r < 0)
928 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for static route: %m");
929
930 r = sd_dhcp_client_set_request_option(link->dhcp_client,
931 SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
932 if (r < 0)
933 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for classless static route: %m");
934 }
935
936 if (link->network->dhcp_use_ntp) {
937 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
938 if (r < 0)
939 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for NTP server: %m");
940 }
941
942 if (link->network->dhcp_use_timezone) {
943 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
944 if (r < 0)
945 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for timezone: %m");
946 }
947
948 r = dhcp4_set_hostname(link);
949 if (r < 0)
950 return r;
951
952 if (link->network->dhcp_vendor_class_identifier) {
953 r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
954 link->network->dhcp_vendor_class_identifier);
955 if (r < 0)
956 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set vendor class identifier: %m");
957 }
958
959 if (link->network->dhcp_user_class) {
960 r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
961 if (r < 0)
962 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
963 }
964
965 if (link->network->dhcp_client_port) {
966 r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
967 if (r < 0)
968 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
969 }
970
971 if (link->network->dhcp_max_attempts > 0) {
972 r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts);
973 if (r < 0)
974 return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m");
975 }
976
977 return dhcp4_set_client_identifier(link);
978 }