[systemd-devel] [PATCH 4/8] sd-dhcp6-client: Add Option Request Option support
Zbigniew Jędrzejewski-Szmek
zbyszek at in.waw.pl
Thu Jun 26 03:59:14 PDT 2014
On Thu, Jun 26, 2014 at 01:24:14PM +0300, Patrik Flykt wrote:
> 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.
> ---
> src/libsystemd-network/dhcp6-protocol.h | 12 +++++++
> src/libsystemd-network/sd-dhcp6-client.c | 57 ++++++++++++++++++++++++++++++
> src/libsystemd-network/test-dhcp6-client.c | 9 +++++
> src/systemd/sd-dhcp6-client.h | 2 ++
> 4 files changed, 80 insertions(+)
>
> diff --git a/src/libsystemd-network/dhcp6-protocol.h b/src/libsystemd-network/dhcp6-protocol.h
> index 8b3a819..37a8671 100644
> --- a/src/libsystemd-network/dhcp6-protocol.h
> +++ b/src/libsystemd-network/dhcp6-protocol.h
> @@ -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 {
> diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
> index 928f562..f6709da 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) * sizeof(option)))
> + return -ENOMEM;
GREEDY_REALLOC takes the number of *items*, so this will overallocated if I'm
not mistaken (since commit ca2d3784147).
> +
> + 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;
>
> diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c
> index c5729db..5bb410d 100644
> --- a/src/libsystemd-network/test-dhcp6-client.c
> +++ b/src/libsystemd-network/test-dhcp6-client.c
> @@ -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);
>
> diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
> index 15e633b..93edcc4 100644
> --- a/src/systemd/sd-dhcp6-client.h
> +++ b/src/systemd/sd-dhcp6-client.h
> @@ -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);
Zbyszek
More information about the systemd-devel
mailing list