sd-dhcp6-client.c revision c601ebf79f0c54be14d3c16f0f484c0335cdeec4
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack This file is part of systemd.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack systemd is free software; you can redistribute it and/or modify it
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack under the terms of the GNU Lesser General Public License as published by
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack the Free Software Foundation; either version 2.1 of the License, or
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack (at your option) any later version.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack systemd is distributed in the hope that it will be useful, but
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack WITHOUT ANY WARRANTY; without even the implied warranty of
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack Lesser General Public License for more details.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack You should have received a copy of the GNU Lesser General Public License
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack along with systemd; If not, see <http://www.gnu.org/licenses/>.
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackconst char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST",
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel MackDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int);
d02608170e599b1ffbc7c9a22062bae2579d6e36Lennart Poetteringconst char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure",
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available",
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack [DHCP6_STATUS_NO_BINDING] = "Binding unavailable",
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel MackDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel MackDEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp6_client*, sd_dhcp6_client_unref);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack#define _cleanup_dhcp6_client_unref_ _cleanup_(sd_dhcp6_client_unrefp)
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack _cleanup_dhcp6_client_unref_ _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackint sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {
c2a23db0b91faca3795099fd4b41587bac170ff7Daniel Mackint sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
c2a23db0b91faca3795099fd4b41587bac170ff7Daniel Mack assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mackint sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
c2a23db0b91faca3795099fd4b41587bac170ff7Daniel Mackstatic int client_ensure_duid(sd_dhcp6_client *client) {
e2fa5721c3ee5ea400b99a6463e8c1c257e20415Daniel Mack return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
switch (type) {
case DHCP6_DUID_LLT:
return -EINVAL;
case DHCP6_DUID_EN:
return -EINVAL;
case DHCP6_DUID_LL:
return -EINVAL;
case DHCP6_DUID_UUID:
return -EINVAL;
size_t t;
switch(option) {
case DHCP6_OPTION_DNS_SERVERS:
case DHCP6_OPTION_DOMAIN_LIST:
case DHCP6_OPTION_NTP_SERVER:
return -EINVAL;
return -EEXIST;
return -ENOMEM;
return -ENOMSG;
if (ret)
if (!message)
return -ENOMEM;
case DHCP6_STATE_SOLICITATION:
case DHCP6_STATE_REQUEST:
case DHCP6_STATE_RENEW:
case DHCP6_STATE_REBIND:
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_BOUND:
return -EINVAL;
void *userdata) {
void *userdata) {
void *userdata) {
assert(s);
void *userdata) {
assert(s);
case DHCP6_STATE_SOLICITATION:
case DHCP6_STATE_REQUEST:
case DHCP6_STATE_RENEW:
case DHCP6_STATE_REBIND:
&expire);
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_BOUND:
if (max_retransmit_count &&
goto error;
if (max_retransmit_time &&
client);
goto error;
goto error;
goto error;
goto error;
goto error;
goto error;
r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->ia_na.id);
bool clientid = false;
&optval)) >= 0) {
switch (optcode) {
case DHCP6_OPTION_CLIENTID:
if (clientid) {
return -EINVAL;
return -EINVAL;
clientid = true;
case DHCP6_OPTION_SERVERID:
if (r >= 0 && id) {
return -EINVAL;
case DHCP6_OPTION_PREFERENCE:
return -EINVAL;
case DHCP6_OPTION_STATUS_CODE:
return -EINVAL;
if (status) {
return -EINVAL;
case DHCP6_OPTION_IA_NA:
if (r < 0 && r != -ENOMSG)
return -EINVAL;
case DHCP6_OPTION_DNS_SERVERS:
case DHCP6_OPTION_DOMAIN_LIST:
case DHCP6_OPTION_NTP_SERVER:
if (r == -ENOMSG)
if (r < 0 || !clientid) {
return -EINVAL;
bool rapid_commit;
return -ENOMEM;
if (!rapid_commit)
return DHCP6_STATE_BOUND;
r = DHCP6_STATE_REQUEST;
assert(s);
if (r < 0 || buflen <= 0)
if (!message)
return -ENOMEM;
case DHCP6_SOLICIT:
case DHCP6_REQUEST:
case DHCP6_CONFIRM:
case DHCP6_RENEW:
case DHCP6_REBIND:
case DHCP6_RELEASE:
case DHCP6_DECLINE:
case DHCP6_RELAY_FORW:
case DHCP6_RELAY_REPL:
case DHCP6_ADVERTISE:
case DHCP6_REPLY:
case DHCP6_RECONFIGURE:
case DHCP6_STATE_SOLICITATION:
if (r == DHCP6_STATE_REQUEST) {
case DHCP6_STATE_REQUEST:
case DHCP6_STATE_RENEW:
case DHCP6_STATE_REBIND:
if (r == DHCP6_STATE_BOUND) {
case DHCP6_STATE_BOUND:
case DHCP6_STATE_STOPPED:
switch (state) {
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_SOLICITATION:
case DHCP6_STATE_REQUEST:
case DHCP6_STATE_RENEW:
case DHCP6_STATE_REBIND:
case DHCP6_STATE_BOUND:
client);
client);
client);
assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &client->local_address) > 0, -EINVAL);
return -EBUSY;
client);
goto error;
goto error;
goto error;
if (event)
if (!client)
return NULL;
if (!client)
return NULL;
return client;
if (!client)
return NULL;
return NULL;
return NULL;
size_t t;
if (!client)
return -ENOMEM;
return -ENOMEM;