Compare commits

..

No commits in common. "a2870138c10e26d9d1f63552d1a725c5bb7d4adb" and "bf9012bbf6d8c8828357a8479080339a2b6b5451" have entirely different histories.

7 changed files with 46 additions and 125 deletions

View File

@ -1642,15 +1642,13 @@
<varlistentry> <varlistentry>
<term><varname>SendOption=</varname></term> <term><varname>SendOption=</varname></term>
<listitem> <listitem>
<para>Send an arbitrary option in the DHCPv4 request. Takes a DHCP option number, data type <para>Send an arbitrary option in the DHCPv4 request. Takes a DHCP option number and an arbitrary
and data separated with a colon (<literal><replaceable>option</replaceable>: data string separated with a colon
<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>). The option (<literal><replaceable>option</replaceable>:<replaceable>value</replaceable></literal>). The
number must be an interger in the range 1..254. The type takes one of option number must be an interger in the range 1..254. Special characters in the data string may
<literal>uint8</literal>, <literal>uint16</literal>, <literal>uint32</literal>, be escaped using
<literal>ipv4address</literal>, or <literal>string</literal>.
Special characters in the data string may be escaped using
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style <ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
escapes</ulink>. This option can be specified multiple times. If an empty string is specified, escapes</ulink>. This option can be specified multiple times. If an empty string is specified,
then all options specified earlier are cleared. Defaults to unset.</para> then all options specified earlier are cleared. Defaults to unset.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -273,13 +273,3 @@ static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
}; };
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES); DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
static const char * const dhcp_option_data_type_table[_DHCP_OPTION_DATA_MAX] = {
[DHCP_OPTION_DATA_UINT8] = "uint8",
[DHCP_OPTION_DATA_UINT16] = "uint16",
[DHCP_OPTION_DATA_UINT32] = "uint32",
[DHCP_OPTION_DATA_STRING] = "string",
[DHCP_OPTION_DATA_IPV4ADDRESS] = "ipv4address",
};
DEFINE_STRING_TABLE_LOOKUP(dhcp_option_data_type, DHCPOptionDataType);

View File

@ -15,16 +15,6 @@ typedef enum DHCPUseDomains {
_DHCP_USE_DOMAINS_INVALID = -1, _DHCP_USE_DOMAINS_INVALID = -1,
} DHCPUseDomains; } DHCPUseDomains;
typedef enum DHCPOptionDataType {
DHCP_OPTION_DATA_UINT8,
DHCP_OPTION_DATA_UINT16,
DHCP_OPTION_DATA_UINT32,
DHCP_OPTION_DATA_STRING,
DHCP_OPTION_DATA_IPV4ADDRESS,
_DHCP_OPTION_DATA_MAX,
_DHCP_OPTION_DATA_INVALID,
} DHCPOptionDataType;
typedef struct DUID { typedef struct DUID {
/* Value of Type in [DHCP] section */ /* Value of Type in [DHCP] section */
DUIDType type; DUIDType type;
@ -37,9 +27,6 @@ typedef struct DUID {
const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
const char *dhcp_option_data_type_to_string(DHCPOptionDataType d) _const_;
DHCPOptionDataType dhcp_option_data_type_from_string(const char *d) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_dns); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_dns);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);

View File

@ -480,6 +480,16 @@ int config_parse_dhcp_server_sip(
} }
} }
static const char * const dhcp_raw_option_data_type_table[_DHCP_RAW_OPTION_DATA_MAX] = {
[DHCP_RAW_OPTION_DATA_UINT8] = "uint8",
[DHCP_RAW_OPTION_DATA_UINT16] = "uint16",
[DHCP_RAW_OPTION_DATA_UINT32] = "uint32",
[DHCP_RAW_OPTION_DATA_STRING] = "string",
[DHCP_RAW_OPTION_DATA_IPV4ADDRESS] = "ipv4address",
};
DEFINE_STRING_TABLE_LOOKUP(dhcp_raw_option_data_type, DHCPRawOption);
int config_parse_dhcp_server_raw_option_data( int config_parse_dhcp_server_raw_option_data(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -495,11 +505,11 @@ int config_parse_dhcp_server_raw_option_data(
_cleanup_(sd_dhcp_raw_option_unrefp) sd_dhcp_raw_option *opt = NULL, *old = NULL; _cleanup_(sd_dhcp_raw_option_unrefp) sd_dhcp_raw_option *opt = NULL, *old = NULL;
_cleanup_free_ char *word = NULL, *q = NULL; _cleanup_free_ char *word = NULL, *q = NULL;
union in_addr_union addr; union in_addr_union addr;
DHCPOptionDataType type;
Network *network = data; Network *network = data;
uint16_t uint16_data; uint16_t uint16_data;
uint32_t uint32_data; uint32_t uint32_data;
uint8_t uint8_data; uint8_t uint8_data;
DHCPRawOption type;
const char *p; const char *p;
void *udata; void *udata;
ssize_t sz; ssize_t sz;
@ -549,15 +559,16 @@ int config_parse_dhcp_server_raw_option_data(
return 0; return 0;
} }
type = dhcp_option_data_type_from_string(word); r = dhcp_raw_option_data_type_from_string(word);
if (type < 0) { if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0, log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP server send data type, ignoring assignment: %s", p); "Invalid DHCP server send data type, ignoring assignment: %s", p);
return 0; return 0;
} }
type = r;
switch(type) { switch(type) {
case DHCP_OPTION_DATA_UINT8:{ case DHCP_RAW_OPTION_DATA_UINT8:{
r = safe_atou8(p, &uint8_data); r = safe_atou8(p, &uint8_data);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, log_syntax(unit, LOG_ERR, filename, line, r,
@ -569,7 +580,7 @@ int config_parse_dhcp_server_raw_option_data(
sz = sizeof(uint8_t); sz = sizeof(uint8_t);
break; break;
} }
case DHCP_OPTION_DATA_UINT16:{ case DHCP_RAW_OPTION_DATA_UINT16:{
r = safe_atou16(p, &uint16_data); r = safe_atou16(p, &uint16_data);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, log_syntax(unit, LOG_ERR, filename, line, r,
@ -581,7 +592,7 @@ int config_parse_dhcp_server_raw_option_data(
sz = sizeof(uint16_t); sz = sizeof(uint16_t);
break; break;
} }
case DHCP_OPTION_DATA_UINT32: { case DHCP_RAW_OPTION_DATA_UINT32: {
r = safe_atou32(p, &uint32_data); r = safe_atou32(p, &uint32_data);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, log_syntax(unit, LOG_ERR, filename, line, r,
@ -594,7 +605,7 @@ int config_parse_dhcp_server_raw_option_data(
break; break;
} }
case DHCP_OPTION_DATA_IPV4ADDRESS: { case DHCP_RAW_OPTION_DATA_IPV4ADDRESS: {
r = in_addr_from_string(AF_INET, p, &addr); r = in_addr_from_string(AF_INET, p, &addr);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, log_syntax(unit, LOG_ERR, filename, line, r,
@ -606,7 +617,7 @@ int config_parse_dhcp_server_raw_option_data(
sz = sizeof(addr.in.s_addr); sz = sizeof(addr.in.s_addr);
break; break;
} }
case DHCP_OPTION_DATA_STRING: case DHCP_RAW_OPTION_DATA_STRING:
sz = cunescape(p, 0, &q); sz = cunescape(p, 0, &q);
if (sz < 0) { if (sz < 0) {
log_syntax(unit, LOG_ERR, filename, line, sz, log_syntax(unit, LOG_ERR, filename, line, sz,

View File

@ -7,6 +7,19 @@
typedef struct Link Link; typedef struct Link Link;
typedef enum DHCPRawOption {
DHCP_RAW_OPTION_DATA_UINT8,
DHCP_RAW_OPTION_DATA_UINT16,
DHCP_RAW_OPTION_DATA_UINT32,
DHCP_RAW_OPTION_DATA_STRING,
DHCP_RAW_OPTION_DATA_IPV4ADDRESS,
_DHCP_RAW_OPTION_DATA_MAX,
_DHCP_RAW_OPTION_DATA_INVALID,
} DHCPRawOption;
const char *dhcp_raw_option_data_type_to_string(DHCPRawOption d) _const_;
DHCPRawOption dhcp_raw_option_data_type_from_string(const char *d) _pure_;
int dhcp4_server_configure(Link *link); int dhcp4_server_configure(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);

View File

@ -1580,14 +1580,9 @@ int config_parse_dhcp_send_option(
_cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt = NULL, *old = NULL; _cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt = NULL, *old = NULL;
_cleanup_free_ char *word = NULL, *q = NULL; _cleanup_free_ char *word = NULL, *q = NULL;
union in_addr_union addr;
DHCPOptionDataType type;
Network *network = data; Network *network = data;
uint8_t u, uint8_data;
uint16_t uint16_data;
uint32_t uint32_data;
const char *p; const char *p;
void *udata; uint8_t u;
ssize_t sz; ssize_t sz;
int r; int r;
@ -1623,87 +1618,14 @@ int config_parse_dhcp_send_option(
return 0; return 0;
} }
free(word); sz = cunescape(p, 0, &q);
r = extract_first_word(&p, &word, ":", 0); if (sz < 0) {
if (r == -ENOMEM) log_syntax(unit, LOG_ERR, filename, line, sz,
return log_oom(); "Failed to decode option data, ignoring assignment: %s", p);
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP send option, ignoring assignment: %s", rvalue);
return 0; return 0;
} }
type = dhcp_option_data_type_from_string(word); r = sd_dhcp_option_new(u, q, sz, &opt);
if (type < 0) {
log_syntax(unit, LOG_ERR, filename, line, 0,
"Invalid DHCP send data type, ignoring assignment: %s", p);
return 0;
}
switch(type) {
case DHCP_OPTION_DATA_UINT8:{
r = safe_atou8(p, &uint8_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint8 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint8_data;
sz = sizeof(uint8_t);
break;
}
case DHCP_OPTION_DATA_UINT16:{
r = safe_atou16(p, &uint16_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint16 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint16_data;
sz = sizeof(uint16_t);
break;
}
case DHCP_OPTION_DATA_UINT32: {
r = safe_atou32(p, &uint32_data);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 uint32 data, ignoring assignment: %s", p);
return 0;
}
udata = &uint32_data;
sz = sizeof(uint32_t);
break;
}
case DHCP_OPTION_DATA_IPV4ADDRESS: {
r = in_addr_from_string(AF_INET, p, &addr);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to parse DHCPv4 ipv4address data, ignoring assignment: %s", p);
return 0;
}
udata = &addr.in;
sz = sizeof(addr.in.s_addr);
break;
}
case DHCP_OPTION_DATA_STRING:
sz = cunescape(p, 0, &q);
if (sz < 0) {
log_syntax(unit, LOG_ERR, filename, line, sz,
"Failed to decode option data, ignoring assignment: %s", p);
}
udata = q;
break;
default:
return -EINVAL;
}
r = sd_dhcp_option_new(u, udata, sz, &opt);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, log_syntax(unit, LOG_ERR, filename, line, r,
"Failed to store DHCP send option '%s', ignoring assignment: %m", rvalue); "Failed to store DHCP send option '%s', ignoring assignment: %m", rvalue);

View File

@ -175,7 +175,7 @@ DHCPv4.ListenPort, config_parse_uint16,
DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release) DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release)
DHCPv4.BlackList, config_parse_dhcp_black_listed_ip_address, 0, 0 DHCPv4.BlackList, config_parse_dhcp_black_listed_ip_address, 0, 0
DHCPv4.IPServiceType, config_parse_ip_service_type, 0, offsetof(Network, ip_service_type) DHCPv4.IPServiceType, config_parse_ip_service_type, 0, offsetof(Network, ip_service_type)
DHCPv4.SendOption, config_parse_dhcp_send_option, 0, 0 DHCPv4.SendOption, config_parse_dhcp_send_option, 0, 0
DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns) DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns)
DHCPv6.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp6_use_ntp) DHCPv6.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp6_use_ntp)
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit) DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)