sd-dhcp6-client.c revision 6ec60d20724d2a32e20d25ef75d2af178c242bc2
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright (C) 2014 Intel Corporation. All rights reserved.
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <string.h>
#include "udev.h"
#include "udev-util.h"
#include "virt.h"
#include "siphash24.h"
#include "util.h"
#include "refcnt.h"
#include "network-internal.h"
#include "sd-dhcp6-client.h"
#include "dhcp6-protocol.h"
#include "dhcp6-internal.h"
#include "dhcp6-lease-internal.h"
#define SYSTEMD_PEN 43793
struct sd_dhcp6_client {
enum DHCP6State state;
int event_priority;
int index;
struct ether_addr mac_addr;
struct sd_dhcp6_lease *lease;
int fd;
void *userdata;
struct duid_en {
};
const char * dhcp6_message_type_table[_DHCP6_MESSAGE_MAX] = {
[DHCP6_SOLICIT] = "SOLICIT",
[DHCP6_ADVERTISE] = "ADVERTISE",
[DHCP6_REQUEST] = "REQUEST",
[DHCP6_CONFIRM] = "CONFIRM",
[DHCP6_RENEW] = "RENEW",
[DHCP6_REBIND] = "REBIND",
[DHCP6_REPLY] = "REPLY",
[DHCP6_RELEASE] = "RELEASE",
[DHCP6_DECLINE] = "DECLINE",
[DHCP6_RECONFIGURE] = "RECONFIGURE",
[DHCP6_INFORMATION_REQUEST] = "INFORMATION-REQUEST",
[DHCP6_RELAY_FORW] = "RELAY-FORW",
[DHCP6_RELAY_REPL] = "RELAY-REPL",
};
const char * dhcp6_message_status_table[_DHCP6_STATUS_MAX] = {
[DHCP6_STATUS_SUCCESS] = "Success",
[DHCP6_STATUS_UNSPEC_FAIL] = "Unspecified failure",
[DHCP6_STATUS_NO_ADDRS_AVAIL] = "No addresses available",
[DHCP6_STATUS_NO_BINDING] = "Binding unavailable",
[DHCP6_STATUS_NOT_ON_LINK] = "Not on link",
[DHCP6_STATUS_USE_MULTICAST] = "Use multicast",
};
{
return 0;
}
{
return 0;
}
const struct ether_addr *mac_addr)
{
if (mac_addr)
else
return 0;
}
return -ENOMSG;
return 0;
}
}
return client;
}
client->transaction_id = 0;
client->retransmit_time = 0;
client->retransmit_count = 0;
return 0;
}
if (client)
return client;
}
struct in6_addr all_servers =
int r;
if (!message)
return -ENOMEM;
case DHCP6_STATE_SOLICITATION:
if (r < 0)
return r;
break;
case DHCP6_STATE_REQUEST:
if (r < 0)
return r;
if (r < 0)
return r;
break;
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
case DHCP6_STATE_BOUND:
return -EINVAL;
}
if (r < 0)
return r;
if (r < 0)
return r;
return 0;
}
void *userdata) {
assert_return(s, -EINVAL);
return 0;
}
void *userdata) {
assert_return(s, -EINVAL);
return 0;
}
void *userdata) {
assert(s);
return 0;
}
}
void *userdata) {
int r = 0;
char time_string[FORMAT_TIMESPAN_MAX];
assert(s);
case DHCP6_STATE_SOLICITATION:
return 0;
}
max_retransmit_count = 0;
break;
case DHCP6_STATE_REQUEST:
break;
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
case DHCP6_STATE_BOUND:
return 0;
}
if (max_retransmit_count &&
return 0;
}
r = client_send_message(client);
if (r >= 0)
if (r < 0)
goto error;
if (!client->retransmit_time) {
} else {
if (max_retransmit_time &&
else
}
client->retransmit_time, 0));
client);
if (r < 0)
goto error;
if (r < 0)
goto error;
if (r < 0)
goto error;
if (r < 0)
goto error;
}
if (r < 0)
client_stop(client, r);
return 0;
}
return 0;
if (detect_container(NULL) <= 0) {
/* not in a container, udev will be around */
if (!udev)
return -ENOMEM;
if (!device)
return -errno;
if (udev_device_get_is_initialized(device) <= 0)
/* not yet ready */
return -EBUSY;
}
if (name)
else
/* fall back to mac address if no predictable name available */
/* fold into 32 bits */
return 0;
}
sd_dhcp6_lease *lease) {
int r;
bool clientid = false;
&optval)) >= 0) {
switch (optcode) {
case DHCP6_OPTION_CLIENTID:
if (clientid) {
return -EINVAL;
}
return -EINVAL;
}
clientid = true;
break;
case DHCP6_OPTION_SERVERID:
if (r >= 0 && id) {
return -EINVAL;
}
if (r < 0)
return r;
break;
case DHCP6_OPTION_PREFERENCE:
if (optlen != 1)
return -EINVAL;
if (r < 0)
return r;
break;
case DHCP6_OPTION_STATUS_CODE:
if (optlen < 2)
return -EINVAL;
if (status) {
return -EINVAL;
}
break;
case DHCP6_OPTION_IA_NA:
if (r < 0 && r != -ENOMSG)
return r;
if (r < 0)
return r;
return -EINVAL;
}
break;
}
}
return -EINVAL;
}
if (r < 0)
return r;
}
{
int r;
return -EINVAL;
r = dhcp6_lease_new(&lease);
if (r < 0)
return -ENOMEM;
if (r < 0)
return r;
return DHCP6_STATE_BOUND;
}
int r;
return -EINVAL;
r = dhcp6_lease_new(&lease);
if (r < 0)
return r;
if (r < 0)
return r;
if (r < 0)
return r;
r = 0;
}
r = DHCP6_STATE_REQUEST;
return r;
}
void *userdata) {
assert(s);
if (r < 0 || buflen <= 0)
if (!message)
return -ENOMEM;
return 0;
}
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:
return 0;
case DHCP6_ADVERTISE:
case DHCP6_REPLY:
case DHCP6_RECONFIGURE:
break;
default:
return 0;
}
htobe32(0x00ffffff)))
return 0;
case DHCP6_STATE_SOLICITATION:
if (r == DHCP6_STATE_REQUEST)
client_start(client, r);
break;
case DHCP6_STATE_REQUEST:
if (r < 0)
return 0;
if (r == DHCP6_STATE_BOUND) {
if (r < 0) {
client_stop(client, r);
return 0;
}
if (!client)
return 0;
}
break;
case DHCP6_STATE_BOUND:
break;
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
return 0;
}
if (r >= 0) {
}
return 0;
}
{
int r;
char time_string[FORMAT_TIMESPAN_MAX];
client->retransmit_time = 0;
client->retransmit_count = 0;
switch (state) {
case DHCP6_STATE_STOPPED:
case DHCP6_STATE_RS:
case DHCP6_STATE_SOLICITATION:
r = client_ensure_iaid(client);
if (r < 0)
return r;
if (r < 0)
return r;
client);
if (r < 0)
return r;
if (r < 0)
return r;
break;
case DHCP6_STATE_REQUEST:
break;
case DHCP6_STATE_BOUND:
if (r < 0)
return r;
return 0;
}
timeout, 0));
client);
if (r < 0)
return r;
if (r < 0)
return r;
timeout, 0));
client);
if (r < 0)
return r;
if (r < 0)
return r;
return 0;
}
CLOCK_MONOTONIC, 0, 0, client_timeout_resend,
client);
if (r < 0)
return r;
if (r < 0)
return r;
return 0;
}
{
return 0;
}
{
int r = 0;
r = client_reset(client);
if (r < 0)
return r;
}
int priority)
{
int r;
if (event)
else {
if (r < 0)
return 0;
}
return 0;
}
return 0;
}
if (!client)
return NULL;
}
if (client)
return client;
}
return NULL;
}
return client;
}
{
int r;
if (!client)
return -ENOMEM;
/* initialize DUID */
r = sd_id128_get_machine(&machine_id);
if (r < 0)
return r;
/* a bit of snake-oil perhaps, but no need to expose the machine-id
directly */
return 0;
}