mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-10 01:17:44 +03:00
sd-dhcp6: Introduce vendor specific information
RFC: 8415 21.17. Vendor-specific Information Option This option is used by clients and servers to exchange vendor- specific information. The format of the Vendor-specific Information option is: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | OPTION_VENDOR_OPTS | option-len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | enterprise-number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ . . . vendor-option-data . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 30: Vendor-specific Information Option Format option-code OPTION_VENDOR_OPTS (17). option-len 4 + length of vendor-option-data field. enterprise-number The vendor's registered Enterprise Number as maintained by IANA [IANA-PEN]. A 4-octet field containing an unsigned integer. vendor-option-data Vendor options, interpreted by vendor-specific code on the clients and servers. A variable-length field (4 octets less than the value in the option-len field). The definition of the information carried in this option is vendor specific. The vendor is indicated in the enterprise-number field. Use of vendor-specific information allows enhanced operation, utilizing additional features in a vendor's DHCP implementation. A DHCP client that does not receive requested vendor-specific information will still configure the node's IPv6 stack to be functional. The vendor-option-data field MUST be encoded as a sequence of code/length/value fields of format identical to the DHCP options (see Section 21.1). The sub-option codes are defined by the vendor identified in the enterprise-number field and are not managed by IANA. Each of the sub-options is formatted as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | sub-opt-code | sub-option-len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ . . . sub-option-data . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 31: Vendor-specific Options Format sub-opt-code The code for the sub-option. A 2-octet field. sub-option-len An unsigned integer giving the length of the sub-option-data field in this sub-option in octets. A 2-octet field. sub-option-data The data area for the sub-option. The length, in octets, is specified by sub-option-len. Multiple instances of the Vendor-specific Information option may appear in a DHCP message. Each instance of the option is interpreted according to the option codes defined by the vendor identified by the Enterprise Number in that option. Servers and clients MUST NOT send more than one instance of the Vendor-specific Information option with the same Enterprise Number. Each instance of the Vendor-specific Information option MAY contain multiple sub-options. A client that is interested in receiving a Vendor-specific Information option: - MUST specify the Vendor-specific Information option in an Option Request option. - MAY specify an associated Vendor Class option (see Section 21.16). - MAY specify the Vendor-specific Information option with appropriate data. Servers only return the Vendor-specific Information options if specified in Option Request options from clients and: - MAY use the Enterprise Numbers in the associated Vendor Class options to restrict the set of Enterprise Numbers in the Vendor-specific Information options returned. - MAY return all configured Vendor-specific Information options. - MAY use other information in the packet or in its configuration to determine which set of Enterprise Numbers in the Vendor-specific Information options to return.
This commit is contained in:
parent
4737345173
commit
99ccb8ff89
@ -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)
|
||||
|
@ -24,6 +24,7 @@ _not_installed_headers = '''
|
||||
sd-dhcp-client.h
|
||||
sd-dhcp-lease.h
|
||||
sd-dhcp-option.h
|
||||
sd-dhcp6-option.h
|
||||
sd-dhcp-server.h
|
||||
sd-ipv4acd.h
|
||||
sd-ipv4ll.h
|
||||
|
@ -143,7 +143,10 @@ int sd_dhcp6_client_get_address_request(sd_dhcp6_client *client,
|
||||
int *request);
|
||||
int sd_dhcp6_client_set_address_request(sd_dhcp6_client *client,
|
||||
int request);
|
||||
int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client, uint32_t transaction_id);
|
||||
int sd_dhcp6_client_set_transaction_id(sd_dhcp6_client *client,
|
||||
uint32_t transaction_id);
|
||||
int sd_dhcp6_client_add_vendor_option(sd_dhcp6_client *client,
|
||||
sd_dhcp6_option *v);
|
||||
|
||||
int sd_dhcp6_client_get_lease(
|
||||
sd_dhcp6_client *client,
|
||||
|
@ -26,7 +26,7 @@ _SD_BEGIN_DECLARATIONS;
|
||||
|
||||
typedef struct sd_dhcp6_option sd_dhcp6_option;
|
||||
|
||||
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);
|
||||
sd_dhcp6_option *sd_dhcp6_option_ref(sd_dhcp6_option *ra);
|
||||
sd_dhcp6_option *sd_dhcp6_option_unref(sd_dhcp6_option *ra);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user