sd-network: DHCPv6 - add support to send userclass option

sd-network: DHCPv6 - add support to send userclass option

21.15.  User Class Option

   The User Class option is used by a client to identify the type or
   category of users or applications it represents.

   The format of the User 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_USER_CLASS       |          option-len           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      .                                                               .
      .                          user-class-data                      .
      .                                                               .
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                    Figure 26: User Class Option Format

      option-code          OPTION_USER_CLASS (15).

      option-len           Length of user-class-data field.

      user-class-data      The user classes carried by the client.  The
                           length, in octets, is specified by
                           option-len.

The information contained in the data area of this option is
   contained in one or more opaque fields that represent the user class
   or classes of which the client is a member.  A server selects
   configuration information for the client based on the classes
   identified in this option.  For example, the User Class option can be
   used to configure all clients of people in the accounting department
   with a different printer than clients of people in the marketing
   department.  The user class information carried in this option MUST
   be configurable on the client.

   The data area of the User Class option MUST contain one or more
   instances of user-class-data information.  Each instance of
   user-class-data is formatted as follows:

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

                Figure 27: Format of user-class-data Field
This commit is contained in:
Susant Sahani 2020-05-18 14:46:50 +02:00
parent 44dcb318cc
commit 3392392518
4 changed files with 78 additions and 0 deletions

View file

@ -97,6 +97,7 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
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_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

@ -167,6 +167,36 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
return r;
}
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class) {
_cleanup_free_ uint8_t *p = NULL;
size_t total = 0, offset = 0;
char **s;
assert_return(buf && *buf && buflen && user_class, -EINVAL);
STRV_FOREACH(s, user_class) {
size_t len = strlen(*s);
uint8_t *q;
if (len > 0xffff)
return -ENAMETOOLONG;
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_USER_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

@ -67,6 +67,7 @@ struct sd_dhcp6_client {
size_t req_opts_len;
char *fqdn;
char *mudurl;
char **user_class;
sd_event_source *receive_message;
usec_t retransmit_time;
uint8_t retransmit_count;
@ -385,6 +386,27 @@ int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mud
return free_and_strdup(&client->mudurl, mudurl);
}
int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_class) {
_cleanup_strv_free_ char **s = NULL;
char **p;
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(user_class, -EINVAL);
STRV_FOREACH(p, user_class)
if (strlen(*p) > UINT16_MAX)
return -ENAMETOOLONG;
s = strv_copy((char **) user_class);
if (!s)
return -ENOMEM;
client->user_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);
@ -565,6 +587,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->user_class) {
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_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)
@ -611,6 +639,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->user_class) {
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_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)
@ -645,6 +679,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
return r;
}
if (client->user_class) {
r = dhcp6_option_append_user_class(&opt, &optlen, client->user_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)
@ -1602,7 +1642,10 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
free(client->req_opts);
free(client->fqdn);
free(client->mudurl);
ordered_hashmap_free(client->extra_options);
strv_free(client->user_class);
return mfree(client);
}

View file

@ -125,6 +125,10 @@ 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_prefix_delegation_hint(
sd_dhcp6_client *client,
uint8_t prefixlen,