]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-dhcp4.c
add ipv6 range element creation test cases
[thirdparty/systemd.git] / src / network / networkd-dhcp4.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <netinet/in.h>
4 #include <netinet/ip.h>
5 #include <linux/if.h>
6 #include <linux/if_arp.h>
7
8 #include "escape.h"
9 #include "alloc-util.h"
10 #include "dhcp-client-internal.h"
11 #include "hostname-setup.h"
12 #include "hostname-util.h"
13 #include "parse-util.h"
14 #include "network-internal.h"
15 #include "networkd-address.h"
16 #include "networkd-dhcp4.h"
17 #include "networkd-link.h"
18 #include "networkd-manager.h"
19 #include "networkd-network.h"
20 #include "string-table.h"
21 #include "strv.h"
22 #include "sysctl-util.h"
23 #include "web-util.h"
24
25 static int dhcp4_update_address(Link *link, bool announce);
26 static int dhcp4_remove_all(Link *link);
27
28 static int dhcp4_release_old_lease(Link *link) {
29 Route *route;
30 int k, r = 0;
31
32 assert(link);
33
34 if (!link->dhcp_address_old && set_isempty(link->dhcp_routes_old))
35 return 0;
36
37 log_link_debug(link, "Removing old DHCPv4 address and routes.");
38
39 link_dirty(link);
40
41 SET_FOREACH(route, link->dhcp_routes_old) {
42 k = route_remove(route, NULL, link, NULL);
43 if (k < 0)
44 r = k;
45 }
46
47 if (link->dhcp_address_old) {
48 k = address_remove(link->dhcp_address_old, link, NULL);
49 if (k < 0)
50 r = k;
51 }
52
53 return r;
54 }
55
56 static void dhcp4_check_ready(Link *link) {
57 int r;
58
59 if (link->network->dhcp_send_decline && !link->dhcp4_address_bind)
60 return;
61
62 if (link->dhcp4_messages > 0)
63 return;
64
65 link->dhcp4_configured = true;
66
67 /* New address and routes are configured now. Let's release old lease. */
68 r = dhcp4_release_old_lease(link);
69 if (r < 0) {
70 link_enter_failed(link);
71 return;
72 }
73
74 r = sd_ipv4ll_stop(link->ipv4ll);
75 if (r < 0)
76 log_link_warning_errno(link, r, "Failed to drop IPv4 link-local address, ignoring: %m");
77
78 link_check_ready(link);
79 }
80
81 static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
82 int r;
83
84 assert(link);
85 assert(link->dhcp4_messages > 0);
86
87 link->dhcp4_messages--;
88
89 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
90 return 1;
91
92 r = sd_netlink_message_get_errno(m);
93 if (r == -ENETUNREACH && !link->dhcp4_route_retrying) {
94
95 /* It seems kernel does not support that the prefix route cannot be configured with
96 * route table. Let's once drop the config and reconfigure them later. */
97
98 log_link_message_debug_errno(link, m, r, "Could not set DHCPv4 route, retrying later");
99 link->dhcp4_route_failed = true;
100 link->manager->dhcp4_prefix_root_cannot_set_table = true;
101 } else if (r < 0 && r != -EEXIST) {
102 log_link_message_warning_errno(link, m, r, "Could not set DHCPv4 route");
103 link_enter_failed(link);
104 return 1;
105 }
106
107 if (link->dhcp4_messages == 0 && link->dhcp4_route_failed) {
108 link->dhcp4_route_failed = false;
109 link->dhcp4_route_retrying = true;
110
111 r = dhcp4_remove_all(link);
112 if (r < 0)
113 link_enter_failed(link);
114 return 1;
115 }
116
117 dhcp4_check_ready(link);
118
119 return 1;
120 }
121
122 static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
123 assert(route);
124 assert(self_addr);
125
126 if (in4_addr_is_localhost(&route->dst.in) ||
127 (!in4_addr_is_null(self_addr) && in4_addr_equal(&route->dst.in, self_addr)))
128 return RT_SCOPE_HOST;
129 else if (in4_addr_is_null(&route->gw.in))
130 return RT_SCOPE_LINK;
131 else
132 return RT_SCOPE_UNIVERSE;
133 }
134
135 static bool link_prefixroute(Link *link) {
136 return !link->network->dhcp_route_table_set ||
137 link->network->dhcp_route_table == RT_TABLE_MAIN ||
138 link->manager->dhcp4_prefix_root_cannot_set_table;
139 }
140
141 static int dhcp_route_configure(Route *route, Link *link) {
142 Route *ret;
143 int r;
144
145 assert(route);
146 assert(link);
147
148 r = route_configure(route, link, dhcp4_route_handler, &ret);
149 if (r < 0)
150 return log_link_error_errno(link, r, "Failed to set DHCPv4 route: %m");
151
152 link->dhcp4_messages++;
153
154 r = set_ensure_put(&link->dhcp_routes, &route_hash_ops, ret);
155 if (r < 0)
156 return log_link_error_errno(link, r, "Failed to store DHCPv4 route: %m");
157
158 (void) set_remove(link->dhcp_routes_old, ret);
159
160 return 0;
161 }
162
163 static int link_set_dns_routes(Link *link, const struct in_addr *address) {
164 const struct in_addr *dns;
165 uint32_t table;
166 int n, r;
167
168 assert(link);
169 assert(link->dhcp_lease);
170 assert(link->network);
171
172 if (!link->network->dhcp_use_dns ||
173 !link->network->dhcp_routes_to_dns)
174 return 0;
175
176 n = sd_dhcp_lease_get_dns(link->dhcp_lease, &dns);
177 if (IN_SET(n, 0, -ENODATA))
178 return 0;
179 if (n < 0)
180 return log_link_warning_errno(link, n, "DHCP error: could not get DNS servers: %m");
181
182 table = link_get_dhcp_route_table(link);
183
184 for (int i = 0; i < n; i ++) {
185 _cleanup_(route_freep) Route *route = NULL;
186
187 r = route_new(&route);
188 if (r < 0)
189 return log_link_error_errno(link, r, "Could not allocate route: %m");
190
191 /* Set routes to DNS servers. */
192
193 route->family = AF_INET;
194 route->dst.in = dns[i];
195 route->dst_prefixlen = 32;
196 route->prefsrc.in = *address;
197 route->scope = RT_SCOPE_LINK;
198 route->protocol = RTPROT_DHCP;
199 route->priority = link->network->dhcp_route_metric;
200 route->table = table;
201
202 r = dhcp_route_configure(route, link);
203 if (r < 0)
204 return log_link_error_errno(link, r, "Could not set route to DNS server: %m");
205 }
206
207 return 0;
208 }
209
210 static int dhcp_prefix_route_from_lease(
211 const sd_dhcp_lease *lease,
212 uint32_t table,
213 const struct in_addr *address,
214 Route **ret_route) {
215
216 Route *route;
217 struct in_addr netmask;
218 int r;
219
220 r = sd_dhcp_lease_get_netmask((sd_dhcp_lease*) lease, &netmask);
221 if (r < 0)
222 return r;
223
224 r = route_new(&route);
225 if (r < 0)
226 return r;
227
228 route->family = AF_INET;
229 route->dst.in.s_addr = address->s_addr & netmask.s_addr;
230 route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
231 route->prefsrc.in = *address;
232 route->scope = RT_SCOPE_LINK;
233 route->protocol = RTPROT_DHCP;
234 route->table = table;
235 *ret_route = route;
236 return 0;
237 }
238
239 static int link_set_dhcp_routes(Link *link) {
240 _cleanup_free_ sd_dhcp_route **static_routes = NULL;
241 bool classless_route = false, static_route = false;
242 struct in_addr address;
243 uint32_t table;
244 Route *rt;
245 int r, n;
246
247 assert(link);
248
249 if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */
250 return 0;
251
252 if (!link->network) /* link went down while we configured the IP addresses? */
253 return 0;
254
255 if (!link_has_carrier(link) && !link->network->configure_without_carrier)
256 /* During configuring addresses, the link lost its carrier. As networkd is dropping
257 * the addresses now, let's not configure the routes either. */
258 return 0;
259
260 while ((rt = set_steal_first(link->dhcp_routes))) {
261 r = set_ensure_put(&link->dhcp_routes_old, &route_hash_ops, rt);
262 if (r < 0)
263 return log_link_error_errno(link, r, "Failed to store old DHCPv4 route: %m");
264 }
265
266 table = link_get_dhcp_route_table(link);
267
268 r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
269 if (r < 0)
270 return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
271
272 if (!link_prefixroute(link)) {
273 _cleanup_(route_freep) Route *prefix_route = NULL;
274
275 r = dhcp_prefix_route_from_lease(link->dhcp_lease, table, &address, &prefix_route);
276 if (r < 0)
277 return log_link_error_errno(link, r, "Could not create prefix route: %m");
278
279 r = dhcp_route_configure(prefix_route, link);
280 if (r < 0)
281 return log_link_error_errno(link, r, "Could not set prefix route: %m");
282 }
283
284 n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
285 if (n == -ENODATA)
286 log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m");
287 else if (n < 0)
288 return log_link_error_errno(link, n, "DHCP: could not get routes: %m");
289
290 for (int i = 0; i < n; i++) {
291 switch (sd_dhcp_route_get_option(static_routes[i])) {
292 case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
293 classless_route = true;
294 break;
295 case SD_DHCP_OPTION_STATIC_ROUTE:
296 static_route = true;
297 break;
298 }
299 }
300
301 if (link->network->dhcp_use_routes) {
302 /* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
303 * the DHCP client MUST ignore the Static Routes option. */
304 if (classless_route && static_route)
305 log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option");
306
307 for (int i = 0; i < n; i++) {
308 _cleanup_(route_freep) Route *route = NULL;
309
310 if (classless_route &&
311 sd_dhcp_route_get_option(static_routes[i]) != SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE)
312 continue;
313
314 r = route_new(&route);
315 if (r < 0)
316 return log_link_error_errno(link, r, "Could not allocate route: %m");
317
318 route->family = AF_INET;
319 route->protocol = RTPROT_DHCP;
320 route->gw_family = AF_INET;
321 assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
322 assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
323 assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
324 route->priority = link->network->dhcp_route_metric;
325 route->table = table;
326 route->mtu = link->network->dhcp_route_mtu;
327 route->scope = route_scope_from_address(route, &address);
328 if (IN_SET(route->scope, RT_SCOPE_LINK, RT_SCOPE_UNIVERSE))
329 route->prefsrc.in = address;
330
331 if (set_contains(link->dhcp_routes, route))
332 continue;
333
334 r = dhcp_route_configure(route, link);
335 if (r < 0)
336 return log_link_error_errno(link, r, "Could not set route: %m");
337 }
338 }
339
340 if (link->network->dhcp_use_gateway) {
341 const struct in_addr *router;
342
343 r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
344 if (IN_SET(r, 0, -ENODATA))
345 log_link_info(link, "DHCP: No gateway received from DHCP server.");
346 else if (r < 0)
347 return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
348 else if (in4_addr_is_null(&router[0]))
349 log_link_info(link, "DHCP: Received gateway is null.");
350 else if (classless_route)
351 /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
352 * a Router option, the DHCP client MUST ignore the Router option. */
353 log_link_warning(link, "Classless static routes received from DHCP server: ignoring router option");
354 else {
355 _cleanup_(route_freep) Route *route = NULL, *route_gw = NULL;
356
357 r = route_new(&route_gw);
358 if (r < 0)
359 return log_link_error_errno(link, r, "Could not allocate route: %m");
360
361 /* The dhcp netmask may mask out the gateway. Add an explicit
362 * route for the gw host so that we can route no matter the
363 * netmask or existing kernel route tables. */
364 route_gw->family = AF_INET;
365 route_gw->dst.in = router[0];
366 route_gw->dst_prefixlen = 32;
367 route_gw->prefsrc.in = address;
368 route_gw->scope = RT_SCOPE_LINK;
369 route_gw->protocol = RTPROT_DHCP;
370 route_gw->priority = link->network->dhcp_route_metric;
371 route_gw->table = table;
372 route_gw->mtu = link->network->dhcp_route_mtu;
373
374 r = dhcp_route_configure(route_gw, link);
375 if (r < 0)
376 return log_link_error_errno(link, r, "Could not set host route: %m");
377
378 r = route_new(&route);
379 if (r < 0)
380 return log_link_error_errno(link, r, "Could not allocate route: %m");
381
382 route->family = AF_INET;
383 route->gw_family = AF_INET;
384 route->gw.in = router[0];
385 route->prefsrc.in = address;
386 route->protocol = RTPROT_DHCP;
387 route->priority = link->network->dhcp_route_metric;
388 route->table = table;
389 route->mtu = link->network->dhcp_route_mtu;
390
391 r = dhcp_route_configure(route, link);
392 if (r < 0)
393 return log_link_error_errno(link, r, "Could not set router: %m");
394
395 HASHMAP_FOREACH(rt, link->network->routes_by_section) {
396 if (!rt->gateway_from_dhcp_or_ra)
397 continue;
398
399 if (rt->gw_family != AF_INET)
400 continue;
401
402 rt->gw.in = router[0];
403 if (!rt->protocol_set)
404 rt->protocol = RTPROT_DHCP;
405 if (!rt->priority_set)
406 rt->priority = link->network->dhcp_route_metric;
407 if (!rt->table_set)
408 rt->table = table;
409 if (rt->mtu == 0)
410 rt->mtu = link->network->dhcp_route_mtu;
411
412 r = dhcp_route_configure(rt, link);
413 if (r < 0)
414 return log_link_error_errno(link, r, "Could not set gateway: %m");
415 }
416 }
417 }
418
419 return link_set_dns_routes(link, &address);
420 }
421
422 static int dhcp_reset_mtu(Link *link) {
423 uint16_t mtu;
424 int r;
425
426 assert(link);
427
428 if (!link->network->dhcp_use_mtu)
429 return 0;
430
431 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
432 if (r == -ENODATA)
433 return 0;
434 if (r < 0)
435 return log_link_error_errno(link, r, "DHCP error: failed to get MTU from lease: %m");
436
437 if (link->original_mtu == mtu)
438 return 0;
439
440 r = link_set_mtu(link, link->original_mtu);
441 if (r < 0)
442 return log_link_error_errno(link, r, "DHCP error: could not reset MTU: %m");
443
444 return 0;
445 }
446
447 static int dhcp_reset_hostname(Link *link) {
448 const char *hostname;
449 int r;
450
451 assert(link);
452
453 if (!link->network->dhcp_use_hostname)
454 return 0;
455
456 hostname = link->network->dhcp_hostname;
457 if (!hostname)
458 (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
459
460 if (!hostname)
461 return 0;
462
463 /* If a hostname was set due to the lease, then unset it now. */
464 r = manager_set_hostname(link->manager, NULL);
465 if (r < 0)
466 return log_link_error_errno(link, r, "DHCP error: Failed to reset transient hostname: %m");
467
468 return 0;
469 }
470
471 static int dhcp4_remove_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
472 int r;
473
474 assert(m);
475 assert(link);
476 assert(link->dhcp4_remove_messages > 0);
477
478 link->dhcp4_remove_messages--;
479
480 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
481 return 1;
482
483 r = sd_netlink_message_get_errno(m);
484 if (r < 0 && r != -ESRCH)
485 log_link_message_warning_errno(link, m, r, "Failed to remove DHCPv4 route, ignoring");
486
487 if (link->dhcp4_remove_messages == 0) {
488 r = dhcp4_update_address(link, false);
489 if (r < 0)
490 link_enter_failed(link);
491 }
492
493 return 1;
494 }
495
496 static int dhcp4_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
497 int r;
498
499 assert(m);
500 assert(link);
501 assert(link->dhcp4_remove_messages > 0);
502
503 link->dhcp4_remove_messages--;
504
505 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
506 return 1;
507
508 r = sd_netlink_message_get_errno(m);
509 if (r < 0 && r != -EADDRNOTAVAIL)
510 log_link_message_warning_errno(link, m, r, "Failed to remove DHCPv4 address, ignoring");
511 else
512 (void) manager_rtnl_process_address(rtnl, m, link->manager);
513
514 if (link->dhcp4_remove_messages == 0) {
515 r = dhcp4_update_address(link, false);
516 if (r < 0)
517 link_enter_failed(link);
518 }
519
520 return 1;
521 }
522
523 static int dhcp4_remove_all(Link *link) {
524 Route *route;
525 int k, r = 0;
526
527 assert(link);
528
529 SET_FOREACH(route, link->dhcp_routes) {
530 k = route_remove(route, NULL, link, dhcp4_remove_route_handler);
531 if (k < 0)
532 r = k;
533 else
534 link->dhcp4_remove_messages++;
535 }
536
537 if (link->dhcp_address) {
538 k = address_remove(link->dhcp_address, link, dhcp4_remove_address_handler);
539 if (k < 0)
540 r = k;
541 else
542 link->dhcp4_remove_messages++;
543 }
544
545 return r;
546 }
547
548 static int dhcp_lease_lost(Link *link) {
549 int k, r = 0;
550
551 assert(link);
552 assert(link->dhcp_lease);
553
554 log_link_info(link, "DHCP lease lost");
555
556 link->dhcp4_configured = false;
557
558 /* dhcp_lease_lost() may be called during renewing IP address. */
559 k = dhcp4_release_old_lease(link);
560 if (k < 0)
561 r = k;
562
563 k = dhcp4_remove_all(link);
564 if (k < 0)
565 r = k;
566
567 k = dhcp_reset_mtu(link);
568 if (k < 0)
569 r = k;
570
571 k = dhcp_reset_hostname(link);
572 if (k < 0)
573 r = k;
574
575 link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
576 link_dirty(link);
577
578 (void) sd_ipv4acd_stop(link->dhcp_acd);
579
580 return r;
581 }
582
583 static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
584 _cleanup_free_ char *pretty = NULL;
585 union in_addr_union address = {};
586 Link *link;
587 int r;
588
589 assert(acd);
590 assert(userdata);
591
592 link = userdata;
593
594 switch (event) {
595 case SD_IPV4ACD_EVENT_STOP:
596 log_link_debug(link, "Stopping ACD client for DHCP4...");
597 return;
598
599 case SD_IPV4ACD_EVENT_BIND:
600 if (DEBUG_LOGGING) {
601 (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address.in);
602 (void) in_addr_to_string(AF_INET, &address, &pretty);
603 log_link_debug(link, "Successfully claimed DHCP4 address %s", strna(pretty));
604 }
605 link->dhcp4_address_bind = true;
606 dhcp4_check_ready(link);
607 break;
608
609 case SD_IPV4ACD_EVENT_CONFLICT:
610 (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address.in);
611 (void) in_addr_to_string(AF_INET, &address, &pretty);
612 log_link_warning(link, "DAD conflict. Dropping DHCP4 address %s", strna(pretty));
613
614 r = sd_dhcp_client_send_decline(link->dhcp_client);
615 if (r < 0)
616 log_link_warning_errno(link, r, "Failed to send DHCP DECLINE, ignoring: %m");
617
618 if (link->dhcp_lease) {
619 r = dhcp_lease_lost(link);
620 if (r < 0)
621 link_enter_failed(link);
622 }
623 break;
624
625 default:
626 assert_not_reached("Invalid IPv4ACD event.");
627 }
628
629 (void) sd_ipv4acd_stop(acd);
630
631 return;
632 }
633
634 static int dhcp4_configure_dad(Link *link) {
635 int r;
636
637 assert(link);
638 assert(link->manager);
639 assert(link->network);
640
641 if (!link->network->dhcp_send_decline)
642 return 0;
643
644 if (!link->dhcp_acd) {
645 r = sd_ipv4acd_new(&link->dhcp_acd);
646 if (r < 0)
647 return r;
648
649 r = sd_ipv4acd_attach_event(link->dhcp_acd, link->manager->event, 0);
650 if (r < 0)
651 return r;
652 }
653
654 r = sd_ipv4acd_set_ifindex(link->dhcp_acd, link->ifindex);
655 if (r < 0)
656 return r;
657
658 r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->hw_addr.addr.ether);
659 if (r < 0)
660 return r;
661
662 return 0;
663 }
664
665 static int dhcp4_dad_update_mac(Link *link) {
666 bool running;
667 int r;
668
669 assert(link);
670
671 if (!link->dhcp_acd)
672 return 0;
673
674 running = sd_ipv4acd_is_running(link->dhcp_acd);
675
676 r = sd_ipv4acd_stop(link->dhcp_acd);
677 if (r < 0)
678 return r;
679
680 r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->hw_addr.addr.ether);
681 if (r < 0)
682 return r;
683
684 if (running) {
685 r = sd_ipv4acd_start(link->dhcp_acd, true);
686 if (r < 0)
687 return r;
688 }
689
690 return 0;
691 }
692
693 static int dhcp4_start_acd(Link *link) {
694 union in_addr_union addr;
695 struct in_addr old;
696 int r;
697
698 if (!link->network->dhcp_send_decline)
699 return 0;
700
701 if (!link->dhcp_lease)
702 return 0;
703
704 (void) sd_ipv4acd_stop(link->dhcp_acd);
705
706 link->dhcp4_address_bind = false;
707
708 r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr.in);
709 if (r < 0)
710 return r;
711
712 r = sd_ipv4acd_get_address(link->dhcp_acd, &old);
713 if (r < 0)
714 return r;
715
716 r = sd_ipv4acd_set_address(link->dhcp_acd, &addr.in);
717 if (r < 0)
718 return r;
719
720 r = sd_ipv4acd_set_callback(link->dhcp_acd, dhcp_address_on_acd, link);
721 if (r < 0)
722 return r;
723
724 if (DEBUG_LOGGING) {
725 _cleanup_free_ char *pretty = NULL;
726
727 (void) in_addr_to_string(AF_INET, &addr, &pretty);
728 log_link_debug(link, "Starting IPv4ACD client. Probing DHCPv4 address %s", strna(pretty));
729 }
730
731 r = sd_ipv4acd_start(link->dhcp_acd, !in4_addr_equal(&addr.in, &old));
732 if (r < 0)
733 return r;
734
735 return 1;
736 }
737
738 static int dhcp4_address_ready_callback(Address *address) {
739 Link *link;
740 int r;
741
742 assert(address);
743
744 link = address->link;
745
746 /* Do not call this again. */
747 address->callback = NULL;
748
749 r = link_set_dhcp_routes(link);
750 if (r < 0)
751 return r;
752
753 /* Reconfigure static routes as kernel may remove some routes when lease expires. */
754 r = link_set_routes(link);
755 if (r < 0)
756 return r;
757
758 r = dhcp4_start_acd(link);
759 if (r < 0)
760 return log_link_error_errno(link, r, "Failed to start IPv4ACD for DHCP4 address: %m");
761
762 dhcp4_check_ready(link);
763 return 0;
764 }
765
766 static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
767 int r;
768
769 assert(link);
770
771 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
772 return 1;
773
774 r = sd_netlink_message_get_errno(m);
775 if (r < 0 && r != -EEXIST) {
776 log_link_message_warning_errno(link, m, r, "Could not set DHCPv4 address");
777 link_enter_failed(link);
778 return 1;
779 } else if (r >= 0)
780 (void) manager_rtnl_process_address(rtnl, m, link->manager);
781
782 if (address_is_ready(link->dhcp_address)) {
783 r = dhcp4_address_ready_callback(link->dhcp_address);
784 if (r < 0) {
785 link_enter_failed(link);
786 return 1;
787 }
788 } else
789 link->dhcp_address->callback = dhcp4_address_ready_callback;
790
791 return 1;
792 }
793
794 static int dhcp4_update_address(Link *link, bool announce) {
795 _cleanup_(address_freep) Address *addr = NULL;
796 uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
797 struct in_addr address, netmask;
798 unsigned prefixlen;
799 Address *ret;
800 int r;
801
802 assert(link);
803 assert(link->network);
804
805 if (!link->dhcp_lease)
806 return 0;
807
808 link_set_state(link, LINK_STATE_CONFIGURING);
809 link->dhcp4_configured = false;
810
811 /* address_handler calls link_set_routes() and link_set_nexthop(). Before they are called, the
812 * related flags must be cleared. Otherwise, the link becomes configured state before routes
813 * are configured. */
814 link->static_routes_configured = false;
815 link->static_nexthops_configured = false;
816
817 r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
818 if (r < 0)
819 return log_link_warning_errno(link, r, "DHCP error: no address: %m");
820
821 r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
822 if (r < 0)
823 return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
824
825 if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
826 r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
827 if (r < 0)
828 return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
829 }
830
831 prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
832
833 if (announce) {
834 const struct in_addr *router;
835
836 r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
837 if (r < 0 && r != -ENODATA)
838 return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
839
840 if (r > 0 && !in4_addr_is_null(&router[0]))
841 log_struct(LOG_INFO,
842 LOG_LINK_INTERFACE(link),
843 LOG_LINK_MESSAGE(link, "DHCPv4 address "IPV4_ADDRESS_FMT_STR"/%u via "IPV4_ADDRESS_FMT_STR,
844 IPV4_ADDRESS_FMT_VAL(address),
845 prefixlen,
846 IPV4_ADDRESS_FMT_VAL(router[0])),
847 "ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address),
848 "PREFIXLEN=%u", prefixlen,
849 "GATEWAY="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(router[0]));
850 else
851 log_struct(LOG_INFO,
852 LOG_LINK_INTERFACE(link),
853 LOG_LINK_MESSAGE(link, "DHCPv4 address "IPV4_ADDRESS_FMT_STR"/%u",
854 IPV4_ADDRESS_FMT_VAL(address),
855 prefixlen),
856 "ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address),
857 "PREFIXLEN=%u", prefixlen);
858 }
859
860 r = address_new(&addr);
861 if (r < 0)
862 return log_oom();
863
864 addr->family = AF_INET;
865 addr->in_addr.in.s_addr = address.s_addr;
866 addr->cinfo.ifa_prefered = lifetime;
867 addr->cinfo.ifa_valid = lifetime;
868 addr->prefixlen = prefixlen;
869 if (prefixlen <= 30)
870 addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
871 SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link));
872
873 /* allow reusing an existing address and simply update its lifetime
874 * in case it already exists */
875 r = address_configure(addr, link, dhcp4_address_handler, true, &ret);
876 if (r < 0)
877 return log_link_error_errno(link, r, "Failed to set DHCPv4 address: %m");
878
879 if (!address_equal(link->dhcp_address, ret))
880 link->dhcp_address_old = link->dhcp_address;
881 link->dhcp_address = ret;
882
883 return 0;
884 }
885
886 static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
887 sd_dhcp_lease *lease;
888 int r;
889
890 assert(link);
891 assert(client);
892
893 r = sd_dhcp_client_get_lease(client, &lease);
894 if (r < 0)
895 return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
896
897 sd_dhcp_lease_unref(link->dhcp_lease);
898 link->dhcp_lease = sd_dhcp_lease_ref(lease);
899 link_dirty(link);
900
901 return dhcp4_update_address(link, false);
902 }
903
904 static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
905 sd_dhcp_lease *lease;
906 int r;
907
908 assert(client);
909 assert(link);
910
911 r = sd_dhcp_client_get_lease(client, &lease);
912 if (r < 0)
913 return log_link_error_errno(link, r, "DHCP error: No lease: %m");
914
915 sd_dhcp_lease_unref(link->dhcp_lease);
916 link->dhcp_lease = sd_dhcp_lease_ref(lease);
917 link_dirty(link);
918
919 if (link->network->dhcp_use_mtu) {
920 uint16_t mtu;
921
922 r = sd_dhcp_lease_get_mtu(lease, &mtu);
923 if (r >= 0) {
924 r = link_set_mtu(link, mtu);
925 if (r < 0)
926 log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
927 }
928 }
929
930 if (link->network->dhcp_use_hostname) {
931 const char *dhcpname = NULL;
932 _cleanup_free_ char *hostname = NULL;
933
934 if (link->network->dhcp_hostname)
935 dhcpname = link->network->dhcp_hostname;
936 else
937 (void) sd_dhcp_lease_get_hostname(lease, &dhcpname);
938
939 if (dhcpname) {
940 r = shorten_overlong(dhcpname, &hostname);
941 if (r < 0)
942 log_link_warning_errno(link, r, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname);
943 if (r == 1)
944 log_link_notice(link, "Overlong DHCP hostname received, shortened from '%s' to '%s'", dhcpname, hostname);
945 }
946
947 if (hostname) {
948 r = manager_set_hostname(link->manager, hostname);
949 if (r < 0)
950 log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
951 }
952 }
953
954 if (link->network->dhcp_use_timezone) {
955 const char *tz = NULL;
956
957 (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
958
959 if (tz) {
960 r = manager_set_timezone(link->manager, tz);
961 if (r < 0)
962 log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
963 }
964 }
965
966 if (link->dhcp4_remove_messages == 0) {
967 r = dhcp4_update_address(link, true);
968 if (r < 0)
969 return r;
970 } else
971 log_link_debug(link,
972 "The link has previously assigned DHCPv4 address or routes. "
973 "The newly assigned address and routes will set up after old ones are removed.");
974
975 return 0;
976 }
977
978 static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) {
979 int r;
980
981 r = dhcp_lease_acquired(client, link);
982 if (r < 0)
983 (void) dhcp_lease_lost(link);
984
985 return r;
986 }
987
988 static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) {
989 sd_dhcp_lease *lease;
990 struct in_addr addr;
991 int r;
992
993 assert(link);
994 assert(link->network);
995 assert(client);
996
997 r = sd_dhcp_client_get_lease(client, &lease);
998 if (r < 0)
999 return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
1000
1001 r = sd_dhcp_lease_get_server_identifier(lease, &addr);
1002 if (r < 0)
1003 return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m");
1004
1005 if (set_contains(link->network->dhcp_deny_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
1006 log_struct(LOG_DEBUG,
1007 LOG_LINK_INTERFACE(link),
1008 LOG_LINK_MESSAGE(link, "DHCPv4 server IP address "IPV4_ADDRESS_FMT_STR" found in deny-list, ignoring offer",
1009 IPV4_ADDRESS_FMT_VAL(addr)));
1010 return true;
1011 }
1012
1013 return false;
1014 }
1015
1016 static int dhcp_server_is_allow_listed(Link *link, sd_dhcp_client *client) {
1017 sd_dhcp_lease *lease;
1018 struct in_addr addr;
1019 int r;
1020
1021 assert(link);
1022 assert(link->network);
1023 assert(client);
1024
1025 r = sd_dhcp_client_get_lease(client, &lease);
1026 if (r < 0)
1027 return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
1028
1029 r = sd_dhcp_lease_get_server_identifier(lease, &addr);
1030 if (r < 0)
1031 return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m");
1032
1033 if (set_contains(link->network->dhcp_allow_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
1034 log_struct(LOG_DEBUG,
1035 LOG_LINK_INTERFACE(link),
1036 LOG_LINK_MESSAGE(link, "DHCPv4 server IP address "IPV4_ADDRESS_FMT_STR" found in allow-list, accepting offer",
1037 IPV4_ADDRESS_FMT_VAL(addr)));
1038 return true;
1039 }
1040
1041 return false;
1042 }
1043
1044 static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
1045 Link *link = userdata;
1046 int r;
1047
1048 assert(link);
1049 assert(link->network);
1050 assert(link->manager);
1051
1052 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1053 return 0;
1054
1055 switch (event) {
1056 case SD_DHCP_CLIENT_EVENT_STOP:
1057 if (link->ipv4ll) {
1058 log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
1059
1060 r = sd_ipv4ll_start(link->ipv4ll);
1061 if (r < 0)
1062 return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
1063 }
1064
1065 if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
1066 log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it.");
1067 return 0;
1068 }
1069
1070 if (link->dhcp_lease) {
1071 if (link->network->dhcp_send_release) {
1072 r = sd_dhcp_client_send_release(client);
1073 if (r < 0)
1074 log_link_warning_errno(link, r, "Failed to send DHCP RELEASE, ignoring: %m");
1075 }
1076
1077 r = dhcp_lease_lost(link);
1078 if (r < 0) {
1079 link_enter_failed(link);
1080 return r;
1081 }
1082 }
1083
1084 break;
1085 case SD_DHCP_CLIENT_EVENT_EXPIRED:
1086 if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
1087 log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it.");
1088 return 0;
1089 }
1090
1091 if (link->dhcp_lease) {
1092 r = dhcp_lease_lost(link);
1093 if (r < 0) {
1094 link_enter_failed(link);
1095 return r;
1096 }
1097 }
1098
1099 break;
1100 case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
1101 if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
1102 log_link_notice(link, "DHCPv4 connection considered critical, ignoring request to reconfigure it.");
1103 return 0;
1104 }
1105
1106 r = dhcp_lease_ip_change(client, link);
1107 if (r < 0) {
1108 link_enter_failed(link);
1109 return r;
1110 }
1111
1112 break;
1113 case SD_DHCP_CLIENT_EVENT_RENEW:
1114 r = dhcp_lease_renew(client, link);
1115 if (r < 0) {
1116 link_enter_failed(link);
1117 return r;
1118 }
1119 break;
1120 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
1121 r = dhcp_lease_acquired(client, link);
1122 if (r < 0) {
1123 link_enter_failed(link);
1124 return r;
1125 }
1126 break;
1127 case SD_DHCP_CLIENT_EVENT_SELECTING:
1128 if (!set_isempty(link->network->dhcp_allow_listed_ip)) {
1129 r = dhcp_server_is_allow_listed(link, client);
1130 if (r < 0)
1131 return r;
1132 if (r == 0)
1133 return -ENOMSG;
1134 } else {
1135 r = dhcp_server_is_deny_listed(link, client);
1136 if (r < 0)
1137 return r;
1138 if (r != 0)
1139 return -ENOMSG;
1140 }
1141 break;
1142
1143 case SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE:
1144 if (link->ipv4ll && !sd_ipv4ll_is_running(link->ipv4ll)) {
1145 log_link_debug(link, "Problems acquiring DHCP lease, acquiring IPv4 link-local address");
1146
1147 r = sd_ipv4ll_start(link->ipv4ll);
1148 if (r < 0)
1149 return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
1150 }
1151 break;
1152
1153 default:
1154 if (event < 0)
1155 log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
1156 else
1157 log_link_warning(link, "DHCP unknown event: %i", event);
1158 break;
1159 }
1160
1161 return 0;
1162 }
1163
1164 static int dhcp4_set_hostname(Link *link) {
1165 _cleanup_free_ char *hostname = NULL;
1166 const char *hn;
1167 int r;
1168
1169 assert(link);
1170
1171 if (!link->network->dhcp_send_hostname)
1172 hn = NULL;
1173 else if (link->network->dhcp_hostname)
1174 hn = link->network->dhcp_hostname;
1175 else {
1176 r = gethostname_strict(&hostname);
1177 if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */
1178 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to get hostname: %m");
1179
1180 hn = hostname;
1181 }
1182
1183 r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
1184 if (r == -EINVAL && hostname)
1185 /* Ignore error when the machine's hostname is not suitable to send in DHCP packet. */
1186 log_link_debug_errno(link, r, "DHCP4 CLIENT: Failed to set hostname from kernel hostname, ignoring: %m");
1187 else if (r < 0)
1188 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set hostname: %m");
1189
1190 return 0;
1191 }
1192
1193 static int dhcp4_set_client_identifier(Link *link) {
1194 int r;
1195
1196 assert(link);
1197 assert(link->network);
1198 assert(link->dhcp_client);
1199
1200 switch (link->network->dhcp_client_identifier) {
1201 case DHCP_CLIENT_ID_DUID: {
1202 /* If configured, apply user specified DUID and IAID */
1203 const DUID *duid = link_get_duid(link);
1204
1205 if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
1206 r = sd_dhcp_client_set_iaid_duid_llt(link->dhcp_client,
1207 link->network->iaid_set,
1208 link->network->iaid,
1209 duid->llt_time);
1210 else
1211 r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
1212 link->network->iaid_set,
1213 link->network->iaid,
1214 duid->type,
1215 duid->raw_data_len > 0 ? duid->raw_data : NULL,
1216 duid->raw_data_len);
1217 if (r < 0)
1218 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set IAID+DUID: %m");
1219 break;
1220 }
1221 case DHCP_CLIENT_ID_DUID_ONLY: {
1222 /* If configured, apply user specified DUID */
1223 const DUID *duid = link_get_duid(link);
1224
1225 if (duid->type == DUID_TYPE_LLT && duid->raw_data_len == 0)
1226 r = sd_dhcp_client_set_duid_llt(link->dhcp_client,
1227 duid->llt_time);
1228 else
1229 r = sd_dhcp_client_set_duid(link->dhcp_client,
1230 duid->type,
1231 duid->raw_data_len > 0 ? duid->raw_data : NULL,
1232 duid->raw_data_len);
1233 if (r < 0)
1234 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
1235 break;
1236 }
1237 case DHCP_CLIENT_ID_MAC: {
1238 const uint8_t *hw_addr = link->hw_addr.addr.bytes;
1239 size_t hw_addr_len = link->hw_addr.length;
1240
1241 if (link->iftype == ARPHRD_INFINIBAND && hw_addr_len == INFINIBAND_ALEN) {
1242 /* set_client_id expects only last 8 bytes of an IB address */
1243 hw_addr += INFINIBAND_ALEN - 8;
1244 hw_addr_len -= INFINIBAND_ALEN - 8;
1245 }
1246
1247 r = sd_dhcp_client_set_client_id(link->dhcp_client,
1248 link->iftype,
1249 hw_addr,
1250 hw_addr_len);
1251 if (r < 0)
1252 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m");
1253 break;
1254 }
1255 default:
1256 assert_not_reached("Unknown client identifier type.");
1257 }
1258
1259 return 0;
1260 }
1261
1262 static int dhcp4_set_request_address(Link *link) {
1263 Address *a;
1264
1265 assert(link);
1266 assert(link->network);
1267 assert(link->dhcp_client);
1268
1269 if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
1270 return 0;
1271
1272 SET_FOREACH(a, link->addresses_foreign) {
1273 if (a->family != AF_INET)
1274 continue;
1275 if (link_address_is_dynamic(link, a))
1276 break;
1277 }
1278
1279 if (!a)
1280 return 0;
1281
1282 log_link_debug(link, "DHCP4 CLIENT: requesting " IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(a->in_addr.in));
1283
1284 return sd_dhcp_client_set_request_address(link->dhcp_client, &a->in_addr.in);
1285 }
1286
1287 int dhcp4_configure(Link *link) {
1288 sd_dhcp_option *send_option;
1289 void *request_options;
1290 int r;
1291
1292 assert(link);
1293 assert(link->network);
1294
1295 if (!link_dhcp4_enabled(link))
1296 return 0;
1297
1298 if (!link->dhcp_client) {
1299 r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
1300 if (r < 0)
1301 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to allocate DHCP4 client: %m");
1302
1303 r = sd_dhcp_client_attach_event(link->dhcp_client, link->manager->event, 0);
1304 if (r < 0)
1305 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to attach event to DHCP4 client: %m");
1306 }
1307
1308 r = sd_dhcp_client_set_mac(link->dhcp_client,
1309 link->hw_addr.addr.bytes,
1310 link->bcast_addr.length > 0 ? link->bcast_addr.addr.bytes : NULL,
1311 link->hw_addr.length, link->iftype);
1312 if (r < 0)
1313 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set MAC address: %m");
1314
1315 r = sd_dhcp_client_set_ifindex(link->dhcp_client, link->ifindex);
1316 if (r < 0)
1317 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set ifindex: %m");
1318
1319 r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
1320 if (r < 0)
1321 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set callback: %m");
1322
1323 r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, link->network->dhcp_broadcast);
1324 if (r < 0)
1325 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for broadcast: %m");
1326
1327 if (link->mtu > 0) {
1328 r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
1329 if (r < 0)
1330 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set MTU: %m");
1331 }
1332
1333 if (link->network->dhcp_use_mtu) {
1334 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_INTERFACE_MTU);
1335 if (r < 0)
1336 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for MTU: %m");
1337 }
1338
1339 /* NOTE: even if this variable is called "use", it also "sends" PRL
1340 * options, maybe there should be a different configuration variable
1341 * to send or not route options?. */
1342 /* NOTE: when using Anonymize=yes, routes PRL options are sent
1343 * by default, so they don't need to be added here. */
1344 if (link->network->dhcp_use_routes && !link->network->dhcp_anonymize) {
1345 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_STATIC_ROUTE);
1346 if (r < 0)
1347 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for static route: %m");
1348
1349 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
1350 if (r < 0)
1351 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for classless static route: %m");
1352 }
1353
1354 if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO && !link->network->dhcp_anonymize) {
1355 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST);
1356 if (r < 0)
1357 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for domain search list: %m");
1358 }
1359
1360 if (link->network->dhcp_use_ntp) {
1361 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
1362 if (r < 0)
1363 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for NTP server: %m");
1364 }
1365
1366 if (link->network->dhcp_use_sip) {
1367 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_SIP_SERVER);
1368 if (r < 0)
1369 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for SIP server: %m");
1370 }
1371
1372 if (link->network->dhcp_use_timezone) {
1373 r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
1374 if (r < 0)
1375 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for timezone: %m");
1376 }
1377
1378 SET_FOREACH(request_options, link->network->dhcp_request_options) {
1379 uint32_t option = PTR_TO_UINT32(request_options);
1380
1381 r = sd_dhcp_client_set_request_option(link->dhcp_client, option);
1382 if (r < 0)
1383 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for '%u': %m", option);
1384 }
1385
1386 ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_options) {
1387 r = sd_dhcp_client_add_option(link->dhcp_client, send_option);
1388 if (r == -EEXIST)
1389 continue;
1390 if (r < 0)
1391 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m");
1392 }
1393
1394 ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_vendor_options) {
1395 r = sd_dhcp_client_add_vendor_option(link->dhcp_client, send_option);
1396 if (r == -EEXIST)
1397 continue;
1398 if (r < 0)
1399 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m");
1400 }
1401
1402 r = dhcp4_set_hostname(link);
1403 if (r < 0)
1404 return r;
1405
1406 if (link->network->dhcp_vendor_class_identifier) {
1407 r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
1408 link->network->dhcp_vendor_class_identifier);
1409 if (r < 0)
1410 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set vendor class identifier: %m");
1411 }
1412
1413 if (link->network->dhcp_mudurl) {
1414 r = sd_dhcp_client_set_mud_url(link->dhcp_client, link->network->dhcp_mudurl);
1415 if (r < 0)
1416 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set MUD URL: %m");
1417 }
1418
1419 if (link->network->dhcp_user_class) {
1420 r = sd_dhcp_client_set_user_class(link->dhcp_client, link->network->dhcp_user_class);
1421 if (r < 0)
1422 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
1423 }
1424
1425 if (link->network->dhcp_client_port > 0) {
1426 r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
1427 if (r < 0)
1428 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
1429 }
1430
1431 if (link->network->dhcp_max_attempts > 0) {
1432 r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts);
1433 if (r < 0)
1434 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set max attempts: %m");
1435 }
1436
1437 if (link->network->dhcp_ip_service_type > 0) {
1438 r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->dhcp_ip_service_type);
1439 if (r < 0)
1440 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set IP service type: %m");
1441 }
1442
1443 if (link->network->dhcp_fallback_lease_lifetime > 0) {
1444 r = sd_dhcp_client_set_fallback_lease_lifetime(link->dhcp_client, link->network->dhcp_fallback_lease_lifetime);
1445 if (r < 0)
1446 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed set to lease lifetime: %m");
1447 }
1448
1449 r = dhcp4_set_request_address(link);
1450 if (r < 0)
1451 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set initial DHCPv4 address: %m");
1452
1453 r = dhcp4_configure_dad(link);
1454 if (r < 0)
1455 return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to configure service type: %m");
1456
1457 return dhcp4_set_client_identifier(link);
1458 }
1459
1460 int dhcp4_update_mac(Link *link) {
1461 int r;
1462
1463 assert(link);
1464
1465 if (!link->dhcp_client)
1466 return 0;
1467
1468 r = sd_dhcp_client_set_mac(link->dhcp_client, link->hw_addr.addr.bytes,
1469 link->bcast_addr.length > 0 ? link->bcast_addr.addr.bytes : NULL,
1470 link->hw_addr.length, link->iftype);
1471 if (r < 0)
1472 return r;
1473
1474 r = dhcp4_set_client_identifier(link);
1475 if (r < 0)
1476 return r;
1477
1478 r = dhcp4_dad_update_mac(link);
1479 if (r < 0)
1480 return r;
1481
1482 return 0;
1483 }
1484
1485 int config_parse_dhcp_max_attempts(
1486 const char *unit,
1487 const char *filename,
1488 unsigned line,
1489 const char *section,
1490 unsigned section_line,
1491 const char *lvalue,
1492 int ltype,
1493 const char *rvalue,
1494 void *data,
1495 void *userdata) {
1496
1497 Network *network = data;
1498 uint64_t a;
1499 int r;
1500
1501 assert(network);
1502 assert(lvalue);
1503 assert(rvalue);
1504
1505 if (isempty(rvalue)) {
1506 network->dhcp_max_attempts = 0;
1507 return 0;
1508 }
1509
1510 if (streq(rvalue, "infinity")) {
1511 network->dhcp_max_attempts = (uint64_t) -1;
1512 return 0;
1513 }
1514
1515 r = safe_atou64(rvalue, &a);
1516 if (r < 0) {
1517 log_syntax(unit, LOG_WARNING, filename, line, r,
1518 "Failed to parse DHCP maximum attempts, ignoring: %s", rvalue);
1519 return 0;
1520 }
1521
1522 if (a == 0) {
1523 log_syntax(unit, LOG_WARNING, filename, line, 0,
1524 "%s= must be positive integer or 'infinity', ignoring: %s", lvalue, rvalue);
1525 return 0;
1526 }
1527
1528 network->dhcp_max_attempts = a;
1529
1530 return 0;
1531 }
1532
1533 int config_parse_dhcp_acl_ip_address(
1534 const char *unit,
1535 const char *filename,
1536 unsigned line,
1537 const char *section,
1538 unsigned section_line,
1539 const char *lvalue,
1540 int ltype,
1541 const char *rvalue,
1542 void *data,
1543 void *userdata) {
1544
1545 Network *network = data;
1546 Set **acl;
1547 int r;
1548
1549 assert(filename);
1550 assert(lvalue);
1551 assert(rvalue);
1552 assert(data);
1553
1554 acl = STR_IN_SET(lvalue, "DenyList", "BlackList") ? &network->dhcp_deny_listed_ip : &network->dhcp_allow_listed_ip;
1555
1556 if (isempty(rvalue)) {
1557 *acl = set_free(*acl);
1558 return 0;
1559 }
1560
1561 for (const char *p = rvalue;;) {
1562 _cleanup_free_ char *n = NULL;
1563 union in_addr_union ip;
1564
1565 r = extract_first_word(&p, &n, NULL, 0);
1566 if (r == -ENOMEM)
1567 return log_oom();
1568 if (r < 0) {
1569 log_syntax(unit, LOG_WARNING, filename, line, r,
1570 "Failed to parse DHCP '%s=' IP address, ignoring assignment: %s",
1571 lvalue, rvalue);
1572 return 0;
1573 }
1574 if (r == 0)
1575 return 0;
1576
1577 r = in_addr_from_string(AF_INET, n, &ip);
1578 if (r < 0) {
1579 log_syntax(unit, LOG_WARNING, filename, line, r,
1580 "DHCP '%s=' IP address is invalid, ignoring assignment: %s", lvalue, n);
1581 continue;
1582 }
1583
1584 r = set_ensure_put(acl, NULL, UINT32_TO_PTR(ip.in.s_addr));
1585 if (r < 0)
1586 log_syntax(unit, LOG_WARNING, filename, line, r,
1587 "Failed to store DHCP '%s=' IP address '%s', ignoring assignment: %m", lvalue, n);
1588 }
1589 }
1590
1591 int config_parse_dhcp_ip_service_type(
1592 const char *unit,
1593 const char *filename,
1594 unsigned line,
1595 const char *section,
1596 unsigned section_line,
1597 const char *lvalue,
1598 int ltype,
1599 const char *rvalue,
1600 void *data,
1601 void *userdata) {
1602
1603 assert(filename);
1604 assert(lvalue);
1605 assert(rvalue);
1606
1607 if (streq(rvalue, "CS4"))
1608 *((int *)data) = IPTOS_CLASS_CS4;
1609 else if (streq(rvalue, "CS6"))
1610 *((int *)data) = IPTOS_CLASS_CS6;
1611 else
1612 log_syntax(unit, LOG_WARNING, filename, line, 0,
1613 "Failed to parse IPServiceType type '%s', ignoring.", rvalue);
1614
1615 return 0;
1616 }
1617
1618 int config_parse_dhcp_mud_url(
1619 const char *unit,
1620 const char *filename,
1621 unsigned line,
1622 const char *section,
1623 unsigned section_line,
1624 const char *lvalue,
1625 int ltype,
1626 const char *rvalue,
1627 void *data,
1628 void *userdata) {
1629
1630 _cleanup_free_ char *unescaped = NULL;
1631 Network *network = data;
1632 int r;
1633
1634 assert(filename);
1635 assert(lvalue);
1636 assert(rvalue);
1637
1638 if (isempty(rvalue)) {
1639 network->dhcp_mudurl = mfree(network->dhcp_mudurl);
1640 return 0;
1641 }
1642
1643 r = cunescape(rvalue, 0, &unescaped);
1644 if (r < 0) {
1645 log_syntax(unit, LOG_WARNING, filename, line, r,
1646 "Failed to Failed to unescape MUD URL, ignoring: %s", rvalue);
1647 return 0;
1648 }
1649
1650 if (!http_url_is_valid(unescaped) || strlen(unescaped) > 255) {
1651 log_syntax(unit, LOG_WARNING, filename, line, 0,
1652 "Failed to parse MUD URL '%s', ignoring: %m", rvalue);
1653
1654 return 0;
1655 }
1656
1657 return free_and_strdup_warn(&network->dhcp_mudurl, unescaped);
1658 }
1659
1660 int config_parse_dhcp_fallback_lease_lifetime(const char *unit,
1661 const char *filename,
1662 unsigned line,
1663 const char *section,
1664 unsigned section_line,
1665 const char *lvalue,
1666 int ltype,
1667 const char *rvalue,
1668 void *data,
1669 void *userdata) {
1670 Network *network = userdata;
1671 uint32_t k;
1672
1673 assert(filename);
1674 assert(section);
1675 assert(lvalue);
1676 assert(rvalue);
1677 assert(data);
1678
1679 if (isempty(rvalue)) {
1680 network->dhcp_fallback_lease_lifetime = 0;
1681 return 0;
1682 }
1683
1684 /* We accept only "forever" or "infinity". */
1685 if (STR_IN_SET(rvalue, "forever", "infinity"))
1686 k = CACHE_INFO_INFINITY_LIFE_TIME;
1687 else {
1688 log_syntax(unit, LOG_WARNING, filename, line, 0,
1689 "Invalid LeaseLifetime= value, ignoring: %s", rvalue);
1690 return 0;
1691 }
1692
1693 network->dhcp_fallback_lease_lifetime = k;
1694
1695 return 0;
1696 }
1697
1698 static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
1699 [DHCP_CLIENT_ID_MAC] = "mac",
1700 [DHCP_CLIENT_ID_DUID] = "duid",
1701 [DHCP_CLIENT_ID_DUID_ONLY] = "duid-only",
1702 };
1703
1704 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DHCPClientIdentifier);
1705 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DHCPClientIdentifier,
1706 "Failed to parse client identifier type");