sd-dhcp-client.c revision 4f882b2a5007e51032459e29d15a86df6b5ea9f4
/***
This file is part of systemd.
Copyright (C) 2013 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 <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <net/ethernet.h>
#include "util.h"
#include "list.h"
#include "dhcp-protocol.h"
#include "dhcp-internal.h"
#include "sd-dhcp-client.h"
#define DHCP_CLIENT_MIN_OPTIONS_SIZE 312
struct DHCPLease {
};
struct sd_dhcp_client {
int index;
int fd;
union sockaddr_union link;
struct ether_addr mac_addr;
unsigned int attempt;
void *userdata;
};
static const uint8_t default_req_opts[] = {
};
void *userdata)
{
return 0;
}
{
size_t i;
switch(option) {
case DHCP_OPTION_PAD:
case DHCP_OPTION_OVERLOAD:
case DHCP_OPTION_MESSAGE_TYPE:
case DHCP_OPTION_END:
return -EINVAL;
default:
break;
}
for (i = 0; i < client->req_opts_size; i++)
return -EEXIST;
return -ENOMEM;
return 0;
}
{
if (last_addr)
else
return 0;
}
{
return 0;
}
const struct ether_addr *addr)
{
return 0;
}
{
case DHCP_STATE_INIT:
case DHCP_STATE_SELECTING:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_REQUESTING:
return -EADDRNOTAVAIL;
case DHCP_STATE_BOUND:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
break;
}
return 0;
}
{
case DHCP_STATE_INIT:
case DHCP_STATE_SELECTING:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_REQUESTING:
return -EADDRNOTAVAIL;
case DHCP_STATE_BOUND:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
else
return -ENOENT;
break;
}
return 0;
}
{
case DHCP_STATE_INIT:
case DHCP_STATE_SELECTING:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_REQUESTING:
return -EADDRNOTAVAIL;
case DHCP_STATE_BOUND:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
else
return -ENOENT;
break;
}
return 0;
}
{
int len = 0;
while (mask) {
len++;
}
return len;
}
{
case DHCP_STATE_INIT:
case DHCP_STATE_SELECTING:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_REQUESTING:
return -EADDRNOTAVAIL;
case DHCP_STATE_BOUND:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
break;
}
return 0;
}
{
case DHCP_STATE_INIT:
case DHCP_STATE_SELECTING:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_REQUESTING:
return -EADDRNOTAVAIL;
case DHCP_STATE_BOUND:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
break;
}
return 0;
}
{
return 0;
}
unsigned i;
if (!addrs)
return;
for (i = 0; addrs[i]; i++)
}
{
case DHCP_STATE_INIT:
case DHCP_STATE_SELECTING:
case DHCP_STATE_REQUESTING:
case DHCP_STATE_BOUND:
client->start_time = 0;
break;
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
break;
}
}
return 0;
}
{
int err;
if (*optlen < 4)
return -ENOBUFS;
*optlen -= 4;
/* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
refuse to issue an DHCP lease if 'secs' is set to zero */
(*opt)[0] = 0x63;
*opt += 4;
&type);
if (err < 0)
return err;
/* Some DHCP servers will refuse to issue an DHCP lease if the Cliient
Identifier option is not set */
if (err < 0)
return err;
if (err < 0)
return err;
/* Some DHCP servers will send bigger DHCP packets than the
defined default size unless the Maximum Messge Size option
is explicitely set */
2, &max_size);
if (err < 0)
return err;
}
return 0;
}
{
int i;
sum = 0;
for (i = 0; i < len / 2 ; i++)
if (len & 0x01) {
}
while (sum >> 16)
return ~sum;
}
{
}
{
int err = 0;
if (!discover)
return -ENOMEM;
if (err < 0)
return err;
if (err < 0)
return err;
}
if (err < 0)
return err;
return err;
}
{
int err;
if (!request)
return -ENOMEM;
if (err < 0)
return err;
if (err < 0)
return err;
if (err < 0)
return err;
}
if (err < 0)
return err;
len - DHCP_IP_UDP_SIZE);
} else {
}
return err;
}
void *userdata)
{
usec_t next_timeout = 0;
int err = 0;
case DHCP_STATE_RENEWING:
if (time_left < 60)
time_left = 60;
break;
case DHCP_STATE_REBINDING:
if (time_left < 60)
time_left = 60;
break;
case DHCP_STATE_INIT:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_SELECTING:
case DHCP_STATE_REQUESTING:
case DHCP_STATE_BOUND:
break;
}
10 * USEC_PER_MSEC,
&client->timeout_resend);
if (err < 0)
goto error;
case DHCP_STATE_INIT:
if (err >= 0) {
} else {
goto error;
}
break;
case DHCP_STATE_SELECTING:
goto error;
break;
case DHCP_STATE_REQUESTING:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
goto error;
break;
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_BOUND:
break;
}
return 0;
/* Errors were dealt with when stopping the client, don't spill
errors into the event loop handler */
return 0;
}
{
int r;
if (r < 0)
goto error;
&client->timeout_resend);
if (r < 0)
client_stop(client, r);
return 0;
}
void *userdata)
{
return 0;
}
{
int r;
}
if (r < 0) {
client_stop(client, r);
return 0;
}
}
{
int r;
if (r < 0) {
client_stop(client, r);
return 0;
}
}
void *user_data)
{
switch(code) {
if (len == 4) {
}
break;
if (len >= 4)
break;
case DHCP_OPTION_SUBNET_MASK:
if (len >= 4)
break;
case DHCP_OPTION_ROUTER:
if (len >= 4)
break;
if (len >= 4) {
unsigned i;
return -ENOMEM;
for (i = 0; i < len / 4; i++) {
}
}
break;
if (len >= 2) {
}
break;
if (len == 4) {
}
break;
if (len == 4) {
}
break;
}
return 0;
}
{
return -EINVAL;
hdrlen))
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return 0;
}
{
int err;
if (err < 0)
return err;
if (!lease)
return -ENOMEM;
lease) != DHCP_OFFER)
goto error;
goto error;
return 0;
return -ENOMSG;
}
{
int r;
} else {
if (r < 0)
return r;
len -= DHCP_IP_UDP_SIZE;
}
if (!lease)
return -ENOMEM;
if (r == DHCP_NAK) {
r = DHCP_EVENT_NO_LEASE;
goto error;
}
if (r != DHCP_ACK) {
r = -ENOMSG;
goto error;
}
r = -ENOMSG;
goto error;
}
r = DHCP_EVENT_IP_CHANGE;
}
}
return r;
return r;
}
{
+ (random_u32() & 0x1fffff);
}
{
int err;
return -EINVAL;
if (next_timeout < usec)
return -EINVAL;
10 * USEC_PER_MSEC,
&client->timeout_t1);
if (err < 0)
return err;
return -EINVAL;
return -EINVAL;
if (next_timeout < usec)
return -EINVAL;
10 * USEC_PER_MSEC,
&client->timeout_t2);
if (err < 0)
return err;
if (next_timeout < usec)
return -EINVAL;
10 * USEC_PER_MSEC,
&client->timeout_expire);
if (err < 0)
return err;
return 0;
}
{
int len, r = 0, notify_event = 0;
if (len < 0)
return 0;
if (r < 0)
goto error;
case DHCP_STATE_SELECTING:
&client->timeout_resend);
if (r < 0)
goto error;
}
break;
case DHCP_STATE_REQUESTING:
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
if (r == DHCP_EVENT_NO_LEASE)
goto error;
if (r >= 0) {
else if (r != DHCP_EVENT_IP_ACQUIRE)
notify_event = r;
if (r < 0)
goto error;
if (notify_event)
}
r = 0;
break;
case DHCP_STATE_INIT:
case DHCP_STATE_INIT_REBOOT:
case DHCP_STATE_REBOOTING:
case DHCP_STATE_BOUND:
break;
}
if (r < 0 || r == DHCP_EVENT_NO_LEASE)
return client_stop(client, r);
return 0;
}
{
int r;
if (r < 0) {
client_stop(client, r);
return r;
}
}
{
}
{
return NULL;
}
{
if (!client)
return NULL;
return NULL;
}
return client;
}