network: Fix split in SendOption= on client and server

When specifying `DHCPv4.SendOption=`, it is used by systemd-networkd to
set the value of that option within the DHCP request that is sent out.
This differs to setting `DHCPServer.SendOption=`, which will place all
the options together as suboptions into the vendor-specific information
(code 43) option.

This commit adds two new config options, `DHCPv4.SendVendorOption=` and
`DHCPServer.SendVendorOption=`. These both have the behaviour of the old
`DHCPServer.SendOption=` flag, and set the value of the suboption in the
vendor-specific information option.

The behaviour of `DHCPServer.SendOption=` is then changed to reflect
that of `DHCPv4.SendOption=`. It will set the value of the corresponding
option in the DHCP request.
This commit is contained in:
David Wood
2020-03-19 09:08:40 +01:00
committed by Zbigniew Jędrzejewski-Szmek
parent d69b62de44
commit 7354900ddd
12 changed files with 131 additions and 15 deletions
@@ -58,7 +58,8 @@ struct sd_dhcp_server {
struct in_addr *ntp, *dns, *sip;
unsigned n_ntp, n_dns, n_sip;
OrderedHashmap *raw_option;
OrderedHashmap *extra_options;
OrderedHashmap *vendor_options;
bool emit_router;
+36 -6
View File
@@ -89,7 +89,8 @@ struct sd_dhcp_client {
usec_t start_time;
uint64_t attempt;
uint64_t max_attempts;
OrderedHashmap *options;
OrderedHashmap *extra_options;
OrderedHashmap *vendor_options;
usec_t request_sent;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
@@ -540,17 +541,17 @@ int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempt
return 0;
}
int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) {
int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v) {
int r;
assert_return(client, -EINVAL);
assert_return(v, -EINVAL);
r = ordered_hashmap_ensure_allocated(&client->options, &dhcp_option_hash_ops);
r = ordered_hashmap_ensure_allocated(&client->extra_options, &dhcp_option_hash_ops);
if (r < 0)
return r;
r = ordered_hashmap_put(client->options, UINT_TO_PTR(v->option), v);
r = ordered_hashmap_put(client->extra_options, UINT_TO_PTR(v->option), v);
if (r < 0)
return r;
@@ -558,6 +559,25 @@ int sd_dhcp_client_set_dhcp_option(sd_dhcp_client *client, sd_dhcp_option *v) {
return 0;
}
int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v) {
int r;
assert_return(client, -EINVAL);
assert_return(v, -EINVAL);
r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp_option_hash_ops);
if (r < 0)
return -ENOMEM;
r = ordered_hashmap_put(client->vendor_options, v, v);
if (r < 0)
return r;
sd_dhcp_option_ref(v);
return 1;
}
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
assert_return(client, -EINVAL);
@@ -884,13 +904,22 @@ static int client_send_discover(sd_dhcp_client *client) {
return r;
}
ORDERED_HASHMAP_FOREACH(j, client->options, i) {
ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) {
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
j->option, j->length, j->data);
if (r < 0)
return r;
}
if (!ordered_hashmap_isempty(client->vendor_options)) {
r = dhcp_option_append(
&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_VENDOR_SPECIFIC,
ordered_hashmap_size(client->vendor_options), client->vendor_options);
if (r < 0)
return r;
}
r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
@@ -2073,7 +2102,8 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
free(client->hostname);
free(client->vendor_class_identifier);
client->user_class = strv_free(client->user_class);
ordered_hashmap_free(client->options);
ordered_hashmap_free(client->extra_options);
ordered_hashmap_free(client->vendor_options);
return mfree(client);
}
+33 -5
View File
@@ -143,7 +143,8 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) {
hashmap_free(server->leases_by_client_id);
ordered_hashmap_free(server->raw_option);
ordered_hashmap_free(server->extra_options);
ordered_hashmap_free(server->vendor_options);
free(server->bound_leases);
return mfree(server);
@@ -455,6 +456,8 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
be32_t address) {
_cleanup_free_ DHCPPacket *packet = NULL;
be32_t lease_time;
sd_dhcp_option *j;
Iterator i;
size_t offset;
int r;
@@ -519,11 +522,18 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req,
return r;
}
if (!ordered_hashmap_isempty(server->raw_option)) {
ORDERED_HASHMAP_FOREACH(j, server->extra_options, i) {
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
j->option, j->length, j->data);
if (r < 0)
return r;
}
if (!ordered_hashmap_isempty(server->vendor_options)) {
r = dhcp_option_append(
&packet->dhcp, req->max_optlen, &offset, 0,
SD_DHCP_OPTION_VENDOR_SPECIFIC,
ordered_hashmap_size(server->raw_option), server->raw_option);
ordered_hashmap_size(server->vendor_options), server->vendor_options);
if (r < 0)
return r;
}
@@ -1188,11 +1198,29 @@ int sd_dhcp_server_add_option(sd_dhcp_server *server, sd_dhcp_option *v) {
assert_return(server, -EINVAL);
assert_return(v, -EINVAL);
r = ordered_hashmap_ensure_allocated(&server->raw_option, &dhcp_option_hash_ops);
r = ordered_hashmap_ensure_allocated(&server->extra_options, &dhcp_option_hash_ops);
if (r < 0)
return r;
r = ordered_hashmap_put(server->extra_options, UINT_TO_PTR(v->option), v);
if (r < 0)
return r;
sd_dhcp_option_ref(v);
return 0;
}
int sd_dhcp_server_add_vendor_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->vendor_options, &dhcp_option_hash_ops);
if (r < 0)
return -ENOMEM;
r = ordered_hashmap_put(server->raw_option, v, v);
r = ordered_hashmap_put(server->vendor_options, v, v);
if (r < 0)
return r;