sd-dhcp6-client: Add Option Request Option support

Provide a function to request more options from the DHCPv6 server.
Provide a sensible default set at startup and add test basic test
cases for the intended usage.

Define DNS and NTP related option codes and add comments for the
unassigned codes.
This commit is contained in:
Patrik Flykt 2014-06-24 16:20:32 +03:00
parent 1873a3d344
commit da6fe470e1
4 changed files with 80 additions and 0 deletions

View file

@ -111,6 +111,18 @@ enum {
DHCP6_OPTION_INTERFACE_ID = 18,
DHCP6_OPTION_RECONF_MSG = 19,
DHCP6_OPTION_RECONF_ACCEPT = 20,
DHCP6_OPTION_DNS_SERVERS = 23, /* RFC 3646 */
DHCP6_OPTION_DOMAIN_LIST = 24, /* RFC 3646 */
DHCP6_OPTION_SNTP_SERVERS = 31, /* RFC 4075 */
/* option code 35 is unassigned */
DHCP6_OPTION_NTP_SERVER = 56, /* RFC 5908 */
/* option codes 89-142 are unassigned */
/* option codes 144-65535 are unassigned */
};
enum {

View file

@ -51,6 +51,9 @@ struct sd_dhcp6_client {
be32_t transaction_id;
struct sd_dhcp6_lease *lease;
int fd;
be16_t *req_opts;
size_t req_opts_allocated;
size_t req_opts_len;
sd_event_source *receive_message;
usec_t retransmit_time;
uint8_t retransmit_count;
@ -66,6 +69,12 @@ struct sd_dhcp6_client {
} _packed_ duid;
};
static const uint16_t default_req_opts[] = {
DHCP6_OPTION_DNS_SERVERS,
DHCP6_OPTION_DOMAIN_LIST,
DHCP6_OPTION_NTP_SERVER,
};
const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
[DHCP6_SOLICIT] = "SOLICIT",
[DHCP6_ADVERTISE] = "ADVERTISE",
@ -137,6 +146,37 @@ int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
return 0;
}
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
uint16_t option) {
size_t t;
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
switch(option) {
case DHCP6_OPTION_DNS_SERVERS:
case DHCP6_OPTION_DOMAIN_LIST:
case DHCP6_OPTION_SNTP_SERVERS:
case DHCP6_OPTION_NTP_SERVER:
break;
default:
return -EINVAL;
}
for (t = 0; t < client->req_opts_len; t++)
if (client->req_opts[t] == htobe16(option))
return -EEXIST;
if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
client->req_opts_len + 1))
return -ENOMEM;
client->req_opts[client->req_opts_len++] = htobe16(option);
return 0;
}
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
assert_return(client, -EINVAL);
assert_return(ret, -EINVAL);
@ -239,6 +279,12 @@ static int client_send_message(sd_dhcp6_client *client) {
return -EINVAL;
}
r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_ORO,
client->req_opts_len * sizeof(be16_t),
client->req_opts);
if (r < 0)
return r;
r = dhcp6_option_append(&opt, &optlen, DHCP6_OPTION_CLIENTID,
sizeof(client->duid), &client->duid);
if (r < 0)
@ -927,6 +973,7 @@ sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) {
sd_dhcp6_client_detach_event(client);
free(client->req_opts);
free(client);
return NULL;
@ -940,6 +987,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret)
_cleanup_dhcp6_client_unref_ sd_dhcp6_client *client = NULL;
sd_id128_t machine_id;
int r;
size_t t;
assert_return(ret, -EINVAL);
@ -968,6 +1016,15 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret)
siphash24(client->duid.id, &machine_id, sizeof(machine_id),
HASH_KEY.bytes);
client->req_opts_len = ELEMENTSOF(default_req_opts);
client->req_opts = new0(be16_t, client->req_opts_len);
if (!client->req_opts)
return -ENOMEM;
for (t = 0; t < client->req_opts_len; t++)
client->req_opts[t] = htobe16(default_req_opts[t]);
*ret = client;
client = NULL;

View file

@ -68,6 +68,13 @@ static int test_client_basic(sd_event *e) {
assert_se(sd_dhcp6_client_set_mac(client, &mac_addr) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_CLIENTID) == -EINVAL);
assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_NTP_SERVER) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_SNTP_SERVERS) == 0);
assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
assert_se(sd_dhcp6_client_detach_event(client) >= 0);
@ -520,6 +527,8 @@ static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
assert_se(e);
assert_se(event == DHCP6_EVENT_IP_ACQUIRE);
assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
if (verbose)
printf(" got DHCPv6 event %d\n", event);

View file

@ -45,6 +45,8 @@ int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
const struct ether_addr *mac_addr);
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,
uint16_t option);
int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret);