Merge pull request #15884 from ssahani/dhcpv6-vendor
DHCPv6: Introduce vendor specific
This commit is contained in:
@@ -11,12 +11,14 @@
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "list.h"
|
||||
#include "hashmap.h"
|
||||
#include "macro.h"
|
||||
#include "sparse-endian.h"
|
||||
|
||||
typedef struct sd_dhcp6_option {
|
||||
unsigned n_ref;
|
||||
|
||||
uint32_t enterprise_identifier;
|
||||
uint16_t option;
|
||||
void *data;
|
||||
size_t length;
|
||||
@@ -99,6 +101,7 @@ int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Add
|
||||
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
|
||||
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class);
|
||||
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **user_class);
|
||||
int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options);
|
||||
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
|
||||
size_t *optlen, uint8_t **optvalue);
|
||||
int dhcp6_option_parse_status(DHCP6Option *option, size_t len);
|
||||
|
||||
@@ -79,6 +79,39 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options) {
|
||||
sd_dhcp6_option *options;
|
||||
Iterator i;
|
||||
int r;
|
||||
|
||||
assert(buf);
|
||||
assert(*buf);
|
||||
assert(buflen);
|
||||
assert(vendor_options);
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(options, vendor_options, i) {
|
||||
_cleanup_free_ uint8_t *p = NULL;
|
||||
size_t total;
|
||||
|
||||
total = 4 + 2 + 2 + options->length;
|
||||
|
||||
p = malloc(total);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
unaligned_write_be32(p, options->enterprise_identifier);
|
||||
unaligned_write_be16(p + 4, options->option);
|
||||
unaligned_write_be16(p + 6, options->length);
|
||||
memcpy(p + 8, options->data, options->length);
|
||||
|
||||
r = dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_OPTS, total, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia) {
|
||||
uint16_t len;
|
||||
uint8_t *ia_hdr;
|
||||
@@ -683,7 +716,7 @@ static sd_dhcp6_option* dhcp6_option_free(sd_dhcp6_option *i) {
|
||||
return mfree(i);
|
||||
}
|
||||
|
||||
int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, sd_dhcp6_option **ret) {
|
||||
int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, uint32_t enterprise_identifier, sd_dhcp6_option **ret) {
|
||||
assert_return(ret, -EINVAL);
|
||||
assert_return(length == 0 || data, -EINVAL);
|
||||
|
||||
@@ -698,6 +731,7 @@ int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, sd_dhc
|
||||
*p = (sd_dhcp6_option) {
|
||||
.n_ref = 1,
|
||||
.option = option,
|
||||
.enterprise_identifier = enterprise_identifier,
|
||||
.length = length,
|
||||
.data = TAKE_PTR(q),
|
||||
};
|
||||
|
||||
@@ -81,6 +81,7 @@ struct sd_dhcp6_client {
|
||||
usec_t information_request_time_usec;
|
||||
usec_t information_refresh_time_usec;
|
||||
OrderedHashmap *extra_options;
|
||||
OrderedHashmap *vendor_options;
|
||||
};
|
||||
|
||||
static const uint16_t default_req_opts[] = {
|
||||
@@ -225,6 +226,25 @@ int sd_dhcp6_client_set_prefix_delegation_hint(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client, sd_dhcp6_option *v) {
|
||||
int r;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(v, -EINVAL);
|
||||
|
||||
r = ordered_hashmap_ensure_allocated(&client->vendor_options, &dhcp6_option_hash_ops);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_hashmap_put(client->vendor_options, v, v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
sd_dhcp6_option_ref(v);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int client_ensure_duid(sd_dhcp6_client *client) {
|
||||
if (client->duid_len != 0)
|
||||
return 0;
|
||||
@@ -622,6 +642,13 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!ordered_hashmap_isempty(client->vendor_options)) {
|
||||
r = dhcp6_option_append_vendor_option(&opt, &optlen,
|
||||
client->vendor_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->ia_pd, &client->hint_pd_prefix);
|
||||
if (r < 0)
|
||||
@@ -680,6 +707,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!ordered_hashmap_isempty(client->vendor_options)) {
|
||||
r = dhcp6_option_append_vendor_option(&opt, &optlen, client->vendor_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
|
||||
if (r < 0)
|
||||
@@ -726,6 +759,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!ordered_hashmap_isempty(client->vendor_options)) {
|
||||
r = dhcp6_option_append_vendor_option(&opt, &optlen, client->vendor_options);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(client->request, DHCP6_REQUEST_IA_PD)) {
|
||||
r = dhcp6_option_append_pd(opt, optlen, &client->lease->pd, NULL);
|
||||
if (r < 0)
|
||||
|
||||
Reference in New Issue
Block a user