diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index e87ca1f287..8b401eeaf9 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -1643,14 +1643,13 @@
SendOption=
Send an arbitrary option in the DHCPv4 request. Takes a DHCP option number, data type
- and data separated with a colon (option:
- type:value). The option
- number must be an interger in the range 1..254. The type takes one of
- uint8, uint16, uint32,
- ipv4address, or string.
- Special characters in the data string may be escaped using
+ and data separated with a colon
+ (option:type:value).
+ The option number must be an interger in the range 1..254. The type takes one of uint8,
+ uint16, uint32, ipv4address, or
+ string. Special characters in the data string may be escaped using
C-style
- escapes. This option can be specified multiple times. If an empty string is specified,
+ escapes. This setting can be specified multiple times. If an empty string is specified,
then all options specified earlier are cleared. Defaults to unset.
@@ -1905,16 +1904,17 @@
- SendRawOption=
-
- Send a raw option with value via DHCPv4 server. Takes a DHCP option, data type and data
- (option:type:value). The option ranges [1-254]. The type takes one of uint8,
- uint16, uint32, ipv4address, or string.
- Special characters in the data string may be escaped using
- C-style
- escapes. This option can be specified multiple times. If an empty string is specified, then all
- options specified earlier are cleared. Defaults to unset.
-
+ SendOption=
+
+ Send a raw option with value via DHCPv4 server. Takes a DHCP option number, data type
+ and data (option:type:value).
+ The option number is an integer in the range 1..254. The type takes one of uint8,
+ uint16, uint32, ipv4address, or
+ string. Special characters in the data string may be escaped using
+ C-style
+ escapes. This setting can be specified multiple times. If an empty string is specified,
+ then all options specified earlier are cleared. Defaults to unset.
+
diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index c231773bdd..6a803d7b05 100644
--- a/src/libsystemd-network/dhcp-internal.h
+++ b/src/libsystemd-network/dhcp-internal.h
@@ -15,6 +15,16 @@
#include "dhcp-protocol.h"
#include "socket-util.h"
+typedef struct sd_dhcp_option {
+ unsigned n_ref;
+
+ uint8_t option;
+ void *data;
+ size_t length;
+} sd_dhcp_option;
+
+extern const struct hash_ops dhcp_option_hash_ops;
+
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
uint32_t xid, const uint8_t *mac_addr,
size_t mac_addr_len, uint16_t arp_type,
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 061cfde2f0..e03c1a894d 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -79,7 +79,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
break;
case SD_DHCP_OPTION_VENDOR_SPECIFIC: {
OrderedHashmap *s = (OrderedHashmap *) optval;
- struct sd_dhcp_raw_option *p;
+ struct sd_dhcp_option *p;
size_t l = 0;
Iterator i;
@@ -95,7 +95,7 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
*offset += 2;
ORDERED_HASHMAP_FOREACH(p, s, i) {
- options[*offset] = p->type;
+ options[*offset] = p->option;
options[*offset + 1] = p->length;
memcpy(&options[*offset + 2], p->data, p->length);
*offset += 2 + p->length;
@@ -315,3 +315,43 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_callback_t c
return message_type;
}
+
+static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) {
+ if (!i)
+ return NULL;
+
+ free(i->data);
+ return mfree(i);
+}
+
+int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret) {
+ assert_return(ret, -EINVAL);
+ assert_return(length == 0 || data, -EINVAL);
+
+ _cleanup_free_ void *q = memdup(data, length);
+ if (!q)
+ return -ENOMEM;
+
+ sd_dhcp_option *p = new(sd_dhcp_option, 1);
+ if (!p)
+ return -ENOMEM;
+
+ *p = (sd_dhcp_option) {
+ .n_ref = 1,
+ .option = option,
+ .length = length,
+ .data = TAKE_PTR(q),
+ };
+
+ *ret = TAKE_PTR(p);
+ return 0;
+}
+
+DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free);
+DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
+ dhcp_option_hash_ops,
+ void,
+ trivial_hash_func,
+ trivial_compare_func,
+ sd_dhcp_option,
+ sd_dhcp_option_unref);
diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h
index e537d9e622..42c3ceb8b1 100644
--- a/src/libsystemd-network/dhcp-server-internal.h
+++ b/src/libsystemd-network/dhcp-server-internal.h
@@ -37,15 +37,6 @@ typedef struct DHCPLease {
usec_t expiration;
} DHCPLease;
-struct sd_dhcp_raw_option {
- unsigned n_ref;
-
- uint8_t type;
- uint8_t length;
-
- void *data;
-};
-
struct sd_dhcp_server {
unsigned n_ref;
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index bbad10026a..901985fc1b 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -34,14 +34,6 @@
#define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC)
#define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE)
-struct sd_dhcp_option {
- unsigned n_ref;
-
- uint8_t option;
- void *data;
- size_t length;
-};
-
struct sd_dhcp_client {
unsigned n_ref;
@@ -548,46 +540,6 @@ int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempt
return 0;
}
-static sd_dhcp_option* dhcp_option_free(sd_dhcp_option *i) {
- if (!i)
- return NULL;
-
- free(i->data);
- return mfree(i);
-}
-
-int sd_dhcp_option_new(uint8_t option, void *data, size_t length, sd_dhcp_option **ret) {
- assert_return(ret, -EINVAL);
- assert_return(length == 0 || data, -EINVAL);
-
- _cleanup_free_ void *q = memdup(data, length);
- if (!q)
- return -ENOMEM;
-
- sd_dhcp_option *p = new(sd_dhcp_option, 1);
- if (!p)
- return -ENOMEM;
-
- *p = (sd_dhcp_option) {
- .n_ref = 1,
- .option = option,
- .length = length,
- .data = TAKE_PTR(q),
- };
-
- *ret = TAKE_PTR(p);
- return 0;
-}
-
-DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_option, sd_dhcp_option, dhcp_option_free);
-DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
- dhcp_option_hash_ops,
- void,
- trivial_hash_func,
- trivial_compare_func,
- sd_dhcp_option,
- sd_dhcp_option_unref);
-
int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) {
int r;
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 3316c8bda4..9e51bf74f5 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -127,46 +127,6 @@ int client_id_compare_func(const DHCPClientId *a, const DHCPClientId *b) {
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(dhcp_lease_hash_ops, DHCPClientId, client_id_hash_func, client_id_compare_func,
DHCPLease, dhcp_lease_free);
-static sd_dhcp_raw_option* raw_option_free(sd_dhcp_raw_option *i) {
- if (!i)
- return NULL;
-
- free(i->data);
- return mfree(i);
-}
-
-_public_ int sd_dhcp_raw_option_new(uint8_t type, char *data, size_t length, sd_dhcp_raw_option **ret) {
- _cleanup_(sd_dhcp_raw_option_unrefp) sd_dhcp_raw_option *p = NULL;
-
- assert_return(ret, -EINVAL);
-
- p = new(sd_dhcp_raw_option, 1);
- if (!p)
- return -ENOMEM;
-
- *p = (sd_dhcp_raw_option) {
- .n_ref = 1,
- .data = memdup(data, length),
- .length = length,
- .type = type,
- };
-
- if (!p->data)
- return -ENOMEM;
-
- *ret = TAKE_PTR(p);
- return 0;
-}
-
-DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_raw_option, sd_dhcp_raw_option, raw_option_free);
-DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
- dhcp_raw_options_hash_ops,
- void,
- trivial_hash_func,
- trivial_compare_func,
- sd_dhcp_raw_option,
- sd_dhcp_raw_option_unref);
-
static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
assert(server);
@@ -1222,13 +1182,13 @@ int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) {
return 1;
}
-int sd_dhcp_server_add_raw_option(sd_dhcp_server *server, sd_dhcp_raw_option *v) {
+int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v) {
int r;
assert_return(server, -EINVAL);
assert_return(v, -EINVAL);
- r = ordered_hashmap_ensure_allocated(&server->raw_option, &dhcp_raw_options_hash_ops);
+ r = ordered_hashmap_ensure_allocated(&server->raw_option, &dhcp_option_hash_ops);
if (r < 0)
return -ENOMEM;
@@ -1236,7 +1196,7 @@ int sd_dhcp_server_add_raw_option(sd_dhcp_server *server, sd_dhcp_raw_option *v)
if (r < 0)
return r;
- sd_dhcp_raw_option_ref(v);
+ sd_dhcp_option_ref(v);
return 1;
}
diff --git a/src/network/networkd-dhcp-common.c b/src/network/networkd-dhcp-common.c
index 7e42a6edd4..7f8da46cf5 100644
--- a/src/network/networkd-dhcp-common.c
+++ b/src/network/networkd-dhcp-common.c
@@ -1,5 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
+#include "dhcp-internal.h"
+#include "escape.h"
#include "in-addr-util.h"
#include "networkd-dhcp-common.h"
#include "networkd-network.h"
@@ -263,6 +265,167 @@ int config_parse_dhcp6_pd_hint(
return 0;
}
+int config_parse_dhcp_send_option(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ _cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt = NULL, *old = NULL;
+ _cleanup_free_ char *word = NULL, *q = NULL;
+ OrderedHashmap **options = userdata;
+ union in_addr_union addr;
+ DHCPOptionDataType type;
+ uint8_t u, uint8_data;
+ uint16_t uint16_data;
+ uint32_t uint32_data;
+ const void *udata;
+ const char *p;
+ ssize_t sz;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ if (isempty(rvalue)) {
+ *options = ordered_hashmap_free(*options);
+ return 0;
+ }
+
+ p = rvalue;
+ 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 option, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ r = safe_atou8(word, &u);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Invalid DHCP option, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+ if (u < 1 || u >= 255) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Invalid DHCP option, valid range is 1-254, ignoring assignment: %s", rvalue);
+ 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 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 option 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 DHCPv4 option data, ignoring assignment: %s", p);
+ }
+
+ udata = q;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ r = sd_dhcp_option_new(u, udata, sz, &opt);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue);
+ return 0;
+ }
+
+ r = ordered_hashmap_ensure_allocated(options, &dhcp_option_hash_ops);
+ if (r < 0)
+ return log_oom();
+
+ /* Overwrite existing option */
+ old = ordered_hashmap_remove(*options, UINT_TO_PTR(u));
+ r = ordered_hashmap_put(*options, UINT_TO_PTR(u), opt);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue);
+ return 0;
+ }
+
+ TAKE_PTR(opt);
+ return 0;
+}
+
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
"Failed to parse DHCP use domains setting");
diff --git a/src/network/networkd-dhcp-common.h b/src/network/networkd-dhcp-common.h
index b194e0bfb7..1d6ddbb8cc 100644
--- a/src/network/networkd-dhcp-common.h
+++ b/src/network/networkd-dhcp-common.h
@@ -48,3 +48,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_sip);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp6_pd_hint);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c
index 279f7789cb..fc1cd5ca1b 100644
--- a/src/network/networkd-dhcp-server.c
+++ b/src/network/networkd-dhcp-server.c
@@ -2,7 +2,6 @@
#include "sd-dhcp-server.h"
-#include "escape.h"
#include "networkd-dhcp-server.h"
#include "networkd-link.h"
#include "networkd-manager.h"
@@ -192,7 +191,7 @@ static int link_push_uplink_sip_to_dhcp_server(Link *link, sd_dhcp_server *s) {
int dhcp4_server_configure(Link *link) {
bool acquired_uplink = false;
- sd_dhcp_raw_option *p;
+ sd_dhcp_option *p;
Link *uplink = NULL;
Address *address;
Iterator i;
@@ -305,8 +304,8 @@ int dhcp4_server_configure(Link *link) {
return log_link_error_errno(link, r, "Failed to set timezone for DHCP server: %m");
}
- ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_raw_options, i) {
- r = sd_dhcp_server_add_raw_option(link->dhcp_server, p);
+ ORDERED_HASHMAP_FOREACH(p, link->network->dhcp_server_send_options, i) {
+ r = sd_dhcp_server_add_option(link->dhcp_server, p);
if (r == -EEXIST)
continue;
if (r < 0)
@@ -479,167 +478,3 @@ int config_parse_dhcp_server_sip(
n->dhcp_server_sip = m;
}
}
-
-int config_parse_dhcp_server_raw_option_data(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- _cleanup_(sd_dhcp_raw_option_unrefp) sd_dhcp_raw_option *opt = NULL, *old = NULL;
- _cleanup_free_ char *word = NULL, *q = NULL;
- union in_addr_union addr;
- DHCPOptionDataType type;
- Network *network = data;
- uint16_t uint16_data;
- uint32_t uint32_data;
- uint8_t uint8_data;
- const char *p;
- void *udata;
- ssize_t sz;
- uint8_t u;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- network->dhcp_server_raw_options = ordered_hashmap_free(network->dhcp_server_raw_options);
- return 0;
- }
-
- p = rvalue;
- 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 server send raw option, ignoring assignment: %s", rvalue);
- return 0;
- }
-
- r = safe_atou8(word, &u);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse DHCP server send raw option type, ignoring assignment: %s", rvalue);
- return 0;
- }
- if (u < 1 || u >= 255) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Invalid DHCP server send raw option, valid range is 1-254, ignoring assignment: %s", rvalue);
- 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 server send raw 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 server 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 vendor specific 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 vendor specific 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 vendor specific 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 vendor specific 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_raw_option_new(u, udata, sz, &opt);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store DHCP send raw option '%s', ignoring assignment: %m", rvalue);
- return 0;
- }
-
- r = ordered_hashmap_ensure_allocated(&network->dhcp_server_raw_options, &dhcp_raw_options_hash_ops);
- if (r < 0)
- return log_oom();
-
- /* Overwrite existing option */
- old = ordered_hashmap_remove(network->dhcp_server_raw_options, UINT_TO_PTR(u));
- r = ordered_hashmap_put(network->dhcp_server_raw_options, UINT_TO_PTR(u), opt);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store DHCP server send raw option '%s'", rvalue);
- return 0;
- }
-
- TAKE_PTR(opt);
-
- return 0;
-}
diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h
index e0a7799b1c..c90d48ec00 100644
--- a/src/network/networkd-dhcp-server.h
+++ b/src/network/networkd-dhcp-server.h
@@ -12,4 +12,3 @@ int dhcp4_server_configure(Link *link);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_raw_option_data);
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 7504e4eb27..8ca87d99d4 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -6,7 +6,6 @@
#include "alloc-util.h"
#include "dhcp-client-internal.h"
-#include "escape.h"
#include "hostname-util.h"
#include "parse-util.h"
#include "network-internal.h"
@@ -1295,7 +1294,7 @@ int dhcp4_configure(Link *link) {
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for '%u': %m", option);
}
- ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_send_options, i) {
+ ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp_client_send_options, i) {
r = sd_dhcp_client_set_dhcp_option(link->dhcp_client, send_option);
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set send option: %m");
@@ -1566,167 +1565,6 @@ int config_parse_dhcp_request_options(
return 0;
}
-int config_parse_dhcp_send_option(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- _cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt = NULL, *old = NULL;
- _cleanup_free_ char *word = NULL, *q = NULL;
- union in_addr_union addr;
- DHCPOptionDataType type;
- Network *network = data;
- uint8_t u, uint8_data;
- uint16_t uint16_data;
- uint32_t uint32_data;
- const char *p;
- void *udata;
- ssize_t sz;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(data);
-
- if (isempty(rvalue)) {
- network->dhcp_send_options = ordered_hashmap_free(network->dhcp_send_options);
- return 0;
- }
-
- p = rvalue;
- 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;
- }
-
- r = safe_atou8(word, &u);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Invalid DHCP send option, ignoring assignment: %s", rvalue);
- return 0;
- }
- if (u < 1 || u >= 255) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "Invalid DHCP send option, valid range is 1-254, ignoring assignment: %s", rvalue);
- 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);
- 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) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store DHCP send option '%s', ignoring assignment: %m", rvalue);
- return 0;
- }
-
- r = ordered_hashmap_ensure_allocated(&network->dhcp_send_options, &dhcp_option_hash_ops);
- if (r < 0)
- return log_oom();
-
- /* Overwrite existing option */
- old = ordered_hashmap_remove(network->dhcp_send_options, UINT_TO_PTR(u));
- r = ordered_hashmap_put(network->dhcp_send_options, UINT_TO_PTR(u), opt);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store DHCP send option '%s'", rvalue);
- return 0;
- }
-
- TAKE_PTR(opt);
- return 0;
-}
-
static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
[DHCP_CLIENT_ID_MAC] = "mac",
[DHCP_CLIENT_ID_DUID] = "duid",
diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h
index 2c0ccd80df..fce11ef671 100644
--- a/src/network/networkd-dhcp4.h
+++ b/src/network/networkd-dhcp4.h
@@ -27,4 +27,3 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);
-CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index a99ef94d32..f314b1ec16 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -175,7 +175,7 @@ DHCPv4.ListenPort, config_parse_uint16,
DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release)
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.SendOption, config_parse_dhcp_send_option, 0, 0
+DHCPv4.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_options)
DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns)
DHCPv6.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp6_use_ntp)
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, rapid_commit)
@@ -200,7 +200,7 @@ DHCPServer.EmitTimezone, config_parse_bool,
DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone)
DHCPServer.PoolOffset, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_offset)
DHCPServer.PoolSize, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_size)
-DHCPServer.SendRawOption, config_parse_dhcp_server_raw_option_data, 0, 0
+DHCPServer.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_options)
Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost)
Bridge.UseBPDU, config_parse_tristate, 0, offsetof(Network, use_bpdu)
Bridge.HairPin, config_parse_tristate, 0, offsetof(Network, hairpin)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 8727fd329f..6e443975f1 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -686,8 +686,8 @@ static Network *network_free(Network *network) {
set_free_free(network->dnssec_negative_trust_anchors);
- ordered_hashmap_free(network->dhcp_send_options);
- ordered_hashmap_free(network->dhcp_server_raw_options);
+ ordered_hashmap_free(network->dhcp_client_send_options);
+ ordered_hashmap_free(network->dhcp_server_send_options);
return mfree(network);
}
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 9c4dcf0532..aa74bb4ae7 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -114,8 +114,8 @@ struct Network {
DHCPUseDomains dhcp_use_domains;
Set *dhcp_black_listed_ip;
Set *dhcp_request_options;
- OrderedHashmap *dhcp_send_options;
- OrderedHashmap *dhcp_server_raw_options;
+ OrderedHashmap *dhcp_client_send_options;
+ OrderedHashmap *dhcp_server_send_options;
/* DHCPv6 Client support*/
bool dhcp6_use_dns;
diff --git a/src/systemd/meson.build b/src/systemd/meson.build
index 75c48b07a5..05196554ac 100644
--- a/src/systemd/meson.build
+++ b/src/systemd/meson.build
@@ -22,6 +22,7 @@ _not_installed_headers = '''
sd-dhcp6-lease.h
sd-dhcp-client.h
sd-dhcp-lease.h
+ sd-dhcp-option.h
sd-dhcp-server.h
sd-ipv4acd.h
sd-ipv4ll.h
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index a44e6e35a2..f97e35b654 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -26,6 +26,7 @@
#include
#include "sd-dhcp-lease.h"
+#include "sd-dhcp-option.h"
#include "sd-event.h"
#include "_sd-common.h"
@@ -99,7 +100,6 @@ enum {
};
typedef struct sd_dhcp_client sd_dhcp_client;
-typedef struct sd_dhcp_option sd_dhcp_option;
typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
int sd_dhcp_client_set_callback(
@@ -179,9 +179,6 @@ int sd_dhcp_client_set_service_type(
sd_dhcp_client *client,
int type);
-int sd_dhcp_option_new(uint8_t option, void *data, size_t length, sd_dhcp_option **ret);
-sd_dhcp_option* sd_dhcp_option_ref(sd_dhcp_option *i);
-sd_dhcp_option* sd_dhcp_option_unref(sd_dhcp_option *i);
int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v);
int sd_dhcp_client_stop(sd_dhcp_client *client);
@@ -204,7 +201,6 @@ int sd_dhcp_client_detach_event(sd_dhcp_client *client);
sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_client, sd_dhcp_client_unref);
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref);
_SD_END_DECLARATIONS;
diff --git a/src/systemd/sd-dhcp-option.h b/src/systemd/sd-dhcp-option.h
new file mode 100644
index 0000000000..45dbd27985
--- /dev/null
+++ b/src/systemd/sd-dhcp-option.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#ifndef foosddhcpoptionhfoo
+#define foosddhcpoptionhfoo
+
+/***
+ Copyright © 2013 Intel Corporation. All rights reserved.
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see .
+***/
+
+#include
+#include
+
+#include "_sd-common.h"
+
+_SD_BEGIN_DECLARATIONS;
+
+typedef struct sd_dhcp_option sd_dhcp_option;
+
+int sd_dhcp_option_new(uint8_t option, const void *data, size_t length, sd_dhcp_option **ret);
+sd_dhcp_option *sd_dhcp_option_ref(sd_dhcp_option *ra);
+sd_dhcp_option *sd_dhcp_option_unref(sd_dhcp_option *ra);
+
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_option, sd_dhcp_option_unref);
+
+_SD_END_DECLARATIONS;
+
+#endif
diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h
index ba1bc4458a..5950506c9b 100644
--- a/src/systemd/sd-dhcp-server.h
+++ b/src/systemd/sd-dhcp-server.h
@@ -21,26 +21,20 @@
#include
#include
+#include "sd-dhcp-option.h"
#include "sd-event.h"
#include "_sd-common.h"
_SD_BEGIN_DECLARATIONS;
-extern const struct hash_ops dhcp_raw_options_hash_ops;
-
typedef struct sd_dhcp_server sd_dhcp_server;
-typedef struct sd_dhcp_raw_option sd_dhcp_raw_option;
int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex);
sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server);
sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server);
-int sd_dhcp_raw_option_new(uint8_t type, char *data, size_t lengt, sd_dhcp_raw_option **ret);
-sd_dhcp_raw_option *sd_dhcp_raw_option_ref(sd_dhcp_raw_option *ra);
-sd_dhcp_raw_option *sd_dhcp_raw_option_unref(sd_dhcp_raw_option *ra);
-
int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int64_t priority);
int sd_dhcp_server_detach_event(sd_dhcp_server *client);
sd_event *sd_dhcp_server_get_event(sd_dhcp_server *client);
@@ -58,7 +52,7 @@ int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], u
int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n);
int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled);
-int sd_dhcp_server_add_raw_option(sd_dhcp_server *server, sd_dhcp_raw_option *v);
+int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v);
int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t);
int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t);
@@ -66,7 +60,6 @@ int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t);
int sd_dhcp_server_forcerenew(sd_dhcp_server *server);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_server, sd_dhcp_server_unref);
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_raw_option, sd_dhcp_raw_option_unref);
_SD_END_DECLARATIONS;
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index a5f54610da..cb10ca306a 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -259,7 +259,7 @@ MaxLeaseTimeSec=
DefaultLeaseTimeSec=
EmitTimezone=
DNS=
-SendRawOption=
+SendOption=
[NextHop]
Id=
Gateway=