Compare commits

...

5 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek a2870138c1
Merge pull request #14055 from yuwata/network-send-option-takes-type-field
network: make SendOption= also take type field
2019-11-17 19:17:38 +01:00
Yu Watanabe 586ec936c6 network: make SendOption= also take type field
This makes SendOption= and SendRawOption= takes values in the same
format.
2019-11-17 23:17:29 +09:00
Yu Watanabe 2e5580a8c1 network: rename DHCPRawOption to DHCPOptionDataType
And moves the definition from networkd-dhcp-server.[ch] to networkd-dhcp-common.[ch].
2019-11-17 23:00:11 +09:00
Yu Watanabe 599e10a1d2 network: fix logged error value 2019-11-17 22:51:06 +09:00
Yu Watanabe 62a7c3608e network: fix indentation 2019-11-17 22:45:38 +09:00
7 changed files with 125 additions and 46 deletions

View File

@ -1642,11 +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 and an arbitrary <para>Send an arbitrary option in the DHCPv4 request. Takes a DHCP option number, data type
data string separated with a colon and data separated with a colon (<literal><replaceable>option</replaceable>:
(<literal><replaceable>option</replaceable>:<replaceable>value</replaceable></literal>). The <replaceable>type</replaceable>:<replaceable>value</replaceable></literal>). The option
option number must be an interger in the range 1..254. Special characters in the data string may number must be an interger in the range 1..254. The type takes one of
be escaped using <literal>uint8</literal>, <literal>uint16</literal>, <literal>uint32</literal>,
<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>

View File

@ -273,3 +273,13 @@ 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,6 +15,16 @@ 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;
@ -27,6 +37,9 @@ 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,16 +480,6 @@ 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,
@ -505,11 +495,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;
@ -559,16 +549,15 @@ int config_parse_dhcp_server_raw_option_data(
return 0; return 0;
} }
r = dhcp_raw_option_data_type_from_string(word); type = dhcp_option_data_type_from_string(word);
if (r < 0) { if (type < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, log_syntax(unit, LOG_ERR, filename, line, 0,
"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_RAW_OPTION_DATA_UINT8:{ case DHCP_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,
@ -580,7 +569,7 @@ int config_parse_dhcp_server_raw_option_data(
sz = sizeof(uint8_t); sz = sizeof(uint8_t);
break; break;
} }
case DHCP_RAW_OPTION_DATA_UINT16:{ case DHCP_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,
@ -592,7 +581,7 @@ int config_parse_dhcp_server_raw_option_data(
sz = sizeof(uint16_t); sz = sizeof(uint16_t);
break; break;
} }
case DHCP_RAW_OPTION_DATA_UINT32: { case DHCP_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,
@ -605,7 +594,7 @@ int config_parse_dhcp_server_raw_option_data(
break; break;
} }
case DHCP_RAW_OPTION_DATA_IPV4ADDRESS: { case DHCP_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,
@ -617,7 +606,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_RAW_OPTION_DATA_STRING: case DHCP_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,19 +7,6 @@
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,9 +1580,14 @@ 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;
uint8_t u; void *udata;
ssize_t sz; ssize_t sz;
int r; int r;
@ -1618,14 +1623,87 @@ int config_parse_dhcp_send_option(
return 0; return 0;
} }
free(word);
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
"Invalid DHCP send option, ignoring assignment: %s", rvalue);
return 0;
}
type = dhcp_option_data_type_from_string(word);
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); 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,
"Failed to decode option data, ignoring assignment: %s", p); "Failed to decode option data, ignoring assignment: %s", p);
return 0;
} }
r = sd_dhcp_option_new(u, q, sz, &opt); 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);