Compare commits
5 Commits
bf9012bbf6
...
a2870138c1
Author | SHA1 | Date |
---|---|---|
Zbigniew Jędrzejewski-Szmek | a2870138c1 | |
Yu Watanabe | 586ec936c6 | |
Yu Watanabe | 2e5580a8c1 | |
Yu Watanabe | 599e10a1d2 | |
Yu Watanabe | 62a7c3608e |
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue