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