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