1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-10 01:17:44 +03:00

sd-network: DHCPv6 - Add support to send vendor class data

```
21.16.  Vendor Class Option

   This option is used by a client to identify the vendor that
   manufactured the hardware on which the client is running.  The
   information contained in the data area of this option is contained in
   one or more opaque fields that identify details of the hardware
   configuration.  The format of the Vendor Class 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_CLASS      |           option-len          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                       enterprise-number                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      .                                                               .
      .                       vendor-class-data                       .
      .                             . . .                             .
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                   Figure 28: Vendor Class Option Format

      option-code          OPTION_VENDOR_CLASS (16).

      option-len           4 + length of vendor-class-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-class-data    The hardware configuration of the node on
                           which the client is running.  A
                           variable-length field (4 octets less than the
                           value in the option-len field).

   The vendor-class-data field is composed of a series of separate
   items, each of which describes some characteristic of the client's
   hardware configuration.  Examples of vendor-class-data instances
   might include the version of the operating system the client is
   running or the amount of memory installed on the client.

   Each instance of vendor-class-data is formatted as follows:

      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+
      |       vendor-class-len        |          opaque-data          |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+

               Figure 29: Format of vendor-class-data Field

   The vendor-class-len field is 2 octets long and specifies the length
   of the opaque vendor-class-data in network byte order.

   Servers and clients MUST NOT include more than one instance of
   OPTION_VENDOR_CLASS with the same Enterprise Number.  Each instance
   of OPTION_VENDOR_CLASS can carry multiple vendor-class-data
   instances.
   ```
This commit is contained in:
Susant Sahani 2020-04-20 09:04:58 +02:00
parent d08a6ec39c
commit 73c8ced784
6 changed files with 90 additions and 4 deletions

View File

@ -15,7 +15,6 @@
#include "udev-util.h"
#include "virt.h"
#define SYSTEMD_PEN 43793
#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
#define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */

View File

@ -8,6 +8,8 @@
#include "time-util.h"
#include "unaligned.h"
#define SYSTEMD_PEN 43793
typedef enum DUIDType {
DUID_TYPE_LLT = 1,
DUID_TYPE_EN = 2,

View File

@ -98,6 +98,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
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_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);

View File

@ -9,6 +9,7 @@
#include "sd-dhcp6-client.h"
#include "alloc-util.h"
#include "dhcp-identifier.h"
#include "dhcp6-internal.h"
#include "dhcp6-lease-internal.h"
#include "dhcp6-protocol.h"
@ -180,7 +181,6 @@ int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_cl
if (len > 0xffff)
return -ENAMETOOLONG;
q = realloc(p, total + len + 2);
if (!q)
return -ENOMEM;
@ -197,6 +197,46 @@ int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_cl
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p);
}
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **vendor_class) {
_cleanup_free_ uint8_t *p = NULL;
uint32_t enterprise_identifier;
size_t total, offset;
char **s;
assert(buf);
assert(*buf);
assert(buflen);
assert(vendor_class);
enterprise_identifier = htobe32(SYSTEMD_PEN);
p = memdup(&enterprise_identifier, sizeof(enterprise_identifier));
if (!p)
return -ENOMEM;
total = sizeof(enterprise_identifier);
offset = total;
STRV_FOREACH(s, vendor_class) {
size_t len = strlen(*s);
uint8_t *q;
q = realloc(p, total + len + 2);
if (!q)
return -ENOMEM;
p = q;
unaligned_write_be16(&p[offset], len);
memcpy(&p[offset + 2], *s, len);
offset += 2 + len;
total += 2 + len;
}
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_VENDOR_CLASS, total, p);
}
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix) {
DHCP6Option *option = (DHCP6Option *)buf;
size_t i = sizeof(*option) + sizeof(pd->ia_pd);

View File

@ -68,6 +68,7 @@ struct sd_dhcp6_client {
char *fqdn;
char *mudurl;
char **user_class;
char **vendor_class;
sd_event_source *receive_message;
usec_t retransmit_time;
uint8_t retransmit_count;
@ -380,7 +381,7 @@ int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mud
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(mudurl, -EINVAL);
assert_return(strlen(mudurl) <= 255, -EINVAL);
assert_return(strlen(mudurl) <= UINT8_MAX, -EINVAL);
assert_return(http_url_is_valid(mudurl), -EINVAL);
return free_and_strdup(&client->mudurl, mudurl);
@ -392,6 +393,7 @@ int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(user_class, -EINVAL);
STRV_FOREACH(p, user_class)
@ -407,6 +409,27 @@ int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_
return 0;
}
int sd_dhcp6_client_set_request_vendor_class(sd_dhcp6_client *client, char **vendor_class) {
_cleanup_strv_free_ char **s = NULL;
char **p;
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(vendor_class, -EINVAL);
STRV_FOREACH(p, vendor_class)
if (strlen(*p) > UINT8_MAX)
return -ENAMETOOLONG;
s = strv_copy(vendor_class);
if (!s)
return -ENOMEM;
client->vendor_class = TAKE_PTR(s);
return 0;
}
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
assert_return(client, -EINVAL);
assert_return(delegation, -EINVAL);
@ -593,6 +616,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->vendor_class) {
r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class);
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)
@ -645,6 +674,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->vendor_class) {
r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class);
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)
@ -685,6 +720,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->vendor_class) {
r = dhcp6_option_append_vendor_class(&opt, &optlen, client->vendor_class);
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)
@ -1645,6 +1686,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
ordered_hashmap_free(client->extra_options);
strv_free(client->user_class);
strv_free(client->vendor_class);
return mfree(client);
}

View File

@ -125,10 +125,12 @@ int sd_dhcp6_client_set_request_option(
int sd_dhcp6_client_set_request_mud_url(
sd_dhcp6_client *client,
const char *mudurl);
int sd_dhcp6_client_set_request_user_class(
sd_dhcp6_client *client,
char** user_class);
int sd_dhcp6_client_set_request_vendor_class(
sd_dhcp6_client *client,
char** vendor_class);
int sd_dhcp6_client_set_prefix_delegation_hint(
sd_dhcp6_client *client,
uint8_t prefixlen,