74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright (C) 2014-2015 Intel Corporation. All rights reserved.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poetteringstatic const uint16_t default_req_opts[] = {
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poetteringconst char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering [DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST",
2001c80560e3dae69e14fd994d3978c187af48b8Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_type, int);
2001c80560e3dae69e14fd994d3978c187af48b8Lennart Poetteringconst char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering [DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering [DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available",
7b50eb2efa122200e39646c19a29abab302f7d24Lennart Poettering [DHCP6_STATUS_NO_BINDING] = "Binding unavailable",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering [DHCP6_STATUS_NOT_ON_LINK] = "Not on link",
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering [DHCP6_STATUS_USE_MULTICAST] = "Use multicast",
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(dhcp6_message_status, int);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define DHCP6_CLIENT_DONT_DESTROY(client) \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(sd_dhcp6_client_unrefp) _unused_ sd_dhcp6_client *_dont_destroy_##client = sd_dhcp6_client_ref(client)
f5430a3ef308f3a102899fcaf7fbece757082f2aLennart Poetteringstatic int client_start(sd_dhcp6_client *client, enum DHCP6State state);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint sd_dhcp6_client_set_callback(sd_dhcp6_client *client, sd_dhcp6_client_cb_t cb, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_return(interface_index >= -1, -EINVAL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek assert_return(arp_type > 0, -EINVAL);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek assert_return(addr_len == ETH_ALEN, -EINVAL);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek else if (arp_type == ARPHRD_INFINIBAND)
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (client->mac_addr_len == addr_len &&
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek memcmp(&client->mac_addr, addr, addr_len) == 0)
549c1a2564b56f2bb38f1203d59c747ea15817f3Tom Gundersenstatic int client_ensure_duid(sd_dhcp6_client *client) {
549c1a2564b56f2bb38f1203d59c747ea15817f3Tom Gundersen return dhcp_identifier_set_duid_en(&client->duid, &client->duid_len);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek if (duid_len <= sizeof(client->duid.llt))
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek if (duid_len != sizeof(client->duid.en))
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek if (duid_len <= sizeof(client->duid.ll))
9ead3519c54b6d1b79b35541873b5cf7c8b3a7d3Lennart Poettering if (duid_len != sizeof(client->duid.uuid))
50f1e641a93cacfc693b0c3d300bee5df0c8c460Tom Gundersen /* accept unknown type in order to be forward compatible */
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen memcpy(&client->duid.raw.data, duid, duid_len);
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersen client->duid_len = duid_len + sizeof(client->duid.type);
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersenint sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, int enabled) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint sd_dhcp6_client_get_information_request(sd_dhcp6_client *client, int *enabled) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option) {
105e151299dc1208855380be2b22d0db2d66ebc6Lennart Poettering assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (t = 0; t < client->req_opts_len; t++)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (client->req_opts[t] == htobe16(option))
7b50eb2efa122200e39646c19a29abab302f7d24Lennart Poettering if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated,
a8812dd7f161a3e459c1730ac92ff2bbc9986ff1Lennart Poettering client->req_opts[client->req_opts_len++] = htobe16(option);
8730bccfc59fe507bd3e0a3abcf411b497ac4f0eLennart Poetteringint sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
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);
&optval)) >= 0) {
switch (optcode) {
case SD_DHCP6_OPTION_CLIENTID:
if (clientid) {
return -EINVAL;
return -EINVAL;
clientid = true;
case SD_DHCP6_OPTION_SERVERID:
if (r >= 0 && id) {
return -EINVAL;
return -EINVAL;
return -EINVAL;
if (status) {
return -EINVAL;
case SD_DHCP6_OPTION_IA_NA:
if (r < 0 && r != -ENOMSG)
return -EINVAL;
if (r == -ENOMSG)
if (r < 0 || !clientid) {
return -EINVAL;
return -ENOMEM;
if (!rapid_commit)
return DHCP6_STATE_BOUND;
r = DHCP6_STATE_REQUEST;
assert(s);
return -errno;
else if (buflen < 0)
return -EIO;
if (!message)
return -ENOMEM;
if (len < 0) {
return -errno;
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;