1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "dhcp-internal.h"
5 #include "in-addr-util.h"
6 #include "networkd-dhcp-common.h"
7 #include "networkd-network.h"
8 #include "parse-util.h"
9 #include "string-table.h"
12 int config_parse_dhcp(
17 unsigned section_line
,
24 AddressFamily
*dhcp
= data
, s
;
31 /* Note that this is mostly like
32 * config_parse_address_family(), except that it
33 * understands some old names for the enum values */
35 s
= address_family_from_string(rvalue
);
38 /* Previously, we had a slightly different enum here,
39 * support its values for compatibility. */
41 if (streq(rvalue
, "none"))
42 s
= ADDRESS_FAMILY_NO
;
43 else if (streq(rvalue
, "v4"))
44 s
= ADDRESS_FAMILY_IPV4
;
45 else if (streq(rvalue
, "v6"))
46 s
= ADDRESS_FAMILY_IPV6
;
47 else if (streq(rvalue
, "both"))
48 s
= ADDRESS_FAMILY_YES
;
50 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
51 "Failed to parse DHCP option, ignoring: %s", rvalue
);
55 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
56 "DHCP=%s is deprecated, please use DHCP=%s instead.",
57 rvalue
, address_family_to_string(s
));
64 int config_parse_dhcp_use_dns(
69 unsigned section_line
,
76 Network
*network
= data
;
84 r
= parse_boolean(rvalue
);
86 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
87 "Failed to parse UseDNS=%s, ignoring assignment: %m", rvalue
);
91 network
->dhcp_use_dns
= r
;
92 network
->dhcp6_use_dns
= r
;
97 int config_parse_dhcp_use_sip(
102 unsigned section_line
,
109 Network
*network
= data
;
117 r
= parse_boolean(rvalue
);
119 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
120 "Failed to parse UseSIP=%s, ignoring assignment: %m", rvalue
);
124 network
->dhcp_use_sip
= r
;
129 int config_parse_dhcp_use_ntp(
131 const char *filename
,
134 unsigned section_line
,
141 Network
*network
= data
;
149 r
= parse_boolean(rvalue
);
151 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
152 "Failed to parse UseNTP=%s, ignoring assignment: %m", rvalue
);
156 network
->dhcp_use_ntp
= r
;
157 network
->dhcp6_use_ntp
= r
;
162 int config_parse_section_route_table(
164 const char *filename
,
167 unsigned section_line
,
174 Network
*network
= data
;
183 r
= safe_atou32(rvalue
, &rt
);
185 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
186 "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue
);
190 if (STRPTR_IN_SET(section
, "DHCP", "DHCPv4")) {
191 network
->dhcp_route_table
= rt
;
192 network
->dhcp_route_table_set
= true;
193 } else { /* section is IPv6AcceptRA */
194 network
->ipv6_accept_ra_route_table
= rt
;
195 network
->ipv6_accept_ra_route_table_set
= true;
201 int config_parse_iaid(const char *unit
,
202 const char *filename
,
205 unsigned section_line
,
211 Network
*network
= data
;
220 r
= safe_atou32(rvalue
, &iaid
);
222 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
223 "Unable to read IAID, ignoring assignment: %s", rvalue
);
227 network
->iaid
= iaid
;
228 network
->iaid_set
= true;
233 int config_parse_dhcp6_pd_hint(
235 const char *filename
,
238 unsigned section_line
,
245 Network
*network
= data
;
253 r
= in_addr_prefix_from_string(rvalue
, AF_INET6
, (union in_addr_union
*) &network
->dhcp6_pd_address
, &network
->dhcp6_pd_length
);
255 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse PrefixDelegationHint=%s, ignoring assignment", rvalue
);
259 if (network
->dhcp6_pd_length
< 1 || network
->dhcp6_pd_length
> 128) {
260 log_syntax(unit
, LOG_ERR
, filename
, line
, 0, "Invalid prefix length='%d', ignoring assignment", network
->dhcp6_pd_length
);
261 network
->dhcp6_pd_length
= 0;
268 int config_parse_dhcp_send_option(
270 const char *filename
,
273 unsigned section_line
,
280 _cleanup_(sd_dhcp_option_unrefp
) sd_dhcp_option
*opt
= NULL
, *old
= NULL
;
281 _cleanup_free_
char *word
= NULL
, *q
= NULL
;
282 OrderedHashmap
**options
= userdata
;
283 union in_addr_union addr
;
284 DHCPOptionDataType type
;
285 uint8_t u
, uint8_data
;
286 uint16_t uint16_data
;
287 uint32_t uint32_data
;
298 if (isempty(rvalue
)) {
299 *options
= ordered_hashmap_free(*options
);
304 r
= extract_first_word(&p
, &word
, ":", 0);
308 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
309 "Invalid DHCP option, ignoring assignment: %s", rvalue
);
313 r
= safe_atou8(word
, &u
);
315 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
316 "Invalid DHCP option, ignoring assignment: %s", rvalue
);
319 if (u
< 1 || u
>= 255) {
320 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
321 "Invalid DHCP option, valid range is 1-254, ignoring assignment: %s", rvalue
);
326 r
= extract_first_word(&p
, &word
, ":", 0);
330 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
331 "Invalid DHCP option, ignoring assignment: %s", rvalue
);
335 type
= dhcp_option_data_type_from_string(word
);
337 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
338 "Invalid DHCP option data type, ignoring assignment: %s", p
);
343 case DHCP_OPTION_DATA_UINT8
:{
344 r
= safe_atou8(p
, &uint8_data
);
346 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
347 "Failed to parse DHCPv4 uint8 data, ignoring assignment: %s", p
);
352 sz
= sizeof(uint8_t);
355 case DHCP_OPTION_DATA_UINT16
:{
356 r
= safe_atou16(p
, &uint16_data
);
358 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
359 "Failed to parse DHCPv4 uint16 data, ignoring assignment: %s", p
);
363 udata
= &uint16_data
;
364 sz
= sizeof(uint16_t);
367 case DHCP_OPTION_DATA_UINT32
: {
368 r
= safe_atou32(p
, &uint32_data
);
370 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
371 "Failed to parse DHCPv4 uint32 data, ignoring assignment: %s", p
);
375 udata
= &uint32_data
;
376 sz
= sizeof(uint32_t);
380 case DHCP_OPTION_DATA_IPV4ADDRESS
: {
381 r
= in_addr_from_string(AF_INET
, p
, &addr
);
383 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
384 "Failed to parse DHCPv4 ipv4address data, ignoring assignment: %s", p
);
389 sz
= sizeof(addr
.in
.s_addr
);
392 case DHCP_OPTION_DATA_STRING
:
393 sz
= cunescape(p
, 0, &q
);
395 log_syntax(unit
, LOG_ERR
, filename
, line
, sz
,
396 "Failed to decode DHCPv4 option data, ignoring assignment: %s", p
);
405 r
= sd_dhcp_option_new(u
, udata
, sz
, &opt
);
407 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
408 "Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue
);
412 r
= ordered_hashmap_ensure_allocated(options
, &dhcp_option_hash_ops
);
416 /* Overwrite existing option */
417 old
= ordered_hashmap_remove(*options
, UINT_TO_PTR(u
));
418 r
= ordered_hashmap_put(*options
, UINT_TO_PTR(u
), opt
);
420 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
421 "Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue
);
429 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains
, dhcp_use_domains
, DHCPUseDomains
,
430 "Failed to parse DHCP use domains setting");
432 static const char* const dhcp_use_domains_table
[_DHCP_USE_DOMAINS_MAX
] = {
433 [DHCP_USE_DOMAINS_NO
] = "no",
434 [DHCP_USE_DOMAINS_ROUTE
] = "route",
435 [DHCP_USE_DOMAINS_YES
] = "yes",
438 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains
, DHCPUseDomains
, DHCP_USE_DOMAINS_YES
);
440 static const char * const dhcp_option_data_type_table
[_DHCP_OPTION_DATA_MAX
] = {
441 [DHCP_OPTION_DATA_UINT8
] = "uint8",
442 [DHCP_OPTION_DATA_UINT16
] = "uint16",
443 [DHCP_OPTION_DATA_UINT32
] = "uint32",
444 [DHCP_OPTION_DATA_STRING
] = "string",
445 [DHCP_OPTION_DATA_IPV4ADDRESS
] = "ipv4address",
448 DEFINE_STRING_TABLE_LOOKUP(dhcp_option_data_type
, DHCPOptionDataType
);