summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-dhcp6-client.c
diff options
context:
space:
mode:
authorPatrik Flykt <patrik.flykt@linux.intel.com>2014-06-24 16:20:32 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2014-06-26 16:10:11 +0300
commitda6fe470e17fa02f3adedc779585caf8669252bd (patch)
tree1013abf1c360df17f402ca70ec024636364c671e /src/libsystemd-network/sd-dhcp6-client.c
parent1873a3d344042e818d2a5762c0ebfc3823c8f84d (diff)
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.
Diffstat (limited to 'src/libsystemd-network/sd-dhcp6-client.c')
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 928f562df0..5d65603dc2 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -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;