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