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